Remove unused gerrit puppet things

We ain't using em.

Change-Id: I4ce9188a6b6a7e6a670e61bb17ab07e890faebcf
This commit is contained in:
Monty Taylor 2020-03-19 17:15:35 -05:00
parent 711295e918
commit 5468f49254
18 changed files with 12 additions and 2141 deletions

View File

@ -17,14 +17,13 @@ At a Glance
===========
:Hosts:
* http://review.opendev.org
* http://review-dev.openstack.org
:Puppet:
* https://opendev.org/opendev/puppet-gerrit
* :git_file:`modules/openstack_project/manifests/review.pp`
* :git_file:`modules/openstack_project/manifests/review_dev.pp`
* https://review.opendev.org
* https://review-dev.opendev.org
:Ansbile:
* :git_file:`playbooks/service-review.yaml`
* :git_file:`playbooks/roles/gerrit`
:Configuration:
* :git_file:`modules/openstack_project/templates/review.projects.ini.erb`
* :git_file:`playbooks/roles/gerrit/templates/projects.ini.j2`
* :config:`gerrit/projects.yaml`
:Projects:
* http://code.google.com/p/gerrit/
@ -37,9 +36,8 @@ At a Glance
Installation
============
Gerrit is installed and configured by Puppet, including specifying the
exact Java WAR file that is used. See :ref:`sysadmin` for how Puppet
is used to manage OpenStack infrastructure systems.
Gerrit is installed and configured by Ansible, using a Docker container
that contains the Java WAR file.
Cinder Volumes
--------------
@ -103,7 +101,7 @@ account name and add ssh keys - you'll need those.
Once you've created your groups you should create the
``openstack-project-creator`` account by hand (the account name is
referenced from
:git_file:`modules/openstack_project/templates/review.projects.ini.erb`)
:git_file:`playbooks/roles/gerrit/templates/projects.ini.j2`)
using::
cat $pubkey | ssh -p 29418 $USER@$HOST gerrit create-account \
@ -152,21 +150,6 @@ After the team has been added, project will start replicating successfully
to GitHub.
Auto Review Expiry
==================
Puppet automatically installs a daily cron job called ``expire-old-reviews``
onto the Gerrit servers. This script follows two rules:
#. If the review hasn't been touched in 2 weeks, mark as abandoned.
#. If there is a negative review and it hasn't been touched in 1 week, mark as
abandoned.
If your review gets touched by either of these rules, it is possible to
unabandon a review on the Gerrit web interface.
This process is managed by the :ref:`jeepyb` openstack-infra project.
Gerrit IRC Bot
==============
@ -446,15 +429,8 @@ To rename a project:
Add this file to the ``renames/`` directory in the
``opendev/project-config`` repository.
#. An hour in advance of the maintenance (if possible), stop puppet
runs on the puppetmaster to prevent early application of
configuration changes::
sudo crontab -u root -e
Comment out the crontab entries. Use ps to make sure that a run is
not currently in progress. When it finishes, make sure the entry
has not been added back to the crontab.
#. An hour in advance of the maintenance (if possible), put
``review01.opendev.org`` into the emergency file on bridge.
#. Run the ansible rename repos playbook, passing in the path to your yaml
file::
@ -466,9 +442,7 @@ To rename a project:
#. Rename the project or transfer ownership in GitHub
#. Re-enable puppet runs on the puppetmaster::
sudo crontab -u root -e
#. Remove ``review01.opendev.org`` from the emergency file.
.. warning::
Wait for the ``project-config`` changes to merge before

View File

@ -76,7 +76,6 @@ INTEGRATION_MODULES["$OPENSTACK_GIT_ROOT/opendev/puppet-elasticsearch"]="origin/
INTEGRATION_MODULES["$OPENSTACK_GIT_ROOT/opendev/puppet-ethercalc"]="origin/master"
INTEGRATION_MODULES["$OPENSTACK_GIT_ROOT/opendev/puppet-exim"]="origin/master"
INTEGRATION_MODULES["$OPENSTACK_GIT_ROOT/opendev/puppet-germqtt"]="origin/master"
INTEGRATION_MODULES["$OPENSTACK_GIT_ROOT/opendev/puppet-gerrit"]="origin/master"
INTEGRATION_MODULES["$OPENSTACK_GIT_ROOT/opendev/puppet-gerritbot"]="origin/master"
INTEGRATION_MODULES["$OPENSTACK_GIT_ROOT/opendev/puppet-github"]="origin/master"
INTEGRATION_MODULES["$OPENSTACK_GIT_ROOT/opendev/puppet-grafyaml"]="origin/master"

View File

