Fix lf-release-jobs
[releng/global-jjb.git] / docs / jjb / lf-release-jobs.rst
1 .. _lf-global-jjb-release:
2
3 Self-Serve Release Jobs
4 =======================
5
6 Self-serve release jobs allow project committers to direct Jenkins to
7 promote a jar file, container image or Python package from a staging
8 area to a release area.
9
10 To use the self-release process, create a releases/ or .releases/
11 directory at the root of the project repository, add one release yaml
12 file to it, and submit a change set with that release yaml file.  The
13 required contents of the release yaml file are different for each type
14 of release, see the schemas and examples shown below.  The version in
15 the release yaml file must be a valid Semantic Versioning (SemVer)
16 string, matching either the pattern "v#.#.#" or "#.#.#" where "#" is
17 one or more digits.  Upon merge of the change, Jenkins will sign the
18 reference extrapolated by log_dir and promote the artifact.
19
20 .. note::
21
22    The release file regex is: (releases\/.*\.yaml|\.releases\/.*\.yaml).
23    In words, the directory name can be ".releases" or "releases"; the file
24    name can be anything with suffix ".yaml".
25
26 The build node for all release jobs must be CentOS, which supports the
27 sigul client for accessing a signing server. The build node for
28 container release jobs must have Docker installed.
29
30 A Jenkins admin user can also trigger a release job via the "Build
31 with parameters" action, removing the need to create and merge a
32 release yaml file.  The user must enter parameters in the same way as
33 a release yaml file, except for the special USE_RELEASE_FILE and
34 DRY_RUN check boxes. The user must uncheck the USE_RELEASE_FILE check
35 box if the job should run without a release file, instead passing the
36 required information as build parameters. The user can check the
37 DRY_RUN check box to test the job while skipping upload of files to
38 the release repository.
39
40 For example, the parameters for a Maven release are as follows::
41
42     GERRIT_BRANCH = master
43     VERSION = 1.0.0
44     LOG_DIR = example-project-maven-stage-master/17/
45     DISTRIBUTION_TYPE = maven
46     USE_RELEASE_FILE = false
47     DRY_RUN = false
48
49 Maven Release Files
50 -------------------
51
52 An example of a maven release file appears below.
53
54 .. code-block:: none
55
56     $ cat releases/maven-release.yaml
57     ---
58     distribution_type: maven
59     log_dir: example-project-maven-stage-master/17/
60     project: example-project
61     version: 1.0.0
62
63
64 The following parameters must appear in a maven release yaml file.
65
66 :Required Parameters:
67
68     :distribution_type: Must be "maven".
69     :log_dir: The suffix of the logs URL reported on completion by the
70         Jenkins stage job that created and pushed the artifact
71         to the staging repository.  For example, use value
72         "example-project-maven-stage-master/17" for the logs URL
73         https://logs.lf-project.org/production/vex-sjc-lfp-jenkins-prod-1/example-project-maven-stage-master/17
74     :project: The name of the project.
75     :version: The semantic version string used for the artifact.
76
77 The JSON schema for a maven release file appears below.
78
79 .. code-block:: none
80
81     ---
82     $schema: "http://json-schema.org/schema#"
83     $id: "https://github.com/lfit/releng-global-jjb/blob/master/release-schema.yaml"
84
85     required:
86       - "distribution_type"
87       - "log_dir"
88       - "project"
89       - "version"
90
91     properties:
92       distribution_type:
93         type: "string"
94       log_dir:
95         type: "string"
96       project:
97         type: "string"
98       version:
99         type: "string"
100
101
102 Container Release Files
103 -----------------------
104
105 An example of a container release file appears below.
106
107 .. code-block:: none
108
109     $ cat releases/container-release.yaml
110     ---
111     distribution_type: container
112     container_release_tag: 1.0.0
113     container_pull_registry: nexus.onap.org:10003
114     container_push_registry: nexus.onap.org:10002
115     project: test
116     ref: d1b9cd2dd345fbeec0d3e2162e008358b8b663b2
117     containers:
118         - name: test-backend
119           version: 1.0.0-20190806T184921Z
120         - name: test-frontend
121           version: 1.0.0-20190806T184921Z
122
123
124 The following parameters must appear in a container release yaml file.
125
126 :Required Parameters:
127
128     :distribution_type: Must be "container".
129     :container_release_tag: The string to use as a Docker tag on all
130         released containers.
131     :container_pull_registry: The Nexus registry that supplies the staged
132         image(s).
133     :container_push_registry: The Nexus registry that receives the released
134         image(s).
135     :project: The name of the project.
136     :ref: The git commit reference (SHA-1 code) to tag with the version string.
137     :containers: A list of name and version (tag) pairs that specify the
138         Docker images in the container-pull registry to promote to the
139         container-push registry.
140
141 The JSON schema for a container release file appears below.
142
143 .. code-block:: none
144
145     ---
146     $schema: "http://json-schema.org/schema#"
147     $id: "https://github.com/lfit/releng-global-jjb/blob/master/release-container-schema.yaml"
148
149     required:
150       - "containers"
151       - "distribution_type"
152       - "project"
153       - "container_release_tag"
154       - "ref"
155
156     properties:
157       containers:
158         type: "array"
159         properties:
160           name:
161             type: "string"
162           version:
163             type: "string"
164         additionalProperties: false
165       distribution_type:
166         type: "string"
167       project:
168         type: "string"
169       container_release_tag:
170         type: "string"
171       container_pull_registry"
172         type: "string"
173       container_push_registry"
174         type: "string"
175       ref:
176         type: "string"
177
178
179 PyPI Release Files
180 ------------------
181
182 An example of a PyPI release file appears below. Name of the release file must
183 start with "pypi". For example releases/pypi-1.0.0-mypackage.yaml
184
185 .. code-block:: none
186
187     $ cat releases/pypi-1.0.0-mypackage.yaml
188     ---
189     pypi_project: mypackage
190     python_version: '3.4'
191     version: 1.0.0
192     log_dir: example-project-pypi-merge-master/17
193
194
195 The following parameters must appear in the PyPI release yaml file.
196 These are not part of the Jenkins job definition to allow independent
197 self-release of a package maintained in a git repository with other
198 packages.
199
200 :Required Parameters:
201
202     :log_dir: The suffix of the logs URL reported on completion by the
203         Jenkins merge job that created and pushed the distribution files
204         to the staging repository.  For example, use value
205         "example-project-pypi-merge-master/17" for the logs URL
206         https://logs.lf-project.org/production/vex-sjc-lfp-jenkins-prod-1/example-project-pypi-merge-master/17
207     :pypi_project: The PyPI project name at the staging and
208         release repositories, for example "mypackage".
209     :python_version: The Python interpreter version to use for pip
210         "Requires-Python" compatibility checks, for example '3', '3.7' or 3.7.4.
211         Put valid decimal values such as 3 or 3.7 in quotes to pass schema validation.
212     :version: The semantic version string used for the package in the
213         setup.py file.
214
215 The JSON schema for a PyPI release file appears below.
216
217 .. code-block:: none
218
219     ---
220     $schema: "http://json-schema.org/schema#"
221     $id: "https://github.com/lfit/releng-global-jjb/blob/master/release-pypi-schema.yaml"
222
223     required:
224       - "log_dir"
225       - "pypi_project"
226       - "python_version"
227       - "version"
228
229     properties:
230       log_dir:
231         type: "string"
232       pypi_project:
233         type: "string"
234       python_version:
235         type: "string"
236       version:
237         type: "string"
238
239
240 PackageCloud Release Files
241 --------------------------
242
243 An example of a PackageCloud release file appears below. Name of release file
244 must start with "packagecloud". For example releases/packagecloud-1.6-tree.yaml
245
246 .. code-block:: none
247
248     $ cat releases/packagecloud-1.6-tree.yaml
249     ---
250     package_name:
251         - name: tree-1.6.0-10.el7.x86_64.rpm
252         - name: test.rpm
253
254 The following parameters must appear in the PackageCloud release yaml file.
255 These are not part of the Jenkins job definition to allow independent
256 self-release of a package maintained in a git repository with other
257 packages.
258
259 :Required Parameters:
260
261     :package_name: A list of names that specify the packages to promote.
262         (Found in jenkins console log when using gem to push package eg.
263         "Pushing /path/of/package/name-of-package.rpm... success!"
264         OR using rest api call to query packagecloud.io repo
265         "curl https://packagecloud.io/api/v1/repos/test_user/test_repo/search?q=
266         | yq -r .[].filename"
267
268 The JSON schema for a PackageCloud release file appears below.
269
270 .. code-block:: none
271
272     ---
273     $schema: "http://json-schema.org/schema#"
274     $id: "https://github.com/lfit/releng-global-jjb/blob/master/packagecloud-release-schema"
275
276     required:
277       - "package_name"
278
279     properties:
280       package_name:
281         type: "array"
282         properties:
283           name:
284             type: "string"
285
286 Jenkins Jobs
287 ------------
288
289 An example of a Jenkins job configuration that uses the global-jjb
290 templates for maven and container release jobs appears next.
291
292 .. code-block:: none
293
294     - project:
295         name: my-project-release
296         project: my-project
297         project-name: my-project
298         build-node: centos7-docker-4c-4g
299         mvn-settings: my-project-settings
300         jobs:
301             - '{project-name}-gerrit-release-jobs'
302
303
304 .. note::
305
306    Release Engineers: please follow the setup guide below before adding the job definition.
307
308
309 JJB Macros
310 ----------
311
312 lf-release
313 ~~~~~~~~~~
314
315 Release verify and merge jobs are the same except for their scm,
316 trigger, and builders definition. This anchor is the common template.
317
318 JJB Templates
319 -------------
320
321 Release Merge
322 ~~~~~~~~~~~~~
323
324 This template supports Maven and Container release jobs.
325
326 :Template Name: {project-name}-release-merge
327
328 :Comment Trigger: remerge
329
330 :Required parameters:
331
332     :build-node: The node to run build on.
333     :jenkins-ssh-release-credential: Credential to use for SSH. (Generally set
334         in defaults.yaml)
335     :project: Git repository name
336     :project-name: Jenkins job name prefix
337
338 :Optional parameters:
339
340     :build-days-to-keep: Days to keep build logs in Jenkins. (default: 7)
341     :build-timeout: Timeout in minutes before aborting build. (default: 15)
342
343     :gerrit_merge_triggers: Override Gerrit Triggers.
344     :gerrit_trigger_file_paths: Override file paths filter which checks which
345         file modifications will trigger a build.
346         **default**::
347
348             - compare-type: REG_EXP
349               pattern: '(releases\/.*\.yaml|\.releases\/.*\.yaml)'
350
351
352 Release Verify
353 ~~~~~~~~~~~~~~
354
355 This template supports Maven and Container release jobs.
356
357 :Template Name: {project-name}-release-verify
358
359 :Comment Trigger: recheck|reverify
360
361 :Required Parameters:
362
363     :build-node: The node to run build on.
364     :jenkins-ssh-credential: Credential to use for SSH. (Generally set
365         in defaults.yaml)
366     :project: Git repository name
367     :project-name: Jenkins job name prefix
368
369 :Optional Parameters:
370
371     :build-days-to-keep: Days to keep build logs in Jenkins. (default: 7)
372     :build-node: The node to run build on.
373     :build-timeout: Timeout in minutes before aborting build. (default: 15)
374     :gerrit-skip-vote: Skip voting for this job. (default: false)
375     :git-url: URL clone project from. (default: $GIT_URL/$PROJECT)
376
377     :gerrit_verify_triggers: Override Gerrit Triggers.
378     :gerrit_trigger_file_paths: Override file paths filter which checks which
379         file modifications will trigger a build.
380         **default**::
381
382             - compare-type: REG_EXP
383               pattern: '(releases\/.*\.yaml|\.releases\/.*\.yaml)'
384
385
386 PyPI Release Merge
387 ~~~~~~~~~~~~~~~~~~
388
389 Publishes a Python package on merge of a patch set with a release yaml
390 file. Checks the format of the version string, downloads the package
391 artifacts from the PyPI staging repository, uploads the package
392 artifacts to the PyPI release repository, tags the git repository,
393 signs the tag and pushes the tag to the git server. The release verify
394 template accepts neither a branch nor a stream parameter.
395
396 :Template Names:
397
398     - {project-name}-pypi-release-merge
399     - gerrit-pypi-release-merge
400     - github-pypi-release-merge
401
402 :Comment Trigger: remerge
403
404 :Required Parameters:
405
406     :build-node: The node to run build on, which must be Centos.
407     :jenkins-ssh-release-credential: Credential to use for SSH. (Generally set
408         in defaults.yaml)
409     :project: Git repository name
410     :project-name: Jenkins job name prefix
411
412 :Optional Parameters:
413
414     :build-days-to-keep: Days to keep build logs in Jenkins. (default: 7)
415     :build-timeout: Timeout in minutes before aborting build. (default: 15)
416     :disable-job: Whether to disable the job (default: false)
417     :git-url: URL clone project from. (default: $GIT_URL/$PROJECT)
418     :pypi-stage-index: Base URL of the PyPI staging repository.
419         (default https://test.pypi.org/simple)
420     :pypi-repo: Key for the PyPI release repository in the .pypirc file,
421         should be the repository pypy.org. (default: pypi)
422     :use-release-file: Whether to use the release file. (default: true)
423
424     :gerrit_trigger_file_paths: Override file paths filter which checks which
425         file modifications will trigger a build.
426         **default**::
427
428             - compare-type: REG_EXP
429               pattern: '(releases\/pypi.*\.yaml|\.releases\/pypi.*\.yaml)'
430
431 PyPI Release Verify
432 ~~~~~~~~~~~~~~~~~~~
433
434 Verifies a Python package project on creation of a patch set with a
435 release yaml file. Checks the contents of the release yaml file,
436 checks the format of the version string, and downloads the release
437 artifacts from the specified PyPI staging repository. The release
438 verify template accepts neither a branch nor a stream parameter.
439
440 :Template Names:
441
442     - {project-name}-pypi-release-verify
443     - gerrit-pypi-release-verify
444     - github-pypi-release-verify
445
446 :Comment Trigger: recheck
447
448 :Required Parameters:
449
450     :build-node: The node to run build on, which must be Centos.
451     :jenkins-ssh-credential: Credential to use for SSH. (Generally set
452         in defaults.yaml)
453     :project: Git repository name
454     :project-name: Jenkins job name prefix
455
456 :Optional Parameters:
457
458     :build-days-to-keep: Days to keep build logs in Jenkins. (default: 7)
459     :build-timeout: Timeout in minutes before aborting build. (default: 15)
460     :disable-job: Whether to disable the job (default: false)
461     :git-url: URL clone project from. (default: $GIT_URL/$PROJECT)
462     :pypi-stage-index: Base URL of the PyPI staging repository.
463         (default https://test.pypi.org/simple)
464     :pypi-repo: Key for the PyPI release repository in the .pypirc file,
465         should be the repository pypy.org (default: pypi)
466     :use-release-file: Whether to use the release file. (default: true)
467
468     :gerrit_trigger_file_paths: Override file paths filter which checks which
469         file modifications will trigger a build.
470         **default**::
471
472             - compare-type: REG_EXP
473               pattern: '(releases\/pypi.*\.yaml|\.releases\/pypi.*\.yaml)'
474
475 PackageCloud Release Verify
476 ~~~~~~~~~~~~~~~~~~~~~~~~~~~
477
478 This template supports PackageCloud release jobs.
479
480 :Template Name: {project-name}-packagecloud-release-verify
481
482 :Comment Trigger: recheck|reverify
483
484 :Required Parameters:
485
486     :build-node: The node to run build on.
487     :jenkins-ssh-credential: Credential to use for SSH. (Generally set
488         in defaults.yaml)
489     :project: Git repository name
490     :project-name: Jenkins job name prefix
491
492 :Optional Parameters:
493
494     :build-days-to-keep: Days to keep build logs in Jenkins. (default: 7)
495     :build-node: The node to run build on.
496     :build-timeout: Timeout in minutes before aborting build. (default: 15)
497     :gerrit-skip-vote: Skip voting for this job. (default: false)
498     :git-url: URL clone project from. (default: $GIT_URL/$PROJECT)
499
500     :gerrit_verify_triggers: Override Gerrit Triggers.
501     :gerrit_trigger_file_paths: Override file paths filter which checks which
502         file modifications will trigger a build.
503         **default**::
504
505             - compare-type: REG_EXP
506               pattern: '(releases\/packagecloud.*\.yaml|\.releases\/packagecloud.*\.yaml)'
507
508
509 PackageCloud Release Merge
510 ~~~~~~~~~~~~~~~~~~~~~~~~~~
511
512 This template supports PackageCloud release jobs.
513
514 :template name: {project-name}-packagecloud-release-merge
515
516 :comment trigger: remerge
517
518 :required parameters:
519
520     :build-node: the node to run build on.
521     :jenkins-ssh-release-credential: credential to use for ssh. (generally set
522         in defaults.yaml)
523     :project: git repository name
524     :project-name: jenkins job name prefix
525
526 :optional parameters:
527
528     :build-days-to-keep: days to keep build logs in jenkins. (default: 7)
529     :build-timeout: timeout in minutes before aborting build. (default: 15)
530
531     :gerrit_merge_triggers: override gerrit triggers.
532     :gerrit_trigger_file_paths: override file paths filter which checks which
533         file modifications will trigger a build.
534         **default**::
535
536             - compare-type: reg_exp
537               pattern: '(releases\/packagecloud.*\.yaml|\.releases\/packagecloud.*\.yaml)'
538
539
540 Setup for LFID, Nexus, Jenkins and Gerrit
541 -----------------------------------------
542
543 This section is for the Linux Foundation release engineering team.
544
545 LFID
546 ~~~~
547
548 Create an ``lfid`` and an ``ssh-key``
549
550 ``YOUR_RELEASE_USERNAME`` for example: onap-release
551
552 ``YOUR_RELEASE_EMAIL`` for example: collab-it+onap-release@linuxfoundation.org
553
554 ssh-key example:
555
556 .. code-block:: bash
557
558    ssh-keygen -t rsa -C "collab-it+odl-release@linuxfoundation.org"  -f /tmp/odl-release
559
560
561 `Create an LFID with the above values <https://identity.linuxfoundation.org>`_
562
563
564 Nexus
565 ~~~~~
566
567 Create a Nexus account called ``'jenkins-release'`` with promote privileges.
568
569 .. image:: ../_static/nexus-promote-privs.png
570
571 Gerrit
572 ~~~~~~
573
574 Log into your Gerrit with ``YOUR_RELEASE_USERNAME``, upload the public
575 part of the ``ssh-key`` you created earlier. Log out of Gerrit and log
576 in again with your normal account for the next steps.
577
578
579 In Gerrit create a new group called ``self-serve-release`` and give it
580 direct push rights via ``All-Projects`` Add ``YOUR_RELEASE_USERNAME``
581 to group ``self-serve-release`` and group ``Non-Interactive Users``
582
583
584 In All project, grant group self-serve-release the following:
585
586 .. code-block:: none
587
588     [access "refs/heads/*"]
589       push = group self-serve-release
590     [access "refs/tags/*"]
591       createTag = group self-serve-release
592       createSignedTag = group self-serve-release
593       forgeCommitter = group self-serve-release
594       push = group self-serve-release
595
596
597 Jenkins
598 ~~~~~~~
599
600 Add a global credential to Jenkins called ``jenkins-release`` and set
601 the ID: ``'jenkins-release'`` as its value insert the private half of
602 the ``ssh-key`` that you created for your Gerrit user.
603
604 Add Global variables in Jenkins:
605 Jenkins configure -> Global properties -> Environment variables::
606
607     RELEASE_USERNAME = YOUR_RELEASE_USERNAME
608     RELEASE_EMAIL = YOUR_RELEASE_EMAIL
609
610
611 .. note::
612
613     Add these variables to your global-vars-$SILO.sh file or they will
614     be overwritten.
615
616 Jenkins configure -> Managed Files -> Add a New Config -> Custom File
617
618 .. code-block:: none
619
620     id: signing-pubkey
621     Name: SIGNING_PUBKEY (optional)
622     Comment: SIGNING_PUBKEY (optional)
623
624     Content: (Ask Andy for the public signing key)
625     -----BEGIN PGP PUBLIC KEY BLOCK-----
626
627
628 Add or edit the managed file in Jenkins called ``lftoolsini``,
629 appending a nexus section: Jenkins Settings -> Managed files -> Add
630 (or edit) -> Custom file
631
632 .. code-block:: none
633
634    [nexus.example.com]
635    username=jenkins-release
636    password=<plaintext password>
637
638 Ci-management
639 ~~~~~~~~~~~~~
640
641 Upgrade your project's global-jjb if needed, then add the following to
642 your global defaults file (e.g., jjb/defaults.yaml).
643
644 .. code-block:: none
645
646    jenkins-ssh-release-credential: jenkins-release