Initial commit
This commit is contained in:
commit
4816c135c7
46
README.rst
Normal file
46
README.rst
Normal file
@ -0,0 +1,46 @@
|
||||
puppet-phabricator
|
||||
=================
|
||||
|
||||
A puppet module for installing and managing a phabricator instance. This is
|
||||
derived greatly from http://github.com/bloomberg/phabricator-tools
|
||||
|
||||
some notes for now:
|
||||
|
||||
This module should not manage a MySQL or a mail server itself - it should
|
||||
assume that those have been set up by other modules.
|
||||
|
||||
We want to put all config customizations into local.json and not into the
|
||||
database.
|
||||
|
||||
The initial.db file is from bloomberg, I'm not sure it's all that useful
|
||||
to folks.
|
||||
|
||||
We still need to do this in my.cnf ::
|
||||
|
||||
sql_mode=STRICT_ALL_TABLES
|
||||
ft_stopword_file=/phabricator/instances/dev/phabricator/resources/sql/stopwords.txt
|
||||
ft_min_word_len=3
|
||||
ft_boolean_syntax=' |-><()~*:""&^'
|
||||
innodb_buffer_pool_size=600M
|
||||
|
||||
then do::
|
||||
|
||||
REPAIR TABLE phabricator_search.search_documentfield;
|
||||
|
||||
I did not do: https://secure.phabricator.com/book/phabricator/article/configuring_file_domain/ yet, or really think about it.
|
||||
|
||||
I also have not made puppet do anything with::
|
||||
|
||||
sudo /phabricator/instances/dev/phabricator/bin/phd start
|
||||
|
||||
Which are the background daemons.
|
||||
|
||||
storyboard migration
|
||||
--------------------
|
||||
|
||||
The data migration script assumes a storyboard schema in the same mysql server
|
||||
as the phabricator schemas. It sets up users for everyone in storyboard
|
||||
with a password of admin. We'll be doing openid/oauth eventually, so I didn't
|
||||
spend a ton of time on that.
|
||||
|
||||
The apps that are disabled are disabled on purpose.
|
5042
files/initial.db
Normal file
5042
files/initial.db
Normal file
File diff suppressed because one or more lines are too long
158
manifests/init.pp
Normal file
158
manifests/init.pp
Normal file
@ -0,0 +1,158 @@
|
||||
# == Class: phabricator
|
||||
#
|
||||
class phabricator (
|
||||
$vhost_name = $::fqdn,
|
||||
$phab_dir = "/phabricator",
|
||||
$instance = 'dev',
|
||||
$mysql_host = 'localhost',
|
||||
$mysql_port = 3306,
|
||||
$mysql_database = 'phabricator',
|
||||
$mysql_user = 'phabricator',
|
||||
$mysql_user_password,
|
||||
$ssl_cert_file = "/etc/ssl/certs/${::fqdn}.pem",
|
||||
$ssl_key_file = "/etc/ssl/private/${::fqdn}.key",
|
||||
$ssl_chain_file = '',
|
||||
$ssl_cert_file_contents = '', # If left empty puppet will not create file.
|
||||
$ssl_key_file_contents = '', # If left empty puppet will not create file.
|
||||
$ssl_chain_file_contents = '' # If left empty puppet will not create file.
|
||||
) {
|
||||
|
||||
$instances_dir = "${phab_dir}/instances",
|
||||
$instance_dir = "${instances_dir}/${instance}"",
|
||||
|
||||
$packages = [
|
||||
"php5",
|
||||
"php5-mysql",
|
||||
"php5-gd",
|
||||
"php5-dev",
|
||||
"php5-curl",
|
||||
"php-apc",
|
||||
"php5-cli"
|
||||
]
|
||||
package { $packages:
|
||||
ensure => installed,
|
||||
}
|
||||
|
||||
if !defined(Package['git']) {
|
||||
package { 'git':
|
||||
ensure => present
|
||||
}
|
||||
}
|
||||
|
||||
file { $phab_dir:
|
||||
ensure => directory,
|
||||
}
|
||||
file { $instances_dir:
|
||||
ensure => directory,
|
||||
}
|
||||
file { $instance_dir:
|
||||
ensure => directory,
|
||||
}
|
||||
|
||||
if $ssl_cert_file_contents != '' {
|
||||
file { $ssl_cert_file:
|
||||
owner => 'root',
|
||||
group => 'root',
|
||||
mode => '0640',
|
||||
content => $ssl_cert_file_contents,
|
||||
before => Apache::Vhost[$vhost_name],
|
||||
}
|
||||
}
|
||||
|
||||
if $ssl_key_file_contents != '' {
|
||||
file { $ssl_key_file:
|
||||
owner => 'root',
|
||||
group => 'ssl-cert',
|
||||
mode => '0640',
|
||||
content => $ssl_key_file_contents,
|
||||
before => Apache::Vhost[$vhost_name],
|
||||
}
|
||||
}
|
||||
|
||||
if $ssl_chain_file_contents != '' {
|
||||
file { $ssl_chain_file:
|
||||
owner => 'root',
|
||||
group => 'root',
|
||||
mode => '0640',
|
||||
content => $ssl_chain_file_contents,
|
||||
before => Apache::Vhost[$vhost_name],
|
||||
}
|
||||
}
|
||||
|
||||
vcsrepo { "${instance_dir}/phabricator":
|
||||
ensure => latest,
|
||||
provider => git,
|
||||
revision => $commit,
|
||||
source => "https://github.com/phacility/phabricator.git",
|
||||
require => [
|
||||
File[$instance_dir],
|
||||
Package['git'],
|
||||
]
|
||||
}
|
||||
|
||||
vcsrepo { "${instance_dir}/arcanist":
|
||||
ensure => latest,
|
||||
provider => git,
|
||||
revision => $commit,
|
||||
source => "https://github.com/phacility/arcanist.git",
|
||||
require => [
|
||||
File[$instance_dir],
|
||||
Package['git'],
|
||||
]
|
||||
}
|
||||
|
||||
vcsrepo { "${instance_dir}/libphutil":
|
||||
ensure => latest,
|
||||
provider => git,
|
||||
revision => $commit,
|
||||
source => "https://github.com/phacility/libphutil.git",
|
||||
require => [
|
||||
File[$instance_dir],
|
||||
Package['git'],
|
||||
]
|
||||
}
|
||||
|
||||
file { "initial.db":
|
||||
path => "${phab_dir}/initial.db",
|
||||
source => "puppet:///modules/phabricator/initial.db",
|
||||
ensure => present,
|
||||
}
|
||||
|
||||
file {'local.json':
|
||||
path => "${instance_dir}/phabricator/conf/local/local.json",
|
||||
content => template("phabricator/local.json.erb"),
|
||||
ensure => present,
|
||||
}
|
||||
|
||||
exec { "load-initial-db":
|
||||
command => "mysql < ${phab_dir}/initial.db && ${instance_dir}/phabricator/bin/storage upgrade --force",
|
||||
unless => "${instance_dir}/phabricator/bin/storage status",
|
||||
subscribe => File["initial.db"],
|
||||
refreshonly => true,
|
||||
require => [
|
||||
Vcsrepo["$instance_dir/phabricator"],
|
||||
File["initial.db"],
|
||||
]
|
||||
}
|
||||
|
||||
exec { "update-database":
|
||||
command => "${instance_dir}/phabricator/bin/storage upgrade --force",
|
||||
refreshonly => true,
|
||||
subscribe => Vcsrepo["${instance_dir}/phabricator"],
|
||||
require => Vcsrepo["${instance_dir}/phabricator"],
|
||||
}
|
||||
|
||||
include apache
|
||||
a2mod { 'rewrite':
|
||||
ensure => present,
|
||||
}
|
||||
|
||||
apache::vhost { $vhost_name:
|
||||
port => 443,
|
||||
docroot => "${instance_dir}/phabricator/webroot",
|
||||
priority => '50',
|
||||
template => "phabricator/vhost.erb",
|
||||
ssl => true,
|
||||
}
|
||||
|
||||
}
|
509
migrate-to-phab.sql
Normal file
509
migrate-to-phab.sql
Normal file
@ -0,0 +1,509 @@
|
||||
-- (c) 2015 Hewlett-Packard Development Company, L.P.
|
||||
--
|
||||
-- Licensed under the Apache License, Version 2.0 (the "License");
|
||||
-- you may not use this file except in compliance with the License.
|
||||
-- You may obtain a copy of the License at
|
||||
--
|
||||
-- http://www.apache.org/licenses/LICENSE-2.0
|
||||
--
|
||||
-- Unless required by applicable law or agreed to in writing, software
|
||||
-- distributed under the License is distributed on an "AS IS" BASIS,
|
||||
-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
-- implied.
|
||||
-- See the License for the specific language governing permissions and
|
||||
-- limitations under the License.
|
||||
|
||||
-- Migrate data from a storyboard schema to a phabricator schema
|
||||
-- Assumes standard phabricator schema and that storyboard schema is loaded
|
||||
-- in storyboard adjacent to the phabricator schema
|
||||
|
||||
use storyboard;
|
||||
|
||||
delimiter //
|
||||
|
||||
-- phabricator uses an artificial id for everything to facilitate vertical
|
||||
-- sharding without needing cross-repo joins. You can tell they started life
|
||||
-- at Facebook
|
||||
drop function if exists make_phid //
|
||||
create function make_phid(slug varbinary(9))
|
||||
returns varbinary(30)
|
||||
BEGIN
|
||||
return concat(
|
||||
'PHID-',
|
||||
concat(slug, concat('-', left(
|
||||
concat(
|
||||
lower(conv(floor(rand() * 99999999999999), 20, 36)),
|
||||
lower(conv(floor(rand() * 99999999999999), 20, 36))
|
||||
),
|
||||
24-length(slug)
|
||||
))));
|
||||
END //
|
||||
|
||||
-- There are several places where columns need a random string of a length
|
||||
-- This is kinda lame way to make it (make a 256 character random string, then
|
||||
-- return the first len characters, but it gets the job done
|
||||
drop function if exists make_cert //
|
||||
create function make_cert(len integer)
|
||||
returns varbinary(255)
|
||||
BEGIN
|
||||
return left(
|
||||
concat(
|
||||
md5(rand()),
|
||||
md5(rand()),
|
||||
md5(rand()),
|
||||
md5(rand()),
|
||||
md5(rand()),
|
||||
md5(rand()),
|
||||
md5(rand()),
|
||||
md5(rand())
|
||||
), len);
|
||||
END //
|
||||
|
||||
-- We probably won't eventually use this, but this creates an apache style
|
||||
-- 1000 md5s in a row password hash that we can use to seed the database
|
||||
-- with a bunch of passwords
|
||||
drop function if exists make_hash //
|
||||
create function make_hash(input varbinary(255))
|
||||
returns varbinary(255)
|
||||
BEGIN
|
||||
DECLARE x int;
|
||||
DECLARE str VARBINARY(255);
|
||||
SET x = 0;
|
||||
SET str = input;
|
||||
while x < 1000 DO
|
||||
SET str = md5(str);
|
||||
SET x = x + 1;
|
||||
END WHILE;
|
||||
return str;
|
||||
END //
|
||||
delimiter ;
|
||||
|
||||
-- We're going to generate PHID values in each of the original tables
|
||||
-- so that we can inject via joins
|
||||
alter table users add column phid varbinary(64);
|
||||
alter table stories add column phid varbinary(64);
|
||||
alter table tasks add column phid varbinary(64);
|
||||
alter table tasks add column storyPHID varbinary(64);
|
||||
alter table projects add column phid varbinary(64);
|
||||
alter table project_groups add column phid varbinary(64);
|
||||
alter table comments add column phid varbinary(64);
|
||||
alter table comments add column transPHID varbinary(64);
|
||||
|
||||
-- Add PHIDs to everything
|
||||
update users set phid = make_phid('USER');
|
||||
update stories set phid = make_phid('TASK');
|
||||
update tasks set phid = make_phid('TASK');
|
||||
update projects set phid = make_phid('PROJ');
|
||||
update project_groups set phid = make_phid('PROJ');
|
||||
update comments set phid = make_phid('XCMT');
|
||||
update comments set transPHID = make_phid('XACT-TASK');
|
||||
|
||||
-- We want to track what story the task was related to without needing a
|
||||
-- backreference join
|
||||
update stories, tasks
|
||||
set tasks.storyPHID=stories.phid
|
||||
where stories.id=tasks.story_id;
|
||||
|
||||
-- There are a bunch of duplicate users in the storyboard db that are listed
|
||||
-- with @example.com email addresses. username is unique in phabricator
|
||||
update users
|
||||
set username=concat(username, '_')
|
||||
where email like '%example.com' and username not like '%_';
|
||||
|
||||
|
||||
-- Create temporary table that helps us sort stories with a single task
|
||||
-- from stories with multiple tasks
|
||||
drop table if exists task_count;
|
||||
create table task_count
|
||||
select story_id, storyPHID, count(storyPHID) as count
|
||||
from tasks group by storyPHID;
|
||||
|
||||
-- Scrub the data into something a bit more usable before we import
|
||||
alter table tasks
|
||||
modify column `priority` enum('low', 'medium', 'high', 'wishlist');
|
||||
update tasks set priority='wishlist' where priority is null;
|
||||
update tasks set status='todo' if status is NULL;
|
||||
|
||||
-- We're straight re-using the ids, so we need to make sure story and task ids
|
||||
-- don't conflict.
|
||||
-- Also, id's start with a T now, so we don't need to do as much to avoid
|
||||
-- overlap with launchpad ids
|
||||
alter table tasks drop constraint tasks_ibfk_4;
|
||||
update stories set id = id+3000 where id < 3000;
|
||||
update tasks set story_id = story_id + 3000 where story_id < 3000;
|
||||
update events set story_id = story_id + 3000 where story_id < 3000;
|
||||
update stories set id = id - 2000000 + 4000 where id >= 2000000;
|
||||
update tasks set story_id = story_id - 2000000 + 4000 where story_id >= 2000000;
|
||||
update events set story_id = story_id - 2000000 + 4000 where story_id < 2000000;
|
||||
|
||||
use phabricator_user
|
||||
|
||||
delete from user;
|
||||
delete from user_email;
|
||||
|
||||
insert into user
|
||||
select
|
||||
id,
|
||||
phid,
|
||||
username,
|
||||
if(full_name is NULL, username, full_name),
|
||||
NULL,
|
||||
NULL,
|
||||
storyboard.make_cert(32),
|
||||
'',
|
||||
unix_timestamp(created_at),
|
||||
if(updated_at is NULL, unix_timestamp(now()), unix_timestamp(updated_at)),
|
||||
NULL, 0, 0, '', storyboard.make_cert(255),
|
||||
0, 0, is_superuser, 'UTC', 1, 1,
|
||||
storyboard.make_cert(64),
|
||||
0
|
||||
from storyboard.users;
|
||||
|
||||
update user
|
||||
set passwordHash = concat(
|
||||
'md5:', storyboard.make_hash(
|
||||
concat(username, 'password', phid, passwordSalt)));
|
||||
|
||||
insert into user_email
|
||||
select
|
||||
id, phid, email, 1, 1,
|
||||
storyboard.make_cert(24),
|
||||
unix_timestamp(created_at),
|
||||
if(updated_at is NULL, unix_timestamp(now()), unix_timestamp(updated_at))
|
||||
from storyboard.users;
|
||||
|
||||
|
||||
use phabricator_maniphest
|
||||
|
||||
-- priorities
|
||||
-- 100 = Unbreak Now!
|
||||
-- 90 = Needs Triage
|
||||
-- 80 = High
|
||||
-- 50 = Normal
|
||||
-- 25 = Low
|
||||
-- 0 = Wishlist
|
||||
|
||||
delete from maniphest_task;
|
||||
delete from edge;
|
||||
delete from maniphest_transaction;
|
||||
delete from maniphest_transaction_comment;
|
||||
|
||||
-- stories with one task get collapsed in a single new task
|
||||
insert into maniphest_task
|
||||
select
|
||||
s.id, -- id
|
||||
s.phid, -- phid
|
||||
if(s.creator_id is NULL, '', s.creator_id), -- second pass authorPHID
|
||||
if(t.assignee_id is NULL, NULL, t.assignee_id), -- second pass ownerPHID
|
||||
'', -- attached
|
||||
case t.status -- status
|
||||
when 'todo' then 'open'
|
||||
when 'inprogress' then 'inprogress'
|
||||
when 'invalid' then 'invalid'
|
||||
when 'review' then 'review'
|
||||
when 'merged' then 'merged'
|
||||
when 'invalid' then 'invalid'
|
||||
end,
|
||||
case t.priority -- priority
|
||||
when 'high' then 80
|
||||
when 'medium' then 50
|
||||
when 'low' then 25
|
||||
when 'wishlist' then 0
|
||||
end,
|
||||
s.title, -- title
|
||||
s.title, -- originalTitle
|
||||
s.description, -- description
|
||||
unix_timestamp(s.created_at), -- dateCreated
|
||||
if(t.updated_at is NULL, unix_timestamp(t.created_at), unix_timestamp(t.updated_at)), -- dateUpdated
|
||||
'[]', -- update in second pass - projectPHIDs
|
||||
storyboard.make_cert(20), -- mailKey
|
||||
NULL, -- ownerOrdering
|
||||
NULL, -- originalEmailSource
|
||||
0, -- subpriority
|
||||
'users', -- viewPolicy
|
||||
'users' -- editPolicy
|
||||
from storyboard.stories s, storyboard.tasks t, storyboard.task_count c
|
||||
where s.id = t.story_id and c.story_id=s.id and c.count = 1;
|
||||
|
||||
-- For stories with more than one task, each task becomes a new task
|
||||
insert into maniphest_task
|
||||
select
|
||||
t.id,
|
||||
t.phid,
|
||||
if(t.creator_id is NULL, '', t.creator_id), -- u.phid,
|
||||
if(t.assignee_id is NULL, NULL, t.assignee_id), -- second pass
|
||||
'',
|
||||
case t.status
|
||||
when 'todo' then 'open'
|
||||
when 'inprogress' then 'inprogress'
|
||||
when 'invalid' then 'invalid'
|
||||
when 'review' then 'review'
|
||||
when 'merged' then 'merged'
|
||||
when 'invalid' then 'invalid'
|
||||
end,
|
||||
case t.priority
|
||||
when 'high' then 80
|
||||
when 'medium' then 50
|
||||
when 'low' then 25
|
||||
when 'wishlist' then 0
|
||||
end,
|
||||
t.title,
|
||||
t.title,
|
||||
'',
|
||||
unix_timestamp(t.created_at),
|
||||
if(t.updated_at is NULL, unix_timestamp(t.created_at), unix_timestamp(t.updated_at)),
|
||||
'[]', -- update in second pass
|
||||
storyboard.make_cert(20),
|
||||
NULL,
|
||||
NULL,
|
||||
0,
|
||||
'users',
|
||||
'users'
|
||||
from storyboard.stories s, storyboard.tasks t, storyboard.task_count c
|
||||
where s.id = t.story_id and c.story_id=s.id and c.count > 1;
|
||||
|
||||
-- For stories with more than one task, each story also becomes a task, but
|
||||
-- it doesn't have a project associated with it
|
||||
insert into maniphest_task
|
||||
select
|
||||
s.id,
|
||||
s.phid,
|
||||
if(s.creator_id is NULL, '', s.creator_id), -- u.phid,
|
||||
NULL,
|
||||
'',
|
||||
'open',
|
||||
50,
|
||||
s.title,
|
||||
s.title,
|
||||
s.description,
|
||||
unix_timestamp(s.created_at),
|
||||
if(s.updated_at is NULL, unix_timestamp(s.created_at), unix_timestamp(s.updated_at)),
|
||||
'[]',
|
||||
storyboard.make_cert(20),
|
||||
NULL,
|
||||
NULL,
|
||||
0,
|
||||
'users',
|
||||
'users'
|
||||
from storyboard.stories s, storyboard.task_count c, storyboard.users u
|
||||
where c.story_id=s.id and c.count > 1
|
||||
and u.id = s.creator_id;
|
||||
|
||||
-- Set the author and owner PHIDs as a second pass to avoid really crazy
|
||||
-- join semantics above. It could be done ... but why?
|
||||
update maniphest_task, storyboard.users
|
||||
set maniphest_task.authorPHID=storyboard.users.phid
|
||||
where maniphest_task.authorPHID=storyboard.users.id;
|
||||
|
||||
update maniphest_task, storyboard.users
|
||||
set maniphest_task.ownerPHID=storyboard.users.phid
|
||||
where maniphest_task.ownerPHID=storyboard.users.id;
|
||||
|
||||
-- Releationships are edges in a DAG, so set up relationships between
|
||||
-- tasks with their owners and authors in both directions
|
||||
insert into edge
|
||||
select authorPHID, 22, phid, 0, 0, NULL from maniphest_task;
|
||||
insert into edge
|
||||
select phid, 21, authorPHID, 0, 0, NULL from maniphest_task;
|
||||
replace into edge
|
||||
select ownerPHID, 22, phid, 0, 0, NULL from maniphest_task where ownerPHID is not null;
|
||||
replace into edge
|
||||
select phid, 21, ownerPHID, 0, 0, NULL from maniphest_task where ownerPHID is not null;
|
||||
|
||||
-- Comments have two parts - the first is an entry in the transaction table
|
||||
-- indicating that a comment happened and associating the comment with the task
|
||||
insert into maniphest_transaction
|
||||
select
|
||||
c.id, -- id
|
||||
c.transPHID, -- phid
|
||||
u.phid, -- authorPHID
|
||||
s.phid, -- objectPHID
|
||||
'public', -- viewPolicy
|
||||
u.phid, -- editPolicy
|
||||
c.phid, -- commentPHID
|
||||
1, -- commentVersion
|
||||
'core:comment', -- transactionType
|
||||
'null', -- oldValue
|
||||
'null', -- newValue
|
||||
'{"source":"web"}', -- contentSource
|
||||
'[]', -- metadata
|
||||
unix_timestamp(c.created_at), -- dateCreated
|
||||
if(c.updated_at is null, unix_timestamp(c.created_at), unix_timestamp(c.updated_at)) -- dateUpdated
|
||||
from storyboard.comments c, storyboard.events e, storyboard.stories s, storyboard.users u
|
||||
where c.id = e.comment_id and s.id = e.story_id
|
||||
and e.event_type='user_comment' and s.creator_id = u.id;
|
||||
|
||||
-- The second part is the comment payload itself
|
||||
insert into maniphest_transaction_comment
|
||||
select
|
||||
c.id, -- id
|
||||
c.phid, -- phid
|
||||
c.transPHID, -- transactionPHID
|
||||
u.phid, -- author
|
||||
'public', -- viewPolicy
|
||||
u.phid, -- editPolicy
|
||||
1, --
|
||||
if(c.content is NULL, '', c.content),
|
||||
'{"source":"web"}',
|
||||
if(c.is_active, false, true),
|
||||
unix_timestamp(c.created_at),
|
||||
if(c.updated_at is null, unix_timestamp(c.created_at), unix_timestamp(c.updated_at))
|
||||
from storyboard.comments c, storyboard.events e, storyboard.stories s, storyboard.users u
|
||||
where c.id = e.comment_id and s.id = e.story_id
|
||||
and e.event_type='user_comment' and s.creator_id = u.id;
|
||||
|
||||
|
||||
-- We go back over to storyboard repo to create some calculated tables to
|
||||
-- help us do project mapping. We needed to run in the tasks first so that
|
||||
-- we can easily tell which tasks we need projects for.
|
||||
use storyboard
|
||||
|
||||
drop table if exists task_project;
|
||||
drop table if exists task_project_list;
|
||||
drop table if exists task_project_grouping;
|
||||
|
||||
-- This is a table mapping tasks to every project it's associated with in a
|
||||
-- clean and easy fashion for later
|
||||
create table task_project
|
||||
select t.phid as task_phid, p.phid as project_phid, t.project_id as project_id
|
||||
from tasks t, phabricator_maniphest.maniphest_task m, projects p
|
||||
where m.phid=t.phid and t.project_id is not null and t.project_id = p.id;
|
||||
-- We also add project groups to this table
|
||||
insert into task_project
|
||||
select t.task_phid, g.phid, t.project_id
|
||||
from task_project t, project_groups g, project_group_mapping m
|
||||
where t.project_id = m.project_id and g.id = m.project_group_id;
|
||||
|
||||
-- based on that table, we make a new table so that we can modify and create
|
||||
-- the comma-separated json list
|
||||
create table task_project_list
|
||||
select task_phid, project_phid from task_project;
|
||||
update task_project_list set project_phid = concat('"', project_phid, '"');
|
||||
-- use group_concat to get a row for each task and then a comma-sep list of
|
||||
-- projects. Since we wrapped them all in " above, this will be comma-sep and
|
||||
-- quoted
|
||||
create table task_project_grouping
|
||||
select task_phid, group_concat(project_phid) as phids
|
||||
from task_project_list
|
||||
group by task_phid;
|
||||
-- Finally, wrap the results in [ and ]
|
||||
update task_project_grouping set phids = concat('[', phids, ']');
|
||||
|
||||
-- We need to map tasks to dependent tasks. Lucky for us, Storyboard only
|
||||
-- groks one level of this. Make a table for easy of importing later
|
||||
drop table if exists task_subtask;
|
||||
create table task_subtask
|
||||
select tasks.phid, tasks.storyPHID
|
||||
from tasks, phabricator_maniphest.maniphest_task
|
||||
where tasks.phid = phabricator_maniphest.maniphest_task.phid;
|
||||
|
||||
-- Grab a PHID to use as an author for the projects.
|
||||
-- TODO: Make a system/bot account that we can use as the "owner" of these
|
||||
-- projects. But I'll do for now.
|
||||
select phid into @author_phid from users where username='mordred';
|
||||
|
||||
use phabricator_project
|
||||
|
||||
delete from project;
|
||||
insert into project
|
||||
select
|
||||
id, -- id
|
||||
name, -- name
|
||||
phid, -- phid
|
||||
@author_phid,
|
||||
unix_timestamp(created_at),
|
||||
if(updated_at is NULL, unix_timestamp(created_at), unix_timestamp(updated_at)),
|
||||
0, -- status
|
||||
'[]', -- subprojectPHIDs
|
||||
concat(replace(lower(name), '/', '_'), '/'),
|
||||
'users',
|
||||
'users',
|
||||
'users',
|
||||
0,
|
||||
NULL,
|
||||
'fa-briefcase',
|
||||
'blue'
|
||||
from storyboard.projects;
|
||||
insert into project
|
||||
select
|
||||
id + 1000,
|
||||
name,
|
||||
phid,
|
||||
@author_phid,
|
||||
unix_timestamp(created_at),
|
||||
if(updated_at is NULL, unix_timestamp(created_at), unix_timestamp(updated_at)),
|
||||
0, -- status
|
||||
'[]', -- subprojectPHIDs
|
||||
concat(replace(lower(name), '/', '_'), '/'),
|
||||
'users',
|
||||
'users',
|
||||
'users',
|
||||
0,
|
||||
NULL,
|
||||
'fa-briefcase',
|
||||
'blue'
|
||||
from storyboard.project_groups;
|
||||
|
||||
delete from project_slug;
|
||||
insert into project_slug
|
||||
select
|
||||
id,
|
||||
phid,
|
||||
replace(lower(name), '/', '_'),
|
||||
dateCreated,
|
||||
dateModified
|
||||
from project;
|
||||
|
||||
|
||||
-- insert into project_datasourcetoken (need to split name on - and do a row for each value) for typeahead search in boxes
|
||||
insert into project_datasourcetoken (projectID, token)
|
||||
SELECT p.id, SUBSTRING_INDEX(SUBSTRING_INDEX(
|
||||
p.name, '-', n.n), '-', -1) value
|
||||
FROM project p CROSS JOIN (
|
||||
SELECT a.N + b.N * 10 + 1 n
|
||||
FROM
|
||||
(SELECT 0 AS N UNION ALL SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3 UNION ALL SELECT 4 UNION ALL SELECT 5 UNION ALL SELECT 6 UNION ALL SELECT 7 UNION ALL SELECT 8 UNION ALL SELECT 9) a,
|
||||
(SELECT 0 AS N UNION ALL SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3 UNION ALL SELECT 4 UNION ALL SELECT 5 UNION ALL SELECT 6 UNION ALL SELECT 7 UNION ALL SELECT 8 UNION ALL SELECT 9) b
|
||||
ORDER BY n
|
||||
) n
|
||||
WHERE n.n <= 1 + (LENGTH(p.name) - LENGTH(REPLACE(p.name, '-', '')))
|
||||
ORDER BY value;
|
||||
|
||||
-- More DAG magic - this will map a project to a task in the projects DB
|
||||
insert into edge
|
||||
select
|
||||
project_phid, 42, task_phid, 0, 0, NULL
|
||||
from storyboard.task_project;
|
||||
|
||||
use phabricator_maniphest
|
||||
|
||||
-- We have projects now, so inject them into the name mapping table in the
|
||||
-- bug system
|
||||
insert into maniphest_nameindex
|
||||
select id, phid, name from phabricator_project.project;
|
||||
update maniphest_task t, storyboard.task_project_grouping g
|
||||
set t.projectPHIDs = g.phids
|
||||
where t.phid = g.task_phid;
|
||||
|
||||
-- Associate tasks with projects from the task side
|
||||
insert into edge
|
||||
select
|
||||
task_phid, 41, project_phid, 0, 0, NULL
|
||||
from storyboard.task_project;
|
||||
|
||||
-- Relationship
|
||||
-- If the task phid matches a storyboard task.phid, then it's a
|
||||
-- subtask, and we should take the storyPHID from that storyboard.task
|
||||
-- and use it to create the parent/child edges
|
||||
-- Create Parent Edge:
|
||||
-- src = story.phid, type = 3, dst = task.phid
|
||||
-- Create Child Backref:
|
||||
-- src = task.phid, type = 4, dst = story.phid
|
||||
insert into edge
|
||||
select
|
||||
storyPHID, 3, phid, 0, 0, NULL
|
||||
from storyboard.task_subtask;
|
||||
insert into edge
|
||||
select
|
||||
phid, 4, storyPHID, 0, 0, NULL
|
||||
from storyboard.task_subtask;
|
51
templates/local.json.erb
Normal file
51
templates/local.json.erb
Normal file
@ -0,0 +1,51 @@
|
||||
{
|
||||
"storage.upload-size-limit": "10M",
|
||||
"config.ignore-issues": {
|
||||
"daemons.need-restarting": true,
|
||||
"security.security.alternate-file-domain": true
|
||||
},
|
||||
"pygments.enabled": true,
|
||||
"repository.default-local-path": "/var/lib/git",
|
||||
"phabricator.serious-business": true,
|
||||
"phabricator.base-uri": "https://<%= @vhost_name %>",
|
||||
"phabricator.uninstalled-applications": {
|
||||
"PhabricatorDifferentialApplication": true,
|
||||
"PhabricatorPhrictionApplication": true,
|
||||
"PhabricatorDiffusionApplication": true,
|
||||
"PhabricatorConpherenceApplication": true,
|
||||
"PhabricatorAuditApplication": true,
|
||||
"PhabricatorTokensApplication": true,
|
||||
"PhabricatorLegalpadApplication": true
|
||||
},
|
||||
"maniphest.statuses": {
|
||||
"open": {
|
||||
"name": "Open",
|
||||
"special": "default"
|
||||
},
|
||||
"inprogress": {
|
||||
"name": "In Progress"
|
||||
},
|
||||
"review": {
|
||||
"name": "In Review"
|
||||
},
|
||||
"merged": {
|
||||
"name": "Merged",
|
||||
"name.full": "Closed, Merged",
|
||||
"closed": true,
|
||||
"special": "closed"
|
||||
},
|
||||
"invalid": {
|
||||
"name": "Invalid",
|
||||
"name.full": "Closed, Invalid",
|
||||
"closed": true
|
||||
},
|
||||
"duplicate": {
|
||||
"name": "Duplicate",
|
||||
"name.full": "Closed, Duplicate",
|
||||
"transaction.icon": "fa-times",
|
||||
"special": "duplicate",
|
||||
"closed": true
|
||||
}
|
||||
},
|
||||
"phabricator.timezone": "UTC"
|
||||
}
|
61
templates/vhost.erb
Normal file
61
templates/vhost.erb
Normal file
@ -0,0 +1,61 @@
|
||||
<VirtualHost *:80>
|
||||
ServerAdmin noc@openstack.org
|
||||
ServerName <%= @vhost_name %>
|
||||
|
||||
DocumentRoot /var/www
|
||||
<Directory />
|
||||
Options FollowSymLinks
|
||||
AllowOverride None
|
||||
</Directory>
|
||||
<Directory /var/www/>
|
||||
Options Indexes FollowSymLinks MultiViews
|
||||
AllowOverride None
|
||||
Order allow,deny
|
||||
allow from all
|
||||
</Directory>
|
||||
|
||||
RewriteEngine on
|
||||
RewriteCond %{SERVER_PORT} !^443$
|
||||
RewriteRule ^/(.*)$ https://<%= @vhost_name %>/$1 [L,R]
|
||||
|
||||
ErrorLog /var/log/apache2/phabricator-error.log
|
||||
|
||||
# Possible values include: debug, info, notice, warn, error, crit,
|
||||
# alert, emerg.
|
||||
LogLevel warn
|
||||
|
||||
CustomLog /var/log/apache2/phabricator-access.log combined
|
||||
ServerSignature Off
|
||||
|
||||
</VirtualHost>
|
||||
<VirtualHost *:443>
|
||||
ServerAdmin noc@openstack.org
|
||||
ServerName <%= @vhost_name %>
|
||||
|
||||
SSLEngine on
|
||||
SSLProtocol All -SSLv2 -SSLv3
|
||||
SSLCertificateFile <%= @ssl_cert_file %>
|
||||
SSLCertificateKeyFile <%= @ssl_key_file %>
|
||||
<% if @ssl_chain_file != "" %>
|
||||
SSLCertificateChainFile <%= @ssl_chain_file %>
|
||||
<% end %>
|
||||
|
||||
DocumentRoot <%= @docroot %>
|
||||
<Directory />
|
||||
Options FollowSymLinks
|
||||
AllowOverride None
|
||||
</Directory>
|
||||
<Directory <%= @docroot %>>
|
||||
Options Indexes FollowSymLinks MultiViews
|
||||
AllowOverride None
|
||||
Order allow,deny
|
||||
allow from all
|
||||
</Directory>
|
||||
|
||||
RewriteEngine on
|
||||
RewriteRule ^/rsrc/(.*) - [L,QSA]
|
||||
RewriteRule ^/favicon.ico - [L,QSA]
|
||||
RewriteRule ^(.*)$ /index.php?__path__=$1 [B,L,QSA]
|
||||
|
||||
SetEnv PHABRICATOR_ENV production
|
||||
</VirtualHost>
|
17
things-I-did
Normal file
17
things-I-did
Normal file
@ -0,0 +1,17 @@
|
||||
# I started from git clone https://github.com/emonty/phabricator-tools.git
|
||||
|
||||
sudo puppet apply phabricator-tools/vagrant/puppet/phabricator/manifests/default.pp --modulepath phabricator-tools/vagrant/puppet
|
||||
|
||||
sudo cp ~/local.json /phabricator/instances/dev/phabricator/conf/local/local.json
|
||||
|
||||
sudo /phabricator/instances/dev/phabricator/bin/phd start
|
||||
|
||||
|
||||
Then run:
|
||||
|
||||
REPAIR TABLE phabricator_search.search_documentfield;
|
||||
|
||||
sudo mkdir /var/lib/git
|
||||
apt-get install exim4 python-pygments
|
||||
|
||||
# I did not do: https://secure.phabricator.com/book/phabricator/article/configuring_file_domain/
|
Loading…
x
Reference in New Issue
Block a user