@ -1,179 +0,0 @@
body {color: #000 !important;}
a,a:visited {color: #264D69 !important; text-decoration: none;}
a:hover {color: #000 !important; text-decoration: underline}
a.gwt-InlineHyperlink {background: none !important}
#openstack-logo img { height: 40px; }
#openstack-logo h1 { margin: 20px; }
#gerrit_header #openstack-logo h1 { margin: 20px 0 0 0; }
#gerrit_header {display: block !important; position: relative; top: -60px; margin-bottom: -60px; width: 200px; padding-left: 17px}
#gerrit_header h1 {font-family: 'PT Sans', sans-serif; font-weight: normal; letter-spacing: -1px}
#gerrit_topmenu {background: none; position:relative; top: 0px; left: 220px; margin-right: 220px}
#gerrit_topmenu tbody tr td table {border: 0}
#gerrit_topmenu tbody tr td table.gwt-TabBar {color: #353535; border-bottom: 1px solid #C5E2EA;}
#gerrit_topmenu .gwt-Button {padding: 3px 6px}
.gwt-TabBarItem-selected {color: #CF2F19 !important; border-bottom: 3px solid #CF2F19;}
.gwt-TabBarItem {color: #353535; border-right: 0 !important}
.gwt-TabBar .gwt-TabBarItem, .gwt-TabBar .gwt-TabBarRest, .gwt-TabPanelBottom {background: 0 !important;}
#gerrit_topmenu .searchTextBox {width: 250px}
#change_infoTable {
border-collapse: collapse;
}
#change_infoTable th {
padding: 2px 4px 2px 6px;
background-color: #eef3f5;
font-style: italic;
text-align: left;
}
#change_infoTable td {
padding: 2px 4px 2px 6px;
border-bottom: 1px solid #eef3f5;
border-right: 1px solid #eef3f5;
}
#change_infoTable tr:last-child td {
border: none;
}
.com-google-gerrit-client-change-ChangeScreen_BinderImpl_GenCss_style-cs2 {
padding-left: 10px;
padding-right: 10px;
}
/* Section headers */
.com-google-gerrit-client-change-ChangeScreen_BinderImpl_GenCss_style-cs2
.com-google-gerrit-client-change-ChangeScreen_BinderImpl_GenCss_style-headerLine,
.com-google-gerrit-client-change-ChangeScreen_BinderImpl_GenCss_style-cs2
.com-google-gerrit-client-change-ChangeScreen_BinderImpl_GenCss_style-sectionHeader {
margin-top: 10px !important;
margin-bottom: 10px !important;
}
/* Commit message */
.com-google-gerrit-client-change-ChangeScreen_BinderImpl_GenCss_style-cs2
.com-google-gerrit-client-change-CommitBox_BinderImpl_GenCss_style-text::first-line {
font-weight: bold !important;
}
/* Commit metadata */
.com-google-gerrit-client-change-ChangeScreen_BinderImpl_GenCss_style-cs2
.com-google-gerrit-client-change-ChangeScreen_BinderImpl_GenCss_style-commitColumn
.com-google-gerrit-client-change-CommitBox_BinderImpl_GenCss_style-header th {
padding: 2px 4px 2px 6px;
background-color: #eef3f5;
font-style: italic;
text-align: left;
}
.com-google-gerrit-client-change-ChangeScreen_BinderImpl_GenCss_style-cs2
.com-google-gerrit-client-change-ChangeScreen_BinderImpl_GenCss_style-commitColumn
.com-google-gerrit-client-change-CommitBox_BinderImpl_GenCss_style-header td {
border-bottom: 1px solid #eef3f5;
padding: 2px 4px 2px 6px;
}
.com-google-gerrit-client-change-ChangeScreen_BinderImpl_GenCss_style-cs2
.com-google-gerrit-client-change-ChangeScreen_BinderImpl_GenCss_style-commitColumn
.com-google-gerrit-client-change-CommitBox_BinderImpl_GenCss_style-header td:last-child {
border-right: 1px solid #eef3f5;
}
/* increase the middle info column to fill empty space (for wide
monitors), but ensure there is a sufficient lower bound to kick in
horiz scroll bar. This will relieve the preasure on the hideci test
results. */
.com-google-gerrit-client-change-ChangeScreen_BinderImpl_GenCss_style-infoColumn {
width: 100% !important;
min-width: 400px;
}
/* Review history */
.com-google-gerrit-client-change-ChangeScreen_BinderImpl_GenCss_style-cs2
.com-google-gerrit-client-change-Message_BinderImpl_GenCss_style-name {
font-weight: bold !important;
}
.com-google-gerrit-client-change-ChangeScreen_BinderImpl_GenCss_style-cs2
.com-google-gerrit-client-change-Message_BinderImpl_GenCss_style-messageBox {
width: inherit;
max-width: 1168px;
}
.comment_test_name {
display: inline-block;
*display: inline;
*zoom: 1;
width: auto !important;
width: 25em;
min-width: 20em;
padding-bottom: 2pt;
}
.comment_test_result {
}
.result_SUCCESS {
color: #007f00;
}
.result_FAILURE, .result_POST_FAILURE, .result_TIMED_OUT, .result_RETRY_LIMIT, .result_DISK_FULL {
color: #cf2f19;
}
.result_UNSTABLE, .result_WARNING {
color: #e39f00;
}
.result_LOST {
color: #e39f00;
}
li.comment_test {list-style-type: none; }
/* this is for support of 'Display Person Name In Review Category' */
.cAPPROVAL {
max-width: 100px;
overflow: hidden;
}
/* fixes to make this like old gerrit */
.changeTable td.dataCell {
height: 1em;
}
/* don't make the non voting stand out more than the voting */
table.infoTable td.notVotable,
.changeTable td.dataCell.labelNotApplicable {
background: inherit;
}
.test_result_table {
border-collapse: collapse;
}
.test_result_table tr {
border-left: 1px solid #eef3f5;
border-right: 1px solid #eef3f5;
}
.test_result_table td.header {
background-color: #eef3f5;
}
.test_result_table td {
padding: 2px 4px 2px 6px;
border: 1px solid #eef3f5;
}
.addMemberTextBox {
width: 20em;
}
/* css attribute selector to make -1s show up red in new screen */
[title="Doesn't seem to work"],
[title="This patch needs further work before it can be merged"] {
color: red;
}

View File

@ -1,6 +0,0 @@
<div id="openstack-logo">
<script type="text/javascript" src="static/jquery.js" />
<script type="text/javascript" src="static/jquery-visibility.js"></script>
<script type="text/javascript" src="static/hideci.js" />
<a href="/"><h1><img src="static/title.svg" style="vertical-align:middle;" /></h1></a>
</div>

View File

@ -1,4 +0,0 @@
#!/bin/sh
# Use timeout to kill any process running longer than 10 minutes.
timeout -k 2m 10m /usr/local/bin/update-bug change-abandoned "$@"

View File

@ -1,5 +0,0 @@
#!/bin/sh
# Use timeout to kill any process running longer than 10 minutes.
timeout -k 2m 10m /usr/local/bin/update-bug change-merged "$@"
timeout -k 2m 10m /usr/local/bin/notify-impact change-merged "$@" --impact DocImpact --dest-address 'openstack-docs@lists.openstack.org' --config /home/gerrit2/review_site/hooks/notify_impact.yaml

View File

@ -1,259 +0,0 @@
<html><body><div>
<h1>
OpenStack Project Individual Contributor License Agreement
</h1>
<!--
This is the current OpenStack Project Individual Contributor License Agreement
reformatted for HTML from the original "RevisedCLA.doc" with SHA1 sum
0467dd893d276cefde614e063a363b995d67e5ee provided by Jonathan Bryce, Executive
Director on behalf of The OpenStack Foundation on Monday, January 7, 2013. No
textual content was changed except to replace quote marks with their strict
ASCII equivalents, add the original LLC CLA text as a block quote, and restore
a previously inapplicable statement (sentence #2 of paragraph #2) adapted from
the Apache Software Foundation ICLA at his direction.
-->
<p><em>
In order to clarify the intellectual property license granted with
Contributions from any person or entity, the OpenStack Project (the "Project")
must have a Contributor License Agreement ("Agreement") on file that has been
signed by each Contributor, indicating agreement to the license terms below.
This license is for your protection as a Contributor as well as the protection
of OpenStack Foundation as Project manager (the "Project Manager") and the
Project users; it does not change your rights to use your own Contributions for
any other purpose.
</em></p>
<p><em>
You accept and agree to the following terms and conditions for Your present and
future Contributions submitted to the Project Manager. In return, the Project
Manager shall not use Your Contributions in a way that is contrary to the
public benefit or inconsistent with its nonprofit status and bylaws in effect
at the time of the Contribution. Except for the license granted herein to the
Project Manager and recipients of software distributed by the Project Manager,
You reserve all right, title, and interest in and to Your Contributions.
</em></p>
<ol>
<li><p><strong>
Definitions.
</strong>
"You" (or "Your") shall mean the copyright owner or legal entity authorized by
the copyright owner that is making this Agreement with the Project Manager. For
legal entities, the entity making a Contribution and all other entities that
control, are controlled by, or are under common control with that entity are
considered to be a single Contributor. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the direction or
management of such entity, whether by contract or otherwise, or (ii) ownership
of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial
ownership of such entity. "Contribution" shall mean any original work of
authorship, including any modifications or additions to an existing work, that
is intentionally submitted by You to the Project Manager for inclusion in, or
documentation of, any of the projects owned or managed by the Project Manager
(the "Work"). For the purposes of this definition, "submitted" means any form of
electronic, verbal, or written communication sent to the Project Manager or its
representatives, including but not limited to communication on electronic
mailing lists, source code control systems, and issue tracking systems that are
managed by, or on behalf of, the Project Manager for the purpose of discussing
and improving the Work, but excluding communication that is conspicuously marked
or otherwise designated in writing by You as "Not a Contribution."
</p></li>
<li><p><strong>
Grant of Copyright License.
</strong>
Subject to the terms and conditions of this Agreement, You hereby grant to the
Project Manager and to recipients of software distributed by the Project
Manager a perpetual, worldwide, non-exclusive, no-charge, royalty-free,
irrevocable copyright license to reproduce, prepare derivative works of,
publicly display, publicly perform, sublicense, and distribute Your
Contributions and such derivative works.
</p></li>
<li><p><strong>
Grant of Patent License.
</strong>
Subject to the terms and conditions of this Agreement, You hereby grant to the
Project Manager and to recipients of software distributed by the Project
Manager a perpetual, worldwide, non-exclusive, no-charge, royalty-free,
irrevocable (except as stated in this section) patent license to make, have
made, use, offer to sell, sell, import, and otherwise transfer the Work, where
such license applies only to those patent claims licensable by You that are
necessarily infringed by Your Contribution(s) alone or by combination of Your
Contribution(s) with the Work to which such Contribution(s) was submitted. If
any entity institutes patent litigation against You or any other entity
(including a cross-claim or counterclaim in a lawsuit) alleging that Your
Contribution, or the Work to which You have contributed, constitutes direct or
contributory patent infringement, then any patent licenses granted to that
entity under this Agreement for that Contribution or Work shall terminate as of
the date such litigation is filed.
</p></li>
<li><p>
You represent that you are legally entitled to grant the above license. If your
employer(s) has rights to intellectual property that you create that includes
your Contributions, You represent that you have received permission to make
Contributions on behalf of that employer, that your employer has waived such
rights for your Contributions to the Project Manager, or that your employer has
executed a separate Corporate Contributor License Agreement with the Project
Manager.
</p></li>
<li><p>
You represent that each of Your Contributions is Your original creation (see
Section 7 for submissions on behalf of others). You represent that Your
Contribution submissions include complete details of any third-party license or
other restriction (including, but not limited to, related patents and
trademarks) of which you are personally aware and which are associated with any
part of Your Contributions.
</p></li>
<li><p>
You are not expected to provide support for Your Contributions, except to the
extent You desire to provide support. You may provide support for free, for a
fee, or not at all. Unless required by applicable law or agreed to in writing,
You provide Your Contributions on an "AS IS" BASIS, WITHOUT WARRANTIES OR
CONDITIONS OF ANY KIND, either express or implied, including, without
limitation, any warranties or conditions of TITLE, NONINFRINGEMENT,
MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE.
</p></li>
<li><p>
Should You wish to submit work that is not Your original creation, You may
submit it to the Project Manager separately from any Contribution, identifying
the complete details of its source and of any license or other restriction
(including, but not limited to, related patents, trademarks, and license
agreements) of which you are personally aware, and conspicuously marking the
work as "Submitted on behalf of a third-party: [named here]".
</p></li>
<li><p>
You agree to notify the Project Manager of any facts or circumstances of which
you become aware that would make these representations inaccurate in any
respect.
</p></li>
<li><p>
In addition, if you have provided a Contribution (as defined in the LLC
Contribution License Agreement below) to the Project under the Contribution
License Agreement to OpenStack, LLC ("LLC Contribution Agreement"), you agree
that OpenStack, LLC may assign the LLC Contribution Agreement along with all
its rights and obligations under the LLC Contribution License Agreement to the
Project Manager.
</p></li>
</ol>
<blockquote>
<p><em>In order to clarify the intellectual property license granted with
Contributions from any person or entity, the OpenStack Project (the "Project")
must have a Contributor License Agreement ("Agreement") on file that has been
signed by each Contributor, indicating agreement to the license terms below.
This license is for your protection as a Contributor as well as the protection
of OpenStack, LLC as Project manager (the "Project Manager") and the Project
users; it does not change your rights to use your own Contributions for any
other purpose. If you have not already done so, please complete and sign this
Individual License Agreement by following the instructions embedded below.
After you fill in the required information and apply your digital signature to
the Agreement, the signature service will generate an email to you. You must
confirm your digital signature as instructed in this email to complete the
signing process. The signature service will then send you a signed copy of this
Agreement for your records.</em></p>
<p><em>You accept and agree to the following terms and conditions for Your
present and future Contributions submitted to the Project Manager. Except for
the license granted herein to the Project Manager and recipients of software
distributed by the Project Manager, You reserve all right, title, and interest
in and to Your Contributions.</em></p>
<ol>
<li><p><strong>Definitions</strong>"You" (or "Your") shall mean the copyright
owner or legal entity authorized by the copyright owner that is making this
Agreement with the Project Manager. For legal entities, the entity making a
Contribution and all other entities that control, are controlled by, or are
under common control with that entity are considered to be a single
Contributor. For the purposes of this definition, "control" means (i) the
power, direct or indirect, to cause the direction or management of such entity,
whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or
more of the outstanding shares, or (iii) beneficial ownership of such
entity. "Contribution" shall mean any original work of authorship, including
any modifications or additions to an existing work, that is intentionally
submitted by You to the Project Manager for inclusion in, or documentation of,
any of the projects owned or managed by the Project Manager (the "Work"). For
the purposes of this definition, "submitted" means any form of electronic,
verbal, or written communication sent to the Project Manager or its
representatives, including but not limited to communication on electronic
mailing lists, source code control systems, and issue tracking systems that are
managed by, or on behalf of, the Project Manager for the purpose of discussing
and improving the Work, but excluding communication that is conspicuously
marked or otherwise designated in writing by You as "Not a
Contribution."</p></li>
<li><p><strong>Grant of Copyright License.</strong> Subject to the terms and
conditions of this Agreement, You hereby grant to the Project Manager and to
recipients of software distributed by the Project Manager a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright
license to reproduce, prepare derivative works of, publicly display, publicly
perform, sublicense, and distribute Your Contributions and such derivative
works.</p></li>
<li><p><strong>Grant of Patent License.</strong> Subject to the terms and
conditions of this Agreement, You hereby grant to the Project Manager and to
recipients of software distributed by the Project Manager a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as
stated in this section) patent license to make, have made, use, offer to sell,
sell, import, and otherwise transfer the Work, where such license applies only
to those patent claims licensable by You that are necessarily infringed by Your
Contribution(s) alone or by combination of Your Contribution(s) with the Work
to which such Contribution(s) was submitted. If any entity institutes patent
litigation against You or any other entity (including a cross-claim or
counterclaim in a lawsuit) alleging that Your Contribution, or the Work to
which You have contributed, constitutes direct or contributory patent
infringement, then any patent licenses granted to that entity under this
Agreement for that Contribution or Work shall terminate as of the date such
litigation is filed.</p></li>
<li><p>You represent that you are legally entitled to grant the above license.
If your employer(s) has rights to intellectual property that you create that
includes your Contributions, You represent that you have received permission to
make Contributions on behalf of that employer, that your employer has waived
such rights for your Contributions to the Project Manager, or that your
employer has executed a separate Corporate Contributor License Agreement with
the Project Manager.</p></li>
<li><p>You represent that each of Your Contributions is Your original creation
(see Section 7 for submissions on behalf other others). You represent that Your
Contribution submissions include complete details of any third-party license or
other restriction (including, but not limited to, related patents and
trademarks) of which you are personally aware and which are associated with any
part of Your Contributions.</p></li>
<li><p>You are not expected to provide support for Your Contributions, except
to the extent You desire to provide support. You may provide support for free,
for a fee, or not at all. Unless required by applicable law or agreed to in
writing, You provide Your Contributions on as "AS IS" BASIS, WITHOUT WARRANTIES
OR CONDITIONS OR ANY KIND, either express or implied, including, without
limitation, any warranties or conditions of TITLE, NONINFRINGEMENT,
MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE.</p></li>
<li><p>Should You wish to submit work that is not Your original creation, You
may submit it to the Project Manager separately from any Contribution,
identifying the complete details of its source and of any license or other
restriction (including, but not limited to, related patents, trademarks, and
license agreements) of which you are personally aware, and conspicuously
marking the work as "Submitted on behalf of a third-party: [named
here]".</p></li>
<li><p>You agree to notify the Project Manager of any facts or circumstances of
which you become aware that would make these representations inaccurate in any
respect.</p></li>
</ol>
</blockquote>
</div></body></html>

View File

@ -1,575 +0,0 @@
// Copyright (c) 2014 VMware, Inc.
// Copyright (c) 2014 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.
// this regex matches the hash part of review pages
var hashRegex = /^\#\/c\/([\d]+)((\/\d+)([.][.](\d+))?)?\/?$/;
// this regex matches CI comments
var ciRegex = /^(.* CI|Jenkins|Zuul)$/;
// this regex matches "Patch set #"
var psRegex = /^(Uploaded patch set|Patch Set) (\d+)(:|\.)/;
// this regex matches merge failure messages
var mergeFailedRegex = /Merge Failed\./;
// this regex matches the name of CI systems we trust to report merge failures
var trustedCIRegex = /^(OpenStack CI|Jenkins|Zuul)$/;
// this regex matches the name+pipeline that we want at the top of the CI list
var firstPartyCI = /^(Jenkins|Zuul)/;
// this regex matches the pipeline markup
var pipelineNameRegex = /Build \w+ \(([-\w]+) pipeline\)/;
// The url to full status information on running jobs
var zuulStatusURL = 'https://zuul.openstack.org';
// The json URL to check for running jobs
var zuulStatusJSON = 'https://zuul.openstack.org/status/change/';
// This is a variable to determine if we're in debugging mode, which
// lets you globally set it to see what's going on in the flow.
var hideci_debug = false;
// This is a variable to enable zuul integration, we default it off so
// that it creates no additional load, and that it's easy to turn off
// the feature.
var zuul_inline = false;
/**
dbg(...) - prints a list of items out to the javascript
console.log. This allows us to leave tracing in this file which is a
no-op by default, but can be triggered if you enter a javascript
console and set hideci_debug = true.
*/
function dbg () {
if (hideci_debug == true) {
for (var i = 0; i < arguments.length; i++) {
console.log(arguments[i]);
}
}
}
function format_time(ms, words) {
if (ms == null) {
return "unknown";
}
var seconds = (+ms)/1000;
var minutes = Math.floor(seconds/60);
var hours = Math.floor(minutes/60);
seconds = Math.floor(seconds % 60);
minutes = Math.floor(minutes % 60);
r = '';
if (words) {
if (hours) {
r += hours;
r += ' hr ';
}
r += minutes + ' min';
} else {
if (hours < 10) r += '0';
r += hours + ':';
if (minutes < 10) r += '0';
r += minutes + ':';
if (seconds < 10) r += '0';
r += seconds;
}
return r;
}
var ci_parse_psnum = function($panel) {
var match = psRegex.exec($panel.html());
if (match !== null) {
return parseInt(match[2]);
}
return 0;
};
var ci_parse_is_merge_conflict = function($panel) {
return (mergeFailedRegex.exec($panel.html()) !== null);
};
var ci_find_pipeline = function($panel) {
var match = pipelineNameRegex.exec($panel.html());
if (match !== null) {
return match[1];
} else {
return null;
}
};
var ci_parse_results = function($panel) {
var result_list = [];
var test_results = $panel.find("li.comment_test");
var pipeline = null;
if (test_results !== null) {
test_results.each(function(i, li) {
var result = {};
if ($(li).find("a").length > 0) {
result["name"] = $(li).find("span.comment_test_name").find("a")[0].innerHTML;
result["link"] = $(li).find("span.comment_test_name").find("a")[0];
}
else {
result["name"] = $(li).find("span.comment_test_name")[0].innerHTML;
}
result["result"] = $(li).find("span.comment_test_result")[0];
result_list.push(result);
});
}
return result_list;
};
/***
* function ci_group_by_ci_pipeline - create a group by structure for
* iterating on CI's pipelines
*
* This function takes the full list of comments, the current patch
* number, and builds an array of (ci_name_pipelinename, comments array)
* tuples. That makes it very easy to process during the display
* phase to ensure we only display the latest result for every CI
* pipeline.
*
* Comments that do not have a parsable pipeline (3rd party ci
* systems) get collapsed by name, and we specify 'check' for their
* pipeline.
*
**/
var ci_group_by_ci_pipeline = function(current, comments) {
var ci_pipelines = [];
var ci_pipeline_comments = [];
for (var i = 0; i < comments.length; i++) {
var comment = comments[i];
if ((comment.psnum != current) || !comment.is_ci || (comment.results.length == 0)) {
continue;
}
var name_pipeline = comment.name;
if (comment.pipeline !== null) {
name_pipeline += ' ' + comment.pipeline;
}
var index = ci_pipelines.indexOf(name_pipeline);
if (index == -1) {
// not found, so create new entries
ci_pipelines.push(name_pipeline);
ci_pipeline_comments.push([comment]);
} else {
ci_pipeline_comments[index].push(comment);
}
}
function sort_by_name(a,b) {
if (a[0] < b[0])
return -1;
else if (a[0] > b[0])
return 1;
else
return 0;
}
var results = [];
var notfirstparty = [];
// we want to separate out first party CI results to always be the
// top of the list, and third party CI to come after, so that
// hunting for first party CI isn't tough.
for (i = 0; i < ci_pipelines.length; i++) {
if (firstPartyCI.test(ci_pipelines[i])) {
results.push([ci_pipelines[i], ci_pipeline_comments[i]]);
} else {
notfirstparty.push([ci_pipelines[i], ci_pipeline_comments[i]]);
}
}
notfirstparty.sort(sort_by_name);
for (i = 0; i < notfirstparty.length; i++) {
results.push(notfirstparty[i]);
}
return results;
};
var ci_parse_comments = function() {
var comments = [];
$("p").each(function() {
var match = psRegex.exec($(this).html());
if (match !== null) {
var psnum = parseInt(match[2]);
var top = $(this).parent().parent().parent();
// old change screen
var name = top.attr("name");
if (!name) {
// new change screen
name = $(this).parent().parent().parent().children().children()[0].innerHTML;
top = $(this).parent().parent().parent().parent();
}
var comment = {};
comment.name = name;
var date_cell = top.find(".commentPanelDateCell");
if (date_cell.attr("title")) {
// old change screen
comment.date = date_cell.attr("title");
} else {
// new change screen
comment.date = $(this).parent().parent().parent().children().children()[2].innerHTML
}
var comment_panel = $(this).parent();
comment.psnum = psnum;
comment.merge_conflict = ci_parse_is_merge_conflict(comment_panel);
comment.pipeline = ci_find_pipeline(comment_panel);
comment.results = ci_parse_results(comment_panel);
comment.is_ci = (ciRegex.exec(comment.name) !== null);
comment.is_trusted_ci = (trustedCIRegex.exec(comment.name) !== null);
comment.ref = top;
dbg("Found comment", comment);
comments.push(comment);
}
});
return comments;
};
var ci_latest_patchset = function(comments) {
var psnum = 0;
for (var i = 0; i < comments.length; i++) {
psnum = Math.max(psnum, comments[i].psnum);
}
return psnum;
};
var ci_is_merge_conflict = function(comments) {
var latest = ci_latest_patchset(comments);
var conflict = false;
for (var i = 0; i < comments.length; i++) {
var comment = comments[i];
// only if we are actually talking about the latest patch set
if (comment.psnum == latest) {
if (comment.is_trusted_ci) {
conflict = comment.merge_conflict;
}
}
}
return conflict;
};
var ci_prepare_results_table = function() {
// Create a table and insert it after the approval table
var table = $("table.test_result_table")[0];
if (!table) {
table = document.createElement("table");
$(table).addClass("test_result_table");
$(table).addClass("infoTable").css({"margin-top":"1em", "margin-bottom":"1em"});
var approval_table = $("div.approvalTable");
if (approval_table.length) {
var outer_table = document.createElement("table");
$(outer_table).insertBefore(approval_table);
var outer_table_row = document.createElement("tr");
$(outer_table).append(outer_table_row);
var td = document.createElement("td");
$(outer_table_row).append(td);
$(td).css({"vertical-align":"top"});
$(td).append(approval_table);
td = document.createElement("td");
$(outer_table_row).append(td);
$(td).css({"vertical-align":"top"});
$(td).append(table);
} else {
var big_table_row = $("div.screen>div>div>table>tbody>tr");
var td = $(big_table_row).children()[1];
$(td).append(table);
}
} else {
$(table).empty();
}
return table;
};
var ci_display_results = function(comments) {
var table = ci_prepare_results_table();
if (ci_is_merge_conflict(comments)) {
var mc_header = $("<tr>").append($('<td class="merge_conflict" colpsan="2">Patch in Merge Conflict</td>'));
mc_header.css('width', '400');
mc_header.css('font-weight', 'bold');
mc_header.css('color', 'red');
mc_header.css('padding-left', '2em');
$(table).append(mc_header);
return;
}
var current = ci_latest_patchset(comments);
var ci_pipelines = ci_group_by_ci_pipeline(current, comments);
for (var i = 0; i < ci_pipelines.length; i++) {
var ci_pipeline_name = ci_pipelines[i][0];
var ci_pipeline_comments = ci_pipelines[i][1];
// the most recent comment on a pipeline
var last = ci_pipeline_comments.length - 1;
var comment = ci_pipeline_comments[last];
var rechecks = "";
if (last > 0) {
rechecks = " (" + last + " rechecks)";
}
var header = $("<tr>").append($('<td class="header">' + ci_pipeline_name + rechecks + '</td>'));
header.append('<td class="header ci_date">' + comment.date + '</td>');
$(table).append(header);
for (var j = 0; j < comment.results.length; j++) {
var result = comment.results[j];
var tr = $("<tr>");
if ("link" in result) {
tr.append($("<td>").append($(result["link"]).clone()));
}
else {
tr.append($("<td>").text(result["name"]));
}
tr.append($("<td>").append($(result["result"]).clone()));
$(table).append(tr);
}
}
};
var set_cookie = function (name, value) {
document.cookie = name + "=" + value + "; path=/";
};
var read_cookie = function (name) {
var nameEQ = name + "=";
var ca = document.cookie.split(';');
for (var i = 0; i < ca.length; i++) {
var c = ca[i];
while (c.charAt(0) == ' ') {
c = c.substring(1, c.length);
}
if (c.indexOf(nameEQ) == 0) {
return c.substring(nameEQ.length, c.length);
}
}
return null;
};
var ci_toggle_visibility = function(comments, showOrHide) {
if (!comments) {
comments = ci_parse_comments();
}
$.each(comments, function(i, comment) {
if (comment.is_ci && !comment.is_trusted_ci) {
$(comment.ref).toggle(showOrHide);
}
});
};
var ci_hide_ci_comments = function(comments) {
if (!comments) {
comments = ci_parse_comments();
}
$.each(comments, function(i, comment) {
if (comment.is_ci && !comment.is_trusted_ci) {
$(comment.ref).hide();
}
});
};
var ci_page_loaded = function() {
if (hashRegex.test(window.location.hash)) {
dbg("Searching for ci results on " + window.location.hash);
$("#toggleci").show();
var comments = ci_parse_comments();
ci_display_results(comments);
var showOrHide = 'true' == read_cookie('show-ci-comments');
if (!showOrHide) {
ci_hide_ci_comments(comments);
}
if (zuul_inline === true) {
ci_zuul_for_change(comments);
}
} else {
$("#toggleci").hide();
}
};
var ci_current_change = function() {
var change = hashRegex.exec(window.location.hash);
if (change.length > 1) {
return change[1];
}
return null;
};
// recursively find the zuul status change, will be much more
// efficient once zuul supports since json status.
var ci_find_zuul_status = function (data, change_psnum) {
var objects = [];
for (var i in data) {
if (!data.hasOwnProperty(i)) continue;
if (typeof data[i] == 'object') {
objects = objects.concat(ci_find_zuul_status(data[i],
change_psnum));
} else if (i == 'id' && data.id == change_psnum) {
objects.push(data);
}
}
return objects;
};
var ci_zuul_all_status = function(jobs) {
var status = "passing";
for (var i = 0; i < jobs.length; i++) {
if (jobs[i].result && jobs[i].result != "SUCCESS") {
status = "failing";
break;
}
}
return status;
};
var ci_zuul_display_status = function(status) {
var zuul_table = $("table.zuul_result_table")[0];
if (!zuul_table) {
var test_results = $("table.test_result_table")[0];
zuul_table = document.createElement("table");
$(zuul_table).addClass("zuul_result_table");
$(zuul_table).addClass("infoTable").css({"margin-bottom":"1em"});
if (test_results) {
$(test_results).prepend(zuul_table);
}
}
$(zuul_table).empty();
$(zuul_table).show();
$(zuul_table).append("<tr><td class='header'>Change currently being tested (<a href='" + zuulStatusURL + "'>full status</a>)</td></tr>");
for (var i = 0; i < status.length; i++) {
var item = status[i];
var pipeline = item.jobs[0].pipeline;
var passing = (item.failing_reasons && item.failing_reasons.length > 0) ? "failing" : "passing";
var timeleft = item.remaining_time;
var row = "<tr><td>";
if (pipeline != null) {
row += pipeline + " pipeline: " + passing;
row += " (" + format_time(timeleft, false) + " left)";
} else {
row += "in between pipelines, status should update shortly";
}
row += "</td></tr>";
$(zuul_table).append(row);
}
};
var ci_zuul_clear_status = function () {
var zuul_table = $("table.zuul_result_table")[0];
if (zuul_table) {
$(zuul_table).hide();
}
};
var ci_zuul_process_changes = function(data, change_psnum) {
var zuul_status = ci_find_zuul_status(data, change_psnum);
if (zuul_status.length) {
ci_zuul_display_status(zuul_status);
} else {
ci_zuul_clear_status();
}
};
var ci_zuul_for_change = function(comments) {
if (!comments) {
comments = ci_parse_comments();
}
var change = ci_current_change();
var psnum = ci_latest_patchset(comments);
var change_psnum = change + "," + psnum;
// do the loop recursively in ajax
(function poll() {
$.ajax({
url: zuulStatusJSON + change_psnum,
type: "GET",
success: function(data) {
dbg("Found zuul data for " + change_psnum, data);
ci_zuul_process_changes(data, change_psnum);
},
dataType: "json",
complete: setTimeout(function() {
// once we are done with this cycle in the loop we
// schedule ourselves again in the future with
// setTimeout. However, by the time the function
// actually gets called, other things might have
// happened, and we may want to just dump the data
// instead.
//
// the UI might have gone hidden (user was bored,
// switched to another tab / window).
//
// the user may have navigated to another review url,
// so the data returned is not relevant.
//
// both cases are recoverable when the user navigates
// around, because a new "thread" gets started on
// ci_page_load.
//
// BUG(sdague): there is the possibility that the user
// navigates away from a page and back fast enough
// that the first "thread" is not dead, and a second
// one is started. greghaynes totally said he'd come
// up with a way to fix that.
if (window.zuul_enable_status_updates == false) {
return;
}
var current = ci_current_change();
if (current && change_psnum.indexOf(current) != 0) {
// window url is dead, so don't schedule any more future
// updates for this url.
return;
}
poll();
}, 15000),
timeout: 5000
});
})();
};
window.onload = function() {
var input = document.createElement("input");
input.id = "toggleci";
input.type = "button";
input.className = "gwt-Button";
input.value = "Toggle Extra CI";
input.onclick = function () {
// Flip the cookie
var showOrHide = 'true' == read_cookie('show-ci-comments');
set_cookie('show-ci-comments', showOrHide ? 'false' : 'true');
// Hide or Show existing comments based on cookie
ci_toggle_visibility(null, !showOrHide);
};
document.body.appendChild(input);
MutationObserver = window.MutationObserver || window.WebKitMutationObserver;
var observer = new MutationObserver(function(mutations, observer) {
var span = $("span.rpcStatus");
$.each(mutations, function(i, mutation) {
if (mutation.target === span[0] &&
mutation.attributeName === "style" &&
(!(span.is(":visible")))) {
ci_page_loaded();
}
});
});
observer.observe(document, {
subtree: true,
attributes: true
});
$(document).on({
'show.visibility': function() {
window.zuul_enable_status_updates = true;
ci_page_loaded();
},
'hide.visibility': function() {
window.zuul_enable_status_updates = false;
}
});
};

View File

@ -1,39 +0,0 @@
[loggers]
keys=root,gerrit_user_sync
[handlers]
keys=console,debug,normal
[formatters]
keys=simple
[logger_root]
level=WARNING
handlers=console
[logger_gerrit_user_sync]
level=DEBUG
handlers=debug,normal
qualname=gerrit_user_sync
[handler_console]
level=WARNING
class=StreamHandler
formatter=simple
args=(sys.stdout,)
[handler_debug]
level=DEBUG
class=logging.handlers.TimedRotatingFileHandler
formatter=simple
args=('/var/log/gerrit_user_sync/debug.log', 'midnight', 1, 30,)
[handler_normal]
level=INFO
class=logging.handlers.TimedRotatingFileHandler
formatter=simple
args=('/var/log/gerrit_user_sync/sync.log', 'midnight', 1, 30,)
[formatter_simple]
format=%(asctime)s %(levelname)s %(name)s: %(message)s
datefmt=

View File

@ -1,11 +0,0 @@
# Directions for web crawlers.
# See http://www.robotstxt.org/wc/norobots.html.
User-agent: HTTrack
User-agent: puf
User-agent: MSIECrawler
User-agent: Nutch
Disallow: /
User-agent: msnbot
Crawl-delay: 1

View File

@ -1,14 +0,0 @@
<html><body><div>
<h1>
Gerrit System Role Accounts Proxy CLA
</h1>
<p>
This is not a real CLA and cannot be signed. See <a
href="https://docs.openstack.org/contributors/common/setup-gerrit.html#individual-contributor-license-agreement">the
account setup instructions</a> for more information on OpenStack Contributor
License Agreements.
</p>
</div></body></html>

View File

@ -1,16 +0,0 @@
<html><body><div>
<h1>
OpenStack Project U.S. Government Contributor License Agreement
</h1>
<p>
This agreement is not managed through Gerrit. If you need to sign the U.S.
Government Contributor License Agreement, please contact the OpenStack
Foundation to initiate the process. See <a
href="https://docs.openstack.org/contributors/common/setup-gerrit.html#individual-contributor-license-agreement">the
account setup instructions</a> for more information on OpenStack Contributor
License Agreements.
</p>
</div></body></html>

View File

@ -1,520 +0,0 @@
# == Class: openstack_project::gerrit
#
# A wrapper class around the main gerrit class that sets gerrit
# up for launchpad single sign on and bug/blueprint links
class openstack_project::gerrit (
$mysql_host,
$mysql_password,
$accountpatchreviewdb_url = undef,
$vhost_name = $::fqdn,
$canonicalweburl = "https://${::fqdn}/",
$git_http_url = '',
$canonical_git_url = '',
$serveradmin = 'webmaster@openstack.org',
$ssh_host_key = '/home/gerrit2/review_site/etc/ssh_host_rsa_key',
$ssh_project_key = '/home/gerrit2/review_site/etc/ssh_project_rsa_key',
$ssl_cert_file = "/etc/ssl/certs/${::fqdn}.pem",
$ssl_key_file = "/etc/ssl/private/${::fqdn}.key",
$ssl_chain_file = '/etc/ssl/certs/intermediate.pem',
$ssl_cert_file_contents = '',
$ssl_key_file_contents = '',
$ssl_chain_file_contents = '',
$ssh_dsa_key_contents = '', # If left empty puppet will not create file.
$ssh_dsa_pubkey_contents = '', # If left empty puppet will not create file.
$ssh_rsa_key_contents = '', # If left empty puppet will not create file.
$ssh_rsa_pubkey_contents = '', # If left empty puppet will not create file.
$ssh_project_rsa_key_contents = '', # If left empty will not create file.
$ssh_project_rsa_pubkey_contents = '', # If left empty will not create file.
$ssh_welcome_rsa_key_contents='', # If left empty will not create file.
$ssh_welcome_rsa_pubkey_contents='', # If left empty will not create file.
$ssh_replication_rsa_key_contents='', # If left empty will not create file.
$ssh_replication_rsa_pubkey_contents='', # If left empty will not create file.
$email = '',
$database_poollimit = '',
$container_heaplimit = '',
$core_packedgitopenfiles = '',
$core_packedgitlimit = '',
$core_packedgitwindowsize = '',
$sshd_threads = '',
$httpd_acceptorthreads = '',
$httpd_minthreads = '',
$httpd_maxthreads = '',
$httpd_maxqueued = '',
$httpd_maxwait = '',
$war = '',
$acls_dir = 'UNDEF',
$notify_impact_file = 'UNDEF',
$projects_file = 'UNDEF',
$projects_config = 'UNDEF',
$github_username = '',
$github_oauth_token = '',
$github_project_username = '',
$github_project_password = '',
$email_private_key = '',
$token_private_key = '',
$replicate_local = true,
$replication_force_update = true,
$replication_auto_reload = false,
$replication = [],
$local_git_dir = '/opt/lib/git',
$jeepyb_cache_dir = '/opt/lib/jeepyb',
$cla_description = 'OpenStack Individual Contributor License Agreement',
$cla_file = 'static/cla.html',
$cla_id = '2',
$cla_name = 'ICLA',
$testmode = false,
$swift_username = '',
$swift_password = '',
$gitweb = true,
$cgit = false,
$web_repo_url = false,
$web_repo_url_encode = false,
$secondary_index = true,
$report_bug_text = 'Get Help',
$report_bug_url = 'https://docs.openstack.org/infra/system-config/project.html#contributing',
$index_threads = 1,
$download = {},
$receive_max_object_size_limit = '100 m',
$cache_accounts = 32768,
$cache_accounts_byemail = 32768,
$cache_accounts_byname = 32768,
$cache_groups_byuuid = 32768,
$commentlinks = [],
$commitmessage_params = {},
$its_plugins = [],
$its_rules = [],
$java_home = '',
$openidssourl = 'https://login.ubuntu.com/+openid',
) {
class { 'jeepyb::openstackwatch':
projects => [
'openstack/ceilometer',
'openstack/cinder',
'openstack/glance',
'openstack/heat',
'openstack/horizon',
'openstack/infra',
'openstack/keystone',
'openstack/nova',
'openstack/oslo',
'openstack/neutron',
'openstack/swift',
'openstack/tempest',
'openstack-dev/devstack',
],
container => 'rss',
json_url => 'https://review.opendev.org/query?q=status:open',
swift_username => $swift_username,
swift_password => $swift_password,
swift_auth_url => 'https://auth.api.rackspacecloud.com/v1.0',
auth_version => '1.0',
}
class { '::gerrit':
vhost_name => $vhost_name,
canonicalweburl => $canonicalweburl,
git_http_url => $git_http_url,
canonical_git_url => $canonical_git_url,
# opinions
allow_drafts => false,
enable_melody => true,
melody_session => true,
robots_txt_source => 'puppet:///modules/openstack_project/gerrit/robots.txt',
enable_javamelody_top_menu => false,
# passthrough
java_home => $java_home,
ssl_cert_file => $ssl_cert_file,
ssl_key_file => $ssl_key_file,
ssl_chain_file => $ssl_chain_file,
ssl_cert_file_contents => $ssl_cert_file_contents,
ssl_key_file_contents => $ssl_key_file_contents,
ssl_chain_file_contents => $ssl_chain_file_contents,
ssh_dsa_key_contents => $ssh_dsa_key_contents,
ssh_dsa_pubkey_contents => $ssh_dsa_pubkey_contents,
ssh_rsa_key_contents => $ssh_rsa_key_contents,
ssh_rsa_pubkey_contents => $ssh_rsa_pubkey_contents,
ssh_project_rsa_key_contents => $ssh_project_rsa_key_contents,
ssh_project_rsa_pubkey_contents => $ssh_project_rsa_pubkey_contents,
ssh_replication_rsa_key_contents => $ssh_replication_rsa_key_contents,
ssh_replication_rsa_pubkey_contents => $ssh_replication_rsa_pubkey_contents,
email => $email,
openidssourl => $openidssourl,
database_poollimit => $database_poollimit,
container_heaplimit => $container_heaplimit,
core_packedgitopenfiles => $core_packedgitopenfiles,
core_packedgitlimit => $core_packedgitlimit,
core_packedgitwindowsize => $core_packedgitwindowsize,
sshd_threads => $sshd_threads,
httpd_acceptorthreads => $httpd_acceptorthreads,
httpd_minthreads => $httpd_minthreads,
httpd_maxthreads => $httpd_maxthreads,
httpd_maxqueued => $httpd_maxqueued,
httpd_maxwait => $httpd_maxwait,
sshd_max_connections_per_user => '96',
commentlinks => $commentlinks,
its_plugins => $its_plugins,
its_rules => $its_rules,
trackingids => [
{
name => 'launchpad-bug',
footers => ['closes-bug:', 'partial-bug:', 'related-bug:'],
match => '\\\\#?(\\\\d+)',
system => 'Launchpad',
},
{
name => 'storyboard-story',
footer => 'story:',
match => '\\\\#?(\\\\d+)',
system => 'Storyboard',
},
{
name => 'storyboard-task',
footer => 'task:',
match => '\\\\#?(\\\\d+)',
system => 'Storyboard',
},
],
war => $war,
mysql_host => $mysql_host,
mysql_password => $mysql_password,
accountpatchreviewdb_url => $accountpatchreviewdb_url,
email_private_key => $email_private_key,
token_private_key => $token_private_key,
replicate_local => $replicate_local,
replicate_path => $local_git_dir,
replicate_on_startup => 'false',
replication_force_update => $replication_force_update,
replication_auto_reload => $replication_auto_reload,
replication => $replication,
gitweb => $gitweb,
cgit => $cgit,
web_repo_url => $web_repo_url,
web_repo_url_encode => $web_repo_url_encode,
testmode => $testmode,
secondary_index => $secondary_index,
require => Class[openstack_project::server],
report_bug_text => $report_bug_text,
report_bug_url => $report_bug_url,
index_threads => $index_threads,
download => $download,
receive_max_object_size_limit => $receive_max_object_size_limit,
commitmessage_params =>
{
maxLineLength => '72',
},
cache_accounts => $cache_accounts,
cache_accounts_byemail => $cache_accounts_byemail,
cache_accounts_byname => $cache_accounts_byname,
cache_groups_byuuid => $cache_groups_byuuid,
}
mysql_backup::backup_remote { 'gerrit':
database_host => $mysql_host,
database_user => 'gerrit2',
database_password => $mysql_password,
dest_dir => '/home/gerrit2/mysql_backups',
num_backups => '10',
require => Class['::gerrit'],
}
if ($testmode == false) {
class { 'gerrit::cron':
gitgc_repos => true,
}
class { 'github':
username => $github_username,
project_username => $github_project_username,
project_password => $github_project_password,
oauth_token => $github_oauth_token,
require => Class['::gerrit']
}
}
file { '/home/gerrit2/review_site/static/cla.html':
ensure => present,
owner => 'root',
group => 'root',
mode => '0444',
source => 'puppet:///modules/openstack_project/gerrit/cla.html',
replace => true,
require => Class['::gerrit'],
}
file { '/home/gerrit2/review_site/static/usg-cla.html':
ensure => present,
owner => 'root',
group => 'root',
mode => '0444',
source => 'puppet:///modules/openstack_project/gerrit/usg-cla.html',
replace => true,
require => Class['::gerrit'],
}
file { '/home/gerrit2/review_site/static/system-cla.html':
ensure => present,
owner => 'root',
group => 'root',
mode => '0444',
source => 'puppet:///modules/openstack_project/gerrit/system-cla.html',
replace => true,
require => Class['::gerrit'],
}
file { '/home/gerrit2/review_site/static/title.svg':
ensure => present,
source => 'puppet:///modules/openstack_project/opendev.svg',
require => Class['::gerrit'],
notify => Exec['reload_gerrit_header'],
}
package { 'libjs-jquery':
ensure => present,
}
file { '/home/gerrit2/review_site/static/jquery.js':
ensure => present,
source => '/usr/share/javascript/jquery/jquery.js',
require => [
File['/home/gerrit2/review_site/static'],
Class['::gerrit'],
Package['libjs-jquery'],
],
subscribe => Package['libjs-jquery'],
notify => Exec['reload_gerrit_header'],
}
vcsrepo { '/opt/jquery-visibility':
ensure => latest,
provider => git,
revision => 'master',
source => 'https://github.com/mathiasbynens/jquery-visibility.git',
}
file { '/home/gerrit2/review_site/static/jquery-visibility.js':
ensure => present,
source => '/opt/jquery-visibility/jquery-visibility.js',
subscribe => Vcsrepo['/opt/jquery-visibility'],
notify => Exec['reload_gerrit_header'],
require => [ File['/home/gerrit2/review_site/static'],
Class['::gerrit'] ]
}
file { '/home/gerrit2/review_site/static/hideci.js':
ensure => present,
source => 'puppet:///modules/openstack_project/gerrit/hideci.js',
require => Class['::gerrit'],
notify => Exec['reload_gerrit_header'],
}
file { '/home/gerrit2/review_site/etc/GerritSite.css':
ensure => present,
source => 'puppet:///modules/openstack_project/gerrit/GerritSite.css',
require => Class['::gerrit'],
}
file { '/home/gerrit2/review_site/etc/GerritSiteHeader.html':
ensure => present,
source =>
'puppet:///modules/openstack_project/gerrit/GerritSiteHeader.html',
require => Class['::gerrit'],
}
exec { 'reload_gerrit_header':
command => 'sleep 10; touch /home/gerrit2/review_site/etc/GerritSiteHeader.html',
path => '/bin:/usr/bin',
refreshonly => true,
}
cron { 'gerritsyncusers':
ensure => absent,
}
cron { 'sync_launchpad_users':
ensure => absent,
}
file { '/home/gerrit2/review_site/hooks/change-merged':
ensure => present,
owner => 'root',
group => 'root',
mode => '0555',
source => 'puppet:///modules/openstack_project/gerrit/change-merged',
replace => true,
require => Class['::gerrit'],
}
file { '/home/gerrit2/review_site/hooks/change-abandoned':
ensure => present,
owner => 'root',
group => 'root',
mode => '0555',
source => 'puppet:///modules/openstack_project/gerrit/change-abandoned',
replace => true,
require => Class['::gerrit'],
}
if ($notify_impact_file != 'UNDEF') {
file { '/home/gerrit2/review_site/hooks/notify_impact.yaml':
ensure => present,
source => $notify_impact_file,
require => Class['::gerrit'],
}
}
file { '/home/gerrit2/review_site/hooks/patchset-created':
ensure => present,
owner => 'root',
group => 'root',
mode => '0555',
content => template('openstack_project/gerrit_patchset-created.erb'),
replace => true,
require => Class['::gerrit'],
}
if $ssh_welcome_rsa_key_contents != '' {
file { '/home/gerrit2/review_site/etc/ssh_welcome_rsa_key':
owner => 'gerrit2',
group => 'gerrit2',
mode => '0600',
content => $ssh_welcome_rsa_key_contents,
replace => true,
require => File['/home/gerrit2/review_site/etc']
}
}
if $ssh_welcome_rsa_pubkey_contents != '' {
file { '/home/gerrit2/review_site/etc/ssh_welcome_rsa_key.pub':
owner => 'gerrit2',
group => 'gerrit2',
mode => '0644',
content => $ssh_welcome_rsa_pubkey_contents,
replace => true,
require => File['/home/gerrit2/review_site/etc']
}
}
if ($projects_file != 'UNDEF') {
if ($replicate_local) {
if (!defined(File[$local_git_dir])) {
file { $local_git_dir:
ensure => directory,
owner => 'gerrit2',
require => Class['::gerrit'],
}
cron { 'mirror_repack':
ensure => absent,
user => 'gerrit2',
}
cron { 'mirror_gitgc':
user => 'gerrit2',
weekday => '0',
hour => '4',
minute => '7',
command => "find ${local_git_dir} -type d -name \"*.git\" -print -exec git --git-dir=\"{}\" gc \\;",
environment => 'PATH=/usr/bin:/bin:/usr/sbin:/sbin',
}
}
}
file { '/home/gerrit2/projects.yaml':
ensure => present,
owner => 'gerrit2',
group => 'gerrit2',
mode => '0444',
source => $projects_file,
replace => true,
require => Class['::gerrit'],
}
file { $jeepyb_cache_dir:
ensure => 'directory',
owner => 'gerrit2',
group => 'gerrit2',
mode => '0755',
}
file { '/home/gerrit2/projects.ini':
ensure => present,
owner => 'gerrit2',
group => 'gerrit2',
mode => '0444',
content => template($projects_config),
replace => true,
require => Class['::gerrit'],
}
file { '/home/gerrit2/acls':
ensure => directory,
owner => 'gerrit2',
group => 'gerrit2',
mode => '0444',
recurse => true,
replace => true,
purge => true,
force => true,
source => $acls_dir,
require => Class['::gerrit']
}
if ($testmode == false) {
exec { 'manage_projects':
command => '/usr/local/bin/manage-projects -v -l /var/log/manage_projects.log',
timeout => 1800, # 30 minutes
subscribe => [
File['/home/gerrit2/projects.yaml'],
File['/home/gerrit2/acls'],
],
refreshonly => true,
logoutput => true,
require => [
File['/home/gerrit2/projects.yaml'],
File['/home/gerrit2/acls'],
Class['jeepyb'],
],
}
cron { 'track_upstream':
user => 'root',
hour => '*',
minute => '42',
command => '/usr/local/bin/track-upstream -v -l /var/log/track_upstream.log',
environment => 'PATH=/usr/bin:/bin:/usr/sbin:/sbin',
require => [
File['/home/gerrit2/projects.yaml'],
Class['jeepyb'],
],
}
include logrotate
logrotate::file { 'manage_projects.log':
log => '/var/log/manage_projects.log',
options => [
'compress',
'missingok',
'rotate 30',
'daily',
'notifempty',
'copytruncate',
],
require => Exec['manage_projects'],
}
logrotate::file { 'track_upstream.log':
log => '/var/log/track_upstream.log',
options => [
'compress',
'missingok',
'rotate 30',
'daily',
'notifempty',
'copytruncate',
],
require => Cron['track_upstream'],
}
}
}
file { '/home/gerrit2/review_site/bin/set_agreements.sh':
ensure => absent,
}
}

View File

@ -1,399 +0,0 @@
# == Class: openstack_project::review
# Current thinking on Gerrit tuning parameters:
# database.poolLimit:
# This limit must be several units higher than the total number of
# httpd and sshd threads as some request processing code paths may need
# multiple connections.
# database.poolLimit = 1 + max(sshd.threads,sshd.batchThreads)
# + sshd.streamThreads + sshd.commandStartThreads
# + httpd.acceptorThreads + httpd.maxThreads
# http://groups.google.com/group/repo-discuss/msg/4c2809310cd27255
# or "2x sshd.threads"
# http://groups.google.com/group/repo-discuss/msg/269024c966e05d6a
# container.heaplimit:
# core.packedgit*
# http://groups.google.com/group/repo-discuss/msg/269024c966e05d6a
# sshd.threads:
# http://groups.google.com/group/repo-discuss/browse_thread/thread/b91491c185295a71
# httpd.maxQueued:
# Default value is too low, should increase to new default.
# https://gerrit-review.googlesource.com/#/c/70627
# httpd.maxWait:
# 12:07 <@spearce> httpd.maxwait defaults to 5 minutes and is how long gerrit
# waits for an idle sshd.thread before aboring the http request
# 12:08 <@spearce> ironically
# 12:08 <@spearce> ProjectQosFilter passes this value as minutes
# 12:08 <@spearce> to a method that accepts milliseconds
# 12:09 <@spearce> so. you get 5 milliseconds before aborting
# thus, set it to 5000minutes until the bug is fixed.
class openstack_project::review (
# Created by running jeepyb ?
$github_oauth_token = '',
# Create a dedicated user e.g. openstack-project-creator, put
# details here.
$github_project_username = '',
$github_project_password = '',
# Create arbitrary values and put here, puppet will use during
# provisioning.
$mysql_host = '',
$mysql_password = '',
$email_private_key = '',
$token_private_key = '',
# Register an IRC bot and supply it's password here.
$gerritbot_password = '',
$gerritbot_ssh_rsa_key_contents = '',
$gerritbot_ssh_rsa_pubkey_contents = '',
# Register SSL keys and pass their contents in.
$ssl_cert_file = "/etc/ssl/certs/${::fqdn}.pem",
$ssl_cert_file_contents = '',
$ssl_key_file = "/etc/ssl/private/${::fqdn}.key",
$ssl_key_file_contents = '',
$ssl_chain_file = '/etc/ssl/certs/intermediate.pem',
$ssl_chain_file_contents = '',
# Create SSH server key by hand and supply here.
$ssh_dsa_key_contents = '',
$ssh_dsa_pubkey_contents = '',
$ssh_rsa_key_contents = '',
$ssh_rsa_pubkey_contents='',
# manage-projects's user ssh key.
$ssh_project_rsa_key_contents='',
$ssh_project_rsa_pubkey_contents='',
# SSH key for outbound ssh-based replication.
$ssh_replication_rsa_key_contents='',
$ssh_replication_rsa_pubkey_contents='',
# welcome-message's user ssh key.
$ssh_welcome_rsa_key_contents='',
$ssh_welcome_rsa_pubkey_contents='',
# Launchpad creds for bug/blueprint updates
$lp_access_token='',
$lp_access_secret='',
$lp_consumer_key='',
# For openstackwatch.
$swift_username = '',
$swift_password = '',
$storyboard_password = '',
$project_config_repo = '',
$projects_config = 'openstack_project/review.projects.ini.erb',
$gerrit_configure = true,
) {
class { 'project_config':
url => $project_config_repo,
}
if ($gerrit_configure) {
$accountpatchreviewdb_url = "jdbc:mysql://${mysql_host}:3306/accountPatchReviewDb?characterSetResults=utf8&characterEncoding=utf8&connectionCollation=utf8_bin&useUnicode=yes&user=gerrit2&password=${mysql_password}"
class { 'openstack_project::gerrit':
vhost_name => 'review.opendev.org',
canonicalweburl => 'https://review.opendev.org/',
git_http_url => 'https://review.opendev.org/',
ssl_cert_file => $ssl_cert_file,
ssl_key_file => $ssl_key_file,
ssl_chain_file => $ssl_chain_file,
ssl_cert_file_contents => $ssl_cert_file_contents,
ssl_key_file_contents => $ssl_key_file_contents,
ssl_chain_file_contents => $ssl_chain_file_contents,
ssh_dsa_key_contents => $ssh_dsa_key_contents,
ssh_dsa_pubkey_contents => $ssh_dsa_pubkey_contents,
ssh_rsa_key_contents => $ssh_rsa_key_contents,
ssh_rsa_pubkey_contents => $ssh_rsa_pubkey_contents,
ssh_project_rsa_key_contents => $ssh_project_rsa_key_contents,
ssh_project_rsa_pubkey_contents => $ssh_project_rsa_pubkey_contents,
ssh_replication_rsa_key_contents => $ssh_replication_rsa_key_contents,
ssh_replication_rsa_pubkey_contents => $ssh_replication_rsa_pubkey_contents,
ssh_welcome_rsa_key_contents => $ssh_welcome_rsa_key_contents,
ssh_welcome_rsa_pubkey_contents => $ssh_welcome_rsa_pubkey_contents,
email => 'review@openstack.org',
# 1 + 100 + 9 + 2 + 2 + 25 => 139(rounded up)
database_poollimit => '225',
container_heaplimit => '48g',
core_packedgitopenfiles => '4096',
core_packedgitlimit => '400m',
core_packedgitwindowsize => '16k',
sshd_threads => '100',
index_threads => 4,
httpd_minthreads => '20',
httpd_maxthreads => '100',
httpd_maxqueued => '200',
war =>
'https://tarballs.openstack.org/gerrit/gerrit-v2.13.12.11.1707fec.war',
acls_dir => $::project_config::gerrit_acls_dir,
notify_impact_file => $::project_config::gerrit_notify_impact_file,
projects_file => $::project_config::jeepyb_project_file,
projects_config => $projects_config,
github_username => 'openstack-gerrit',
github_oauth_token => $github_oauth_token,
github_project_username => $github_project_username,
github_project_password => $github_project_password,
mysql_host => $mysql_host,
mysql_password => $mysql_password,
accountpatchreviewdb_url => $accountpatchreviewdb_url,
email_private_key => $email_private_key,
token_private_key => $token_private_key,
swift_username => $swift_username,
swift_password => $swift_password,
commentlinks => [
{
name => 'bugheader',
match => '([Cc]loses|[Pp]artial|[Rr]elated)-[Bb]ug:\\\\s*#?(\\\\d+)',
link => 'https://launchpad.net/bugs/$2',
},
{
name => 'bug',
match => '\\\\b[Bb]ug:? #?(\\\\d+)',
link => 'https://launchpad.net/bugs/$1',
},
{
name => 'story',
match => '\\\\b[Ss]tory:? #?(\\\\d+)',
link => 'https://storyboard.openstack.org/#!/story/$1',
},
{
name => 'task',
match => '\\\\b[Tt]ask:? #?(\\\\d+)',
link => 'https://storyboard.openstack.org/#!/task/$1',
},
{
name => 'its-storyboard',
match => '\\\\b[Tt]ask:? #?(\\\\d+)',
link => 'task: $1',
},
{
name => 'blueprint',
match => '(\\\\b[Bb]lue[Pp]rint\\\\b|\\\\b[Bb][Pp]\\\\b)[ \\\\t#:]*([A-Za-z0-9\\\\-]+)',
link => 'https://blueprints.launchpad.net/openstack/?searchtext=$2',
},
{
name => 'testresult',
match => '<li>([^ ]+) <a href=\"[^\"]+\" target=\"_blank\" rel=\"nofollow\">([^<]+)</a> : ([^ ]+)([^<]*)</li>',
html => '<li class=\"comment_test\"><span class=\"comment_test_name\"><a href=\"$2\" rel=\"nofollow\">$1</a></span> <span class=\"comment_test_result\"><span class=\"result_$3\">$3</span>$4</span></li>',
},
{
name => 'testresultnoop',
match => '<li>noop noop : SUCCESS([^<]*)</li>',
html => '<li class=\"comment_test\"><span class=\"comment_test_name\">noop</span> <span class=\"comment_test_result\"><span class=\"result_SUCCESS\">SUCCESS</span>$1</span></li>',
},
{
name => 'launchpadbug',
match => '<a href=\"(https://bugs\\\\.launchpad\\\\.net/[a-zA-Z0-9\\\\-]+/\\\\+bug/(\\\\d+))[^\"]*\">[^<]+</a>',
html => '<a href=\"$1\">$1</a>'
},
{
name => 'changeid',
match => '(I[0-9a-f]{8,40})',
link => '/#/q/$1',
},
{
name => 'gitsha',
match => '(<p>|[\\\\s(])([0-9a-f]{40})(</p>|[\\\\s.,;:)])',
html => '$1<a href=\"/#/q/$2\">$2</a>$3',
},
],
its_plugins => [
{
name => 'its-storyboard',
password => $storyboard_password,
url => 'https://storyboard.openstack.org',
},
],
# See https://gerrit.googlesource.com/plugins/its-storyboard
# /+/stable-2.13/src/main/resources/Documentation
# /quick-install-guide.md#its_actions_its_actionsconfigure-its-actions
# for documentation on these options.
its_rules => [
{
name => 'comment-on-status-update',
event_type => 'patchset-created,change-abandoned,change-restored,change-merged',
action => 'add-standard-comment',
},
{
name => 'change_abandoned',
event_type => 'change-abandoned',
action => 'set-status TODO',
},
{
name => 'change_in_progress',
event_type => 'patchset-created,change-restored',
action => 'set-status REVIEW',
},
{
name => 'change_merged',
event_type => 'change-merged',
action => 'set-status MERGED',
},
],
download => {
'command' => ['checkout', 'cherry_pick', 'pull', 'format_patch'],
'scheme' => ['ssh', 'anon_http', 'anon_git'],
'archive' => ['tar', 'tbz2', 'tgz', 'txz'],
},
replication_force_update => true,
replication => [
{
name => 'github',
url => 'git@github.com:',
authGroup => 'Anonymous Users',
replicationDelay => '1',
replicatePermissions => false,
mirror => true,
projects => [
'^openstack/(?!ara$|ara-web$|ara-infra$).*',
'openstack-dev/*',
'openstack-infra/*',
]
},
{
name => 'gitea01',
url => 'ssh://git@gitea01.opendev.org:222/',
authGroup => 'Anonymous Users',
replicationDelay => '1',
replicatePermissions => false,
mirror => true,
threads => '4',
},
{
name => 'gitea02',
url => 'ssh://git@gitea02.opendev.org:222/',
authGroup => 'Anonymous Users',
replicationDelay => '1',
replicatePermissions => false,
mirror => true,
threads => '4',
},
{
name => 'gitea03',
url => 'ssh://git@gitea03.opendev.org:222/',
authGroup => 'Anonymous Users',
replicationDelay => '1',
replicatePermissions => false,
mirror => true,
threads => '4',
},
{
name => 'gitea04',
url => 'ssh://git@gitea04.opendev.org:222/',
authGroup => 'Anonymous Users',
replicationDelay => '1',
replicatePermissions => false,
mirror => true,
threads => '4',
},
{
name => 'gitea05',
url => 'ssh://git@gitea05.opendev.org:222/',
authGroup => 'Anonymous Users',
replicationDelay => '1',
replicatePermissions => false,
mirror => true,
threads => '4',
},
{
name => 'gitea06',
url => 'ssh://git@gitea06.opendev.org:222/',
authGroup => 'Anonymous Users',
replicationDelay => '1',
replicatePermissions => false,
mirror => true,
threads => '4',
},
{
name => 'gitea07',
url => 'ssh://git@gitea07.opendev.org:222/',
authGroup => 'Anonymous Users',
replicationDelay => '1',
replicatePermissions => false,
mirror => true,
threads => '4',
},
{
name => 'gitea08',
url => 'ssh://git@gitea08.opendev.org:222/',
authGroup => 'Anonymous Users',
replicationDelay => '1',
replicatePermissions => false,
mirror => true,
threads => '4',
},
{
name => 'local',
url => 'file:///opt/lib/git/',
replicationDelay => '1',
threads => '4',
mirror => true,
},
],
require => $::project_config::config_dir,
}
gerrit::plugin { 'javamelody': version => 'v2.13.3.e4233d6' }
gerrit::plugin { 'its-storyboard': version => '805f9ac' }
class { 'gerritbot':
nick => 'openstackgerrit',
password => $gerritbot_password,
server => 'irc.freenode.net',
user => 'gerritbot',
vhost_name => 'review.openstack.org',
ssh_rsa_key_contents => $gerritbot_ssh_rsa_key_contents,
ssh_rsa_pubkey_contents => $gerritbot_ssh_rsa_pubkey_contents,
channel_file => $::project_config::gerritbot_channel_file,
require => $::project_config::config_dir,
}
class { 'gerrit::remotes':
ensure => absent,
}
} else {
# Only create gerrit user / group so we can bring a server online.
include ::gerrit::user
}
package { 'python-launchpadlib':
ensure => present,
}
file { '/home/gerrit2/.launchpadlib':
ensure => directory,
owner => 'gerrit2',
group => 'gerrit2',
mode => '0775',
require => User['gerrit2'],
}
file { '/home/gerrit2/.launchpadlib/creds':
ensure => present,
owner => 'gerrit2',
group => 'gerrit2',
mode => '0600',
content => template('openstack_project/infra_lp_creds.erb'),
replace => true,
require => User['gerrit2'],
}
include bup
bup::site { 'ord.rax':
backup_user => 'bup-review',
backup_server => 'backup01.ord.rax.ci.openstack.org',
}
# Compatibility layer for old domain name below here
include ::httpd
if ! defined(Httpd::Mod['alias']) {
httpd::mod { 'alias':
ensure => present,
before => Service['httpd'],
}
}
::httpd::vhost { 'review.openstack.org':
port => 443, # Is required despite not being used.
docroot => 'MEANINGLESS_ARGUMENT',
priority => '50',
template => 'openstack_project/review-openstack-redirect.vhost.erb',
}
}

View File

@ -1,11 +0,0 @@
#!/bin/sh
# Use timeout to kill any process running longer than 10 minutes.
timeout -k 2m 10m /usr/local/bin/update-blueprint patchset-created "$@"
timeout -k 2m 10m /usr/local/bin/update-bug patchset-created "$@"
timeout -k 2m 10m /usr/local/bin/notify-impact patchset-created "$@" --impact SecurityImpact --dest-address 'openstack-security@lists.openstack.org'
<% if @ssh_welcome_rsa_key_contents != "" -%>
timeout -k 2m 10m /usr/local/bin/welcome-message patchset-created \
--verbose --ssh-user=welcome-message \
--ssh-key=/home/gerrit2/review_site/etc/ssh_welcome_rsa_key "$@"
<% end -%>

View File

@ -1,12 +0,0 @@
[projects]
homepage=http://openstack.org
acl-dir=/home/gerrit2/acls
local-git-dir=<%= @local_git_dir %>
jeepyb-cache-dir=<%= @jeepyb_cache_dir %>
gerrit-host=<%= @fqdn %>
gerrit-user=openstack-dev-project-creator
gerrit-key=<%= @ssh_project_key %>
github-config=/etc/github/github-projects.secure.config
has-wiki=False
has-issues=False
has-downloads=False

View File

@ -1,38 +0,0 @@
# ************************************
# Managed by Puppet
# ************************************
<VirtualHost *:80>
ServerName <%= @srvname %>
LogLevel warn
ErrorLog /var/log/apache2/<%= @srvname %>_error.log
CustomLog /var/log/apache2/<%= @srvname %>_access.log combined
ServerSignature Off
Redirect / https://review.opendev.org/
</VirtualHost>
<IfModule mod_ssl.c>
<VirtualHost *:443>
ServerName <%= @srvname %>
SSLEngine on
SSLProtocol All -SSLv2 -SSLv3
# Once the machine is using something to terminate TLS that supports ECDHE
# then this should be edited to remove the RSA+AESGCM:RSA+AES so that PFS
# only is guarenteed.
SSLCipherSuite ECDH+AESGCM:DH+AESGCM:ECDH+AES256:DH+AES256:ECDH+AES128:DH+AES:RSA+AESGCM:RSA+AES:!AES256:!aNULL:!eNULL:!MD5:!DSS:!PSK:!SRP
SSLHonorCipherOrder on
SSLCertificateFile /etc/letsencrypt-certs/review.opendev.org/review.opendev.org.cer
SSLCertificateKeyFile /etc/letsencrypt-certs/review.opendev.org/review.opendev.org.key
SSLCertificateChainFile /etc/letsencrypt-certs/review.opendev.org/ca.cer
LogLevel warn
ErrorLog /var/log/apache2/<%= @srvname %>_error.log
CustomLog /var/log/apache2/<%= @srvname %>_access.log combined
ServerSignature Off
Redirect / https://review.opendev.org/
</VirtualHost>
</IfModule>

View File

@ -1,14 +0,0 @@
[projects]
homepage=https://opendev.org
acl-dir=/home/gerrit2/acls
local-git-dir=<%= @local_git_dir %>
jeepyb-cache-dir=<%= @jeepyb_cache_dir %>
gerrit-host=review.opendev.org
gerrit-user=openstack-project-creator
gerrit-committer=OpenDev Project Creator <openstack-infra@lists.openstack.org>
gerrit-key=<%= @ssh_project_key %>
github-config=/etc/github/github-projects.secure.config
has-wiki=False
has-issues=False
has-pull-requests=False
has-downloads=False