From ace5221576580c5b83388d3b20736ccd81dfddec Mon Sep 17 00:00:00 2001 From: Martyn Welch <martyn.welch@collabora.com> Date: Wed, 12 May 2021 09:20:15 +0100 Subject: [PATCH] Rework component guide The workflows in component guide target Apertis maintainers more than developers, it is also out-of-date in some places. Update this guide and make it more relevant to non-maintainers in the process. Signed-off-by: Martyn Welch <martyn.welch@collabora.com> --- content/guides/component_guide.md | 1210 +++++++++++++++---------- static/images/run-pipeline-button.png | Bin 6229 -> 2562 bytes 2 files changed, 716 insertions(+), 494 deletions(-) diff --git a/content/guides/component_guide.md b/content/guides/component_guide.md index be04955b9..61b652708 100644 --- a/content/guides/component_guide.md +++ b/content/guides/component_guide.md @@ -7,403 +7,613 @@ toc = true title = "Adding and Updating Components" +++ -# Apertis Packaging CI - Apertis stores the source of all the shipped packages in GitLab and uses a [GitLab CI pipeline](https://gitlab.apertis.org/infrastructure/ci-package-builder/-/blob/master/ci-package-builder.yml) to manage the workflows and automate many of the tasks that are required to -release a package: +release a package, thus for many tasks such as adding or updating packages, +interaction is only required with GitLab, with automation taking care of the +rest of the process. + +{{% notice info %}} +Please see the [Apertis workflow]({{< ref "workflow-guide.md" >}}) for more +information regarding the automation provided by Apertis. +{{% /notice %}} -* Pull updates from upstream distributions like Debian 10 Buster. -* Test any changes made to development and release branches. -* Push updated sources for release branches that pass testing to OBS. From here, - fresh binary packages will either be built and added to the relevant Debian - repository or snapshot repository, depending on the release state of the - component. +{{% notice tip %}} +The VirtualBox-based +[Apertis SDK virtual machine images]( {{< ref "virtualbox.md" >}} ) ship with +all the needed tools installed, providing a reliable, self-contained +environment ready to be used. Alternatively, you can run the Apertis +`package-source-builder` Docker container. -## License scans +For v2021 and newer: -As contributors submit merge requests to packaged software, the CI pipeline performs -license scans on those packages, scanning all files in the package, -not just the new submission. The pipeline fails or emits a warning (depending on -the configuration) when it finds files with unknown or unclear licensing terms, -or files under licenses not allowed in the package. When such situation arises, -it is the responsibility of the submitter to perform the review of the license -scan results and make updates to the package if necessary. + APERTIS_RELEASE=v2021 + docker pull registry.gitlab.apertis.org/infrastructure/apertis-docker-images/${APERTIS_RELEASE}-package-source-builder + docker run -it --rm --env HOME -w "$(pwd)" -v "$HOME:$HOME" -v "$HOME:/root" --security-opt label=disable registry.gitlab.apertis.org/infrastructure/apertis-docker-images/${APERTIS_RELEASE}-package-source-builder bash -When the license scan mistakenly identifies a file as being under an incorrect -license, or fails to process it correctly, there are three ways to fix this: +For v2020 and older: - 1. Specify the correct copyright and the license in `debian/apertis/copyright.yml`. - The format of the file is specified in the - [Dpkg::Copyright::Scanner](https://manpages.debian.org/buster/libconfig-model-dpkg-perl/Dpkg::Copyright::Scanner.3pm.en.html) - manpage. - In short, it’s a YAML file mapping paths to their licensing information: + APERTIS_RELEASE=v2020 + docker pull docker-registry.apertis.org/apertis/apertis-${APERTIS_RELEASE}-package-source-builder + docker run -it --rm --env HOME -w "$(pwd)" -v "$HOME:$HOME" -v "$HOME:/root" --security-opt label=disable docker-registry.apertis.org/apertis/apertis-${APERTIS_RELEASE}-package-source-builder bash - debian: - copyright: 2015, Marcel - license: Expat - src/: - copyright: 2016, Joe - license: Expat - .*/NOTICE: - skip: 1 - src/garbled/: - 'override-copyright': 2016 Marcel MeXzigue +{{% /notice %}} - File patterns follow the Perl regular expression rules, and are matched - from the beginning of a path. Patterns are used in the order from the most - specific to the least specific ones. +# Adding New Components - Please also verify `debian/copyright` specifies the correct license, and if it - doesn’t, submit a patch to Debian. +The software components used in Apertis images are packaged in the +[`deb` packaging format](https://wiki.debian.org/Packaging), as used by Debian. +It is preferred, where possible, to add additional packages from Debian as +covered by the +[contribution policy]({{< ref "contributions.md#adding-components-to-apertis" >}}). - 2. Add the file to the list of ignored files. - `debian/apertis/copyright.whitelist` is formatted the same way as `gitignore`, - please refer to the [gitignore](https://manpages.debian.org/buster/git-man/gitignore.5.en.html) - manpage for more information. +## Adding New Packages from Debian - 3. If the file is under a license not suitable for Apertis, it can be removed from - the package by either repackaging the tarball or patching it out, in which case - the scanner will not take it into account. +{{% notice info %}} +As the adding of existing Debian packages is mostly scripted/automated it is +expected that such actions will be carried out by maintainers after a request +made in line with the +[contribution policy]({{< ref "contributions.md#adding-components-to-apertis" >}}). +{{% /notice %}} -The license scanner will store the automatically generated copyright report file -under `debian/apertis/copyright`, updating the merge request when necessary. +This is the process to import a new package from Debian to Apertis: -[Dpkg::Copyright::Scanner]: https://manpages.debian.org/testing/libconfig-model-dpkg-perl/Dpkg::Copyright::Scanner.3pm.en.html -[gitignore]: https://manpages.debian.org/testing/git-man/gitignore.5.en.html +* Create a folder, in the name of the package to import. + * Eg. for package `hello`, run: -## Custom pipelines + mkdir hello -When using the packaging pipeline, developers cannot put their CI/CD automation -in `.gitlab-ci.yml` anymore, as the CI config path points to the -ci-package-builder definition. + * chdir to created folder: -However, developers can put their jobs in the -`debian/apertis/local-gitlab-ci.yml` file and have them executed in a child -pipeline whenever the main packaging pipeline is executed. This is especially -handy to run tests before the actual packaging process begins. + cd hello -{{% notice tip %}} -The instructions below assume an Apertis development enviroment. Either boot -the [Apertis SDK]( {{< ref "virtualbox.md" >}} ) or run the -Apertis `package-source-builder` Docker container: +* Invoke `import-debian-package` from the + [packaging-tools repository](https://gitlab.apertis.org/infrastructure/packaging-tools/). + To fetch the latest version: - APERTIS_RELEASE=v2021 - docker pull registry.gitlab.apertis.org/infrastructure/apertis-docker-images/${APERTIS_RELEASE}-package-source-builder - docker run -it --rm --env HOME -w "$(pwd)" -v "$HOME:$HOME" -v "$HOME:/root" --security-opt label=disable registry.gitlab.apertis.org/infrastructure/apertis-docker-images/${APERTIS_RELEASE}-package-source-builder bash + import-debian-package --upstream buster --downstream apertis/v2021 --component target --package hello + + To fetch a specific version, add the `--version` option: + + import-debian-package --upstream buster --downstream apertis/v2021 --component target --package hello --version 2.10-2 + + * The argument to `--component` reflects the repository component it is part + of (for instance, `target`); it will be stored in + `debian/apertis/component`. + * Multiple downstream branches can be specified, in which case all of them + will be updated to point to the newly imported package version. + * The Apertis version of the package will have a local suffix (`apertis0`) + appended. + + {{% notice warning %}} + Don't use `import-debian-package` on existing repositories, it does not + attempt to merge `apertis/*` branches and instead it re-sets them to new + branches based on the freshly imported Debian package. + {{% /notice %}} + +* Create an empty project on GitLab under the `pkg` namespace (for instance, + `pkg/hello`). +* Configure the origin remote on your local git: + + git remote add origin git@gitlab.apertis.org:pkg/hello + +* Push your local git contents to the newly created GitLab project: + + git push --all --follow-tags origin + +* Set it up with `gitlab-rulez` from the + [gitlab-rulez repository](https://gitlab.apertis.org/infrastructure/gitlab-rulez): + + gitlab-rulez apply rulez.yaml --filter pkg/hello + + {{% notice info %}} + This: + - sets the CI config path to + `ci-package-builder.yml@infrastructure/ci-package-builder` + - changes the merge request settings to: + - only allow fast-forward merges + - ensure merges are only allowed if pipelines succeed + - marks the `apertis/*` and `debian/*` branches as protected + {{% /notice %}} + +* As the CI configuration was set by `gitlab-rulez` after the initial commit, + it will be necessary to run the CI/CD pipeline on each `apertis/*` branch to + push the package through to OBS. + + {{% notice warning %}} + Ensure that one branch successfully completes it's upload to OBS before + starting other branches to ensure that the different branches don't conflict + over uploading the tarballs. + {{% /notice %}} + +## Adding New Packages from Upstream Sources + +There are likely to be instances where it is desirable to import the latest +version of a piece of software into Apertis directly from it's original authors +or maintainers. This may be as a result of the software in question not being +packaged by Apertis' default upstream distribution, Debian, or their being a +mismatch between the desired version in the upstream distribution and what is +required for a specific goal. + +For example, the +[Apertis release flow]( {{< ref "release-flow.md#apertis-release-flow" >}}) +stipulates that each Apertis release should include the latest mainline kernel +LTS release. Due to Debian's release cadence being approximately half that of +Apertis', there are 2 Apertis releases for each Debian stable release and no +guarantees that the kernel's packaged for Debian's current stable or in +progress releases will align with Apertis' requirements. As a result it is +expected that Apertis will occasionally need to take its kernel from the +mainline kernel LTS tree to satisfy it's requirements. + +{{% notice warning %}} +Such packages will require special attention to assure that they remain +up-to-date with any security releases made by the upstream and updated as and +when apropriate. {{% /notice %}} -# Adding new components +Unless the imported package can be used as-is without any modification, there +will be a +[patch series]( {{< ref "buildingpatchingandmaintainingtheapertiskernel.md#packaging" >}} ) +that potentially needs tweaking to apply after the update. The workflow set +out below takes this into consideration. -The software components used in Apertis images are packaged in the -[packaging format](https://wiki.debian.org/Packaging) used by Debian. +Below we use the process of importing +[GNU Hello](https://www.gnu.org/software/hello/) application as an example. -## Adding new packages from Scratch +- Using the Gitlab Web UI, create an empty project in your personal area, for + example called `hello`. -To package a component from scratch, Debian provides [a short guide to get -started](https://wiki.debian.org/Packaging/Intro). +- Download the latest release tarball from upstream. At the time of writing + this is [`hello-2.10.tar.gz`](https://ftp.gnu.org/gnu/hello/) for GNU Hello. -{{% notice tip %}} -The VirtualBox-based -[Apertis SDK virtual machine images]( {{< ref "virtualbox.md" >}} ) ship with -all the needed tools installed, providing a reliable, self-contained -environment ready to be used. +- Extract the tarball and enter the extracted folder + + $ tar xf hello-2.10.tar.gz + $ cd hello-2.10 + +- Create a new git repository and commit the whole source tree; this will + create the `upstream/apertis` branch containing the untouched upstream source + code: + + $ git init + $ git checkout -b upstream/apertis + $ git add . + $ git commit -s -m "Initial commit of GNU Hello 2.10" + +- Commit the original tarball to the `pristine-lfs` branch: + + $ pristine-lfs commit ../hello-2.10.tar.gz + +- Create the packaging branch for the Apertis version you're targetting, for + example if you are targetting Apertis v2021, create the `apertis/v2021` + branch: + + $ APERTIS_RELEASE=v2021 + $ git checkout -b apertis/${APERTIS_RELEASE} + +- Add packaging files and commit them to the packaging branch. + + {{% notice info %}} + Debian packaging is not covered by this document, users interested in that + matter should refer to the + [Debian Packaging Intro](https://wiki.debian.org/Packaging/Intro), + [Debian Policy Manual](https://www.debian.org/doc/debian-policy/) and + [Debian Developer's Reference](https://www.debian.org/doc/manuals/developers-reference/). + {{% /notice %}} + + {{% notice tip %}} + If you are packaging a newer version of a component which is already + available in Debian, starting from the existing Debian packaging may save you + considerable time. + {{% /notice %}} + +- Ensure that the package builds for you locally: + + $ gbp buildpackage -uc -us --git-debian-branch=apertis/${APERTIS_RELEASE} --git-upstream-tree=upstream/apertis + +- Add the Gitlab project you created earlier as the `origin` git remote + (replacing `<username>` with your GitLab username): + + $ GITLAB_USER=<username> + $ git remote add origin git@gitlab.apertis.org:${GITLAB_USER}/hello.git + +- Push your branches to the repository: + + $ git push --all --follow-tags origin + +{{% notice info %}} +If you wish to submit this package for inclusion in the Apertis packages, please make yourself familiar with the [contribution policy]({{< ref "contributions.md#adding-components-to-apertis" >}}). {{% /notice %}} -Once the component has been packaged, its sources can be uploaded to GitLab in -a personal project, such that the developer is free to experiment and iterate -until the component is ready to be submitted to the appropriate GitLab project. +# Updating Existing Components -## Adding new packages from Debian +Once we have components added to Apertis, it is important that we keep them up +to date with any security updates that are made available. -This is the process to import a new package from Debian to Apertis: +## Updating Components from Debian + +Updates coming from Debian have been automated using a CI/CD pipeline. Such +updates are usually triggered from the +[infrastructure dashboard](https://infrastructure.pages.apertis.org/dashboard/) +but can be manually triggered from the GitLab web UI. -* create a folder, in the name of the package to import. - * Eg. for package `hello`, run: `mkdir hello` - * chdir to created folder: `cd hello` -* invoke `import-debian-package` from the [packaging-tools - repository:](https://gitlab.apertis.org/infrastructure/packaging-tools/) - * fetch a specific version: `import-debian-package --upstream buster --downstream apertis/v2020dev0 --component target --package hello --version 2.10-2` - * fetch the latest version: `import-debian-package --upstream buster --downstream apertis/v2020dev0 --component target --package hello` - * the argument to `--component` reflects the repository component it is part of (for instance, `target`); it will be stored in `debian/apertis/component` - * multiple downstream branches can be specified, in which case all of them - will be updated to point to the newly imported package version - * the Apertis version of the package will have a local suffix (`apertis0`) appended - * don't use `import-debian-package` on existing repositories, it does not - attempt to merge `apertis/*` branches and instead it re-sets them to new - branches based on the freshly imported Debian package -* create an empty project on GitLab under the `pkg/*` namespaces (for instance, `pkg/hello`) -* configure the origin remote on your local git: `git remote add origin git@gitlab.apertis.org:pkg/hello` -* push your local git contents to the newly created GitLab project: `git push --all --follow-tags origin` -* set it up with `gitlab-rulez apply rulez.yaml --filter pkg/hello` from - the [gitlab-rulez repository](https://gitlab.apertis.org/infrastructure/gitlab-rulez) - * sets the CI config path to `ci-package-builder.yml@infrastructure/ci-package-builder` - * changes the merge request settings: - * only allow fast-forward merges - * ensure merges are only allowed if pipelines succeed - * marks the `apertis/*` and `debian/*` branches as protected -* follow the process described in the [section about landing downstream changes - to the main archive](#landing-downstream-changes-to-the-main-archive) above to - publish the package on OBS. - -# Updating existing components - -## Pulling updates or security fixes from upstream distributions - -Updates coming from upstream can be pulled it by triggering a CI pipeline on a -branches like `debian/buster` or `debian/bullseye`. - -The pipeline will check the Debian archive for updates, pull them in the +{{% notice note %}} +This functionality will only be available to users with sufficient GitLab +privileges to enable them to run CI/CD pipelines. +{{% /notice %}} + +To trigger the updates pipeline: +- Navigate to the "Pipelines" page of the component in GitLab. +- Click on the `Run pipeline` button in the top right-hand corner. + +- Select the relevant `debian/*` branch that you would like to update (such as + `debian/bullseye`) under `Run for branch name or tag` and click the `Run + pipeline` button shown on that page. + +The pipeline will check the Debian archive for updates, pull them in to the `debian/$RELEASE`-like branch (for instance, `debian/bullseye` or `debian/bullseye-security`), try to merge the new contents with the matching -`apertis/*` branches and, if successful, push a -proposed updates branch while creating a Merge Request for each `apertis/*` -branches it should be landed on. +`apertis/*` branches and, if successful, will create a merge request for +each `apertis/*` branch that requires updating. -The upstream update pipeline is usually triggered from -[the infrastructure dashboard](https://infrastructure.pages.apertis.org/dashboard/) -but can be manually triggered from the GitLab web UI by selecting the -`Run Pipeline` button in the `Pipelines` page of each repository under `pkg/*` -and selecting the `debian/bullseye` branch as the reference. +## Manually Updating Components from Debian - +Upstream updates are usually handled automatically by the +[`ci-package-builder.yml`](https://gitlab.apertis.org/infrastructure/ci-package-builder/) +Continous Integration pipeline, which +[fetches upstream packages, merges them]({{< ref "component_guide.md#updating-components-from-debian" >}}) +with the Apertis contents and directly creates Merge Requests to be reviewed by +[maintainers]({{< ref "contributions.md#the-role-of-maintainers" >}}). + +{{% notice warning %}} +The +[automated pipeline]({{< ref "component_guide.md#updating-components-from-debian" >}}) +should be used to perform this task where possible. + +This guide uses tools that are only provided in the package-source-builder +image. The easiest way to perform this task is to utilise the docker container. +{{% /notice %}} + +However, in some cases it may be necessary to manually perform these +operations. + +- Check out the source repository + + $ GITLAB_GROUP=pkg + $ PACKAGE=hello + $ git clone git@gitlab.apertis.org:${GITLAB_GROUP}/${PACKAGE} + $ cd ${PACKAGE} + + {{% notice note %}} + When handling packages in your personal GitLab namespace, `GITLAB_GROUP` + should point to that, which is your GitLab username, rather than the main + Apertis application group `pkg`. + {{% /notice %}} + +- Ensure we have the required `debian/` and `upstream/` branches locally + + $ CURRENT_UPSTREAM=buster + $ git branch debian/${CURRENT_UPSTREAM} origin/debian/${CURRENT_UPSTREAM} + $ git branch upstream/${CURRENT_UPSTREAM} origin/upstream/${CURRENT_UPSTREAM} + +- Ensure we have a `pristine-lfs` branch locally: + + $ git branch pristine-lfs origin/pristine-lfs + +- Pull in the latest updates Debian from using the `apertis-pkg-pull-updates` script + + $ APERTIS_RELEASE=v2021 + $ MIRROR=https://deb.debian.org/debian + $ git checkout -b apertis/${APERTIS_RELEASE} origin/apertis/${APERTIS_RELEASE} + $ apertis-pkg-pull-updates --package=${PACKAGE} --upstream=${CURRENT_UPSTREAM} --mirror=${MIRROR} + + This will update the `debian/...`, `upstream/...` and `pristine-lfs` branches + as prepared previously. + +- Ensure that the changes to these branches are pushed to your remote `origin`. + It is important that these branches are pushed and in sync with the default + remote. + + $ git push origin --follow-tags pristine-lfs debian/${CURRENT_UPSTREAM} upstream/${CURRENT_UPSTREAM} + +- The upstream changes now need to be merged into the apertis branch. We will + do this via a development branch that can be pushed for review. + + $ PROPOSED_BRANCH=wip/${GITLAB_GROUP}/${APERTIS_RELEASE}-update + $ git checkout -b ${PROPOSED_BRANCH} apertis/${APERTIS_RELEASE} + $ apertis-pkg-merge-updates --upstream=debian/${CURRENT_UPSTREAM} --downstream=${PROPOSED_BRANCH} + +- If the merge fails, fix the conflicts and continue + + $ git add ... + $ git merge --continue + +- Create a new changelog entry for the new version + + $ DEBEMAIL="User Name <user@example.com>" dch -D apertis --local +apertis --no-auto-nmu "" + +- Check `debian/changelog` and update it if needed by listing all the remaining + Apertis changes then commit the changelog. + $ DEBIAN_VERSION=$(dpkg-parsechangelog -S Version) + $ git commit -s -m "Release ${PACKAGE} version ${DEBIAN_VERSION}" debian/changelog + +- Push your changes for review + + $ git push origin ${PROPOSED_BRANCH}:${PROPOSED_BRANCH} + + Follow the instructions provided by the above command to create a merge request + +## Updating Components to a New Debian Release + +The CI/CD pipeline can also be used to pull in a new release of Debian. If the needed `debian/$RELEASE` branch doesn't exist (for example, there is a `debian/buster` branch but no `debian/bullseye`), the Gitlab Web UI can be used -to create it. In the `Create from` field of the branch creation page, users -should select `debian/${RELEASE-1}`. In this case, the new branch named -`debian/bullseye` will be created from `debian/buster`. - -Reviewers can then force-push to the proposed update branch in the Merge -Request to fixup any issue caused by the automated merge, and ultimately land -the MRs to the `apertis/*` branches. - -In some situations the automated merge machinery may ask to -`PLEASE SUMMARIZE remaining Apertis Changes`, and in that case -reviewers should: -* check out the proposed update branch -* edit the changelog to list **all** the downstream changes the package still - ships compared to the newly merged upstream package and their reason, - describing the purpose of each downstream patch and of any other change - shown by `git diff` against the `debian/*` branch -* amend the merge commit -* force-push to the proposed update branch -* land the associated Merge Requests as described above - -Remember to check that the updated package gets included in the next daily -reference image build and wait for its [QA test -results](https://lavaphabbridge.apertis.org/) to catch regressions timely -and act accordingly. - -## Adding updates from a non-default upstream repository of a distribution - -There are circumstances, when we deviate from the default upstream. This usually happens -when: -* Packages are not available in the default distribution repository -* Packages in the default distribution repository are outdated -* Newer version of package, available in the non-default repository, is needed - -For example, Apertis v2020 ships with a newer version of the Linux kernel -(5.4.x) than Debian Buster (4.9.x) on which it is based. In such cases, special -care needs to be taken to update packages from their respective upstreams. - -Below are a set of steps which can be adapted to such exception packages. Let us assume that for -such repository, the package was picked from Debian Unstable instead - -* Clone your repository - - $ git clone git@gitlab.apertis.org:ritesh/libgpiod.git - Cloning into 'libgpiod'... - remote: Enumerating objects: 114, done. - remote: Counting objects: 100% (114/114), done. - remote: Compressing objects: 100% (85/85), done. - remote: Total 114 (delta 18), reused 110 (delta 18), pack-reused 0 - Receiving objects: 100% (114/114), 110.99 KiB | 360.00 KiB/s, done. - Resolving deltas: 100% (18/18), done. - - $ cd libgpiod/ - -* Ensure you have a branch against your deviated upstream. If you are tracking changes from a deviated upstream like **Debian Unstable**, it needs to be ensured that the package's packaging repository has the corresponding branches available. This is needed because the automated machinery tools expect respective branches to be available. - * For example, if you picked a package from Debian Unstable, ensure to have a branch named `debian/unstable` in your git repository. - - $ git checkout -b debian/unstable origin/debian/buster - Branch 'debian/unstable' set up to track remote branch 'debian/buster' from 'origin'. - Switched to a new branch 'debian/unstable' - - $ git checkout debian/buster - Branch 'debian/buster' set up to track remote branch 'debian/buster' from 'origin'. - Switched to a new branch 'debian/buster' - - * Similarly, ensure to have a branch named `upstream/unstable` in your git repository. - - $ git checkout upstream/buster - Branch 'upstream/buster' set up to track remote branch 'upstream/buster' from 'origin'. - Switched to a new branch 'upstream/buster' - - $ git checkout -b upstream/unstable upstream/buster - Switched to a new branch 'upstream/unstable' - -* Ensure that these branches are pushed to your remote `origin`. It is important that these branches are pushed and in sync with the default remote. - - $ git push -u origin --all - Total 0 (delta 0), reused 0 (delta 0), pack-reused 0 - remote: - remote: To create a merge request for debian/unstable, visit: - remote: https://gitlab.apertis.org/ritesh/libgpiod/-/merge_requests/new?merge_request%5Bsource_branch%5D=debian%2Funstable - remote: - To gitlab.apertis.org:ritesh/libgpiod.git - * [new branch] debian/unstable -> debian/unstable - Branch 'apertis/v2019' set up to track remote branch 'apertis/v2019' from 'origin'. - Branch 'debian/buster' set up to track remote branch 'debian/buster' from 'origin'. - Branch 'upstream/buster' set up to track remote branch 'upstream/buster' from 'origin'. - Branch 'debian/unstable' set up to track remote branch 'debian/unstable' from 'origin'. - -* Pull in new updates using the `apertis-pkg-pull-updates` script, instructing it with the deviated upstream - * Eg. `apertis-pkg-pull-updates --package PKGNAME --upstream unstable --mirror http://deb.debian.org/debian` - - $ git checkout apertis/v2021dev2 - Switched to a new branch 'apertis/v2021dev2' - - $ ../apertis-pkg-pull-updates --package libgpiod --upstream unstable --mirror http://deb.debian.org/debian - source package libgpiod - running git branch --track -f debian/unstable origin/debian/unstable - Branch 'debian/unstable' set up to track remote branch 'debian/unstable' from 'origin'. - running git branch --track -f upstream/unstable origin/upstream/unstable - running git branch --track -f upstream/unstable origin/upstream/unstable - running git branch --track -f upstream/unstable origin/upstream/unstable - local version: 1.2-3 - fetch https://qa.debian.org/madison.php?package=libgpiod&yaml=on&s=unstable-security - local version: 1.2-3 - fetch https://qa.debian.org/madison.php?package=libgpiod&yaml=on&s=unstable-proposed-updates - local version: 1.2-3 - fetch https://qa.debian.org/madison.php?package=libgpiod&yaml=on&s=unstable - remote version: 1.4.1-4 - update to 1.4.1-4 - fetch https://snapshot.debian.org/mr/package/libgpiod/1.4.1-4/srcfiles?fileinfo=1 - download http://deb.debian.org//debian/pool/main/libg/libgpiod/libgpiod_1.4.1-4.dsc - running dget --download-only --allow-unauthenticated http://deb.debian.org//debian/pool/main/libg/libgpiod/libgpiod_1.4.1-4.dsc - dget: retrieving http://deb.debian.org//debian/pool/main/libg/libgpiod/libgpiod_1.4.1-4.dsc - % Total % Received % Xferd Average Speed Time Time Time Current - Dload Upload Total Spent Left Speed - 100 332 100 332 0 0 449 0 --:--:-- --:--:-- --:--:-- 448 - 100 2294 100 2294 0 0 1381 0 0:00:01 0:00:01 --:--:-- 5474 - dget: retrieving http://deb.debian.org//debian/pool/main/libg/libgpiod/libgpiod_1.4.1.orig.tar.xz - % Total % Received % Xferd Average Speed Time Time Time Current - Dload Upload Total Spent Left Speed - 100 338 100 338 0 0 637 0 --:--:-- --:--:-- --:--:-- 636 - 100 307k 100 307k 0 0 358k 0 --:--:-- --:--:-- --:--:-- 358k - dget: retrieving http://deb.debian.org//debian/pool/main/libg/libgpiod/libgpiod_1.4.1-4.debian.tar.xz - % Total % Received % Xferd Average Speed Time Time Time Current - Dload Upload Total Spent Left Speed - 100 342 100 342 0 0 677 0 --:--:-- --:--:-- --:--:-- 677 - 100 6132 100 6132 0 0 9922 0 --:--:-- --:--:-- --:--:-- 9922 - Moving branch debian/unstable to debian/, was: 713dadc - running gbp import-dsc /tmp/pull-updatesywrcg0_m/libgpiod_1.4.1-4.dsc --author-is-committer --author-date-is-committer-date --upstream-branch=upstream/unstable --debian-branch=debian/unstable '--debian-tag=debian/%(version)s' --no-sign-tags --no-pristine-tar - gbp:info: Version '1.4.1-4' imported under '/home/rrs/NoBackup/Gitlab_Packages/packaging-tools/libgpiod' - running ./import-tarballs /tmp/pull-updatesywrcg0_m/libgpiod_1.4.1-4.dsc - Importing /tmp/pull-updatesywrcg0_m/libgpiod_1.4.1.orig.tar.xz - - -## Adding updates from distribution development repositories +to create it: +- Navigate to the `Branches` page and click on the `New branch` button. +- Enter the new branch name as `debian/$RELEASE`, where `$RELEASE` is the new + release name, for example `debian/bullseye`. +- In the `Create from` field select the previous Debian release. For example, + the release that preceeds Debian Bullseye is Buster, so pick `debian/buster`. +- Click the `Create branch` button. + +In some situations manual intervention may be required to tweak the packaging, +patches or the automated merge machinery may ask to `PLEASE SUMMARIZE remaining +Apertis Changes`. When this happens: + +- Check out the proposed update branch. +- If asked to summarize the changes, edit the changelog to list **all** the + downstream changes the package still ships compared to the newly merged + upstream package and their reason, describing the purpose of each downstream + patch and of any other change shown by `git diff` against the `debian/*` + branch. +- Where other issues are found, either modify the packaging data or add/modify + the Apertis patch series to address the issue. +- Amend the merge commit. +- Force-push to the proposed update branch +- If changes beyond summarizing the changelog are made, the update branch + should be reviewed before it is merged. + +## Manually Updating Components from a Newer Debian Release + +There are circumstances, when we deviate from the default upstream. This +usually happens when: + +- Packages are not available in the default distribution repository +- Packages in the default distribution repository are outdated +- Newer version of package, available in the non-default repository, is needed + +For example, Apertis v2021 ships with a newer version of the Linux kernel +(5.10.x) than Debian Buster (4.9.x) on which it is based, which is the kernel +found in the next Debian release called Bullseye. In such cases, special care +needs to be taken to update packages from their respective upstreams. + +{{% notice warning %}} +The +[automated pipeline]({{< ref "component_guide.md#updating-components-from-debian" >}}) +should be used to perform this task where possible. + +This guide uses tools that are only provided in the package-source-builder +image. The easiest way to perform this task is to utilise the docker container. +{{% /notice %}} + +Below are a set of steps which can be adapted to such exception packages. Let +us assume that for such repository, the package was picked from Debian Bullseye +instead of Buster + +- Clone the repository: + + $ GITLAB_GROUP=pkg + $ PACKAGE=hello + $ git clone git@gitlab.apertis.org:${GITLAB_GROUP}/${PACKAGE} + $ cd ${PACKAGE} + +- If the required `debian/` and `upstream/` branches don't yet exist in your + repository, create them based on the version that you have for instance. For + instance, if you currently have a version of Apertis based on Debian Buster + and wish to use the updated package in Bullseye: + + $ CURRENT_UPSTREAM=buster + $ DESIRED_UPSTREAM=bullseye + $ git push origin origin/upstream/${CURRENT_UPSTREAM}:refs/heads/upstream/${DESIRED_UPSTREAM} + $ git push origin origin/debian/${CURRENT_UPSTREAM}:refs/heads/debian/${DESIRED_UPSTREAM} + +- Ensure you have the required branches locally: + + $ DESIRED_UPSTREAM=bullseye + $ git branch debian/${DESIRED_UPSTREAM} origin/debian/${DESIRED_UPSTREAM} + $ git branch upstream/${DESIRED_UPSTREAM} origin/upstream/${DESIRED_UPSTREAM} + +- Ensure we have a `pristine-lfs` branch locally: + + $ git branch pristine-lfs origin/pristine-lfs + +- Pull in new updates using the `apertis-pkg-pull-updates` script, passing in + the deviated upstream: + + $ APERTIS_RELEASE=v2021 + $ MIRROR=https://deb.debian.org/debian + $ git checkout -b apertis/${APERTIS_RELEASE} origin/apertis/${APERTIS_RELEASE} + $ apertis-pkg-pull-updates --package ${PACKAGE} --upstream ${DESIRED_UPSTREAM} --mirror ${MIRROR} + + This will update the `debian/...` and `upstream/...` branch as prepared + previously. + +- Ensure that the changes to these branches are pushed to your remote `origin`. + It is important that these branches are pushed and in sync with the default + remote. + + $ git push origin --follow-tags pristine-lfs debian/${DESIRED_UPSTREAM} upstream/${DESIRED_UPSTREAM} + +- The upstream changes now need to be merged into the apertis branch. We will + do this via a development branch that can be pushed for review. + + $ PROPOSED_BRANCH=wip/${GITLAB_GROUP}/${APERTIS_RELEASE}-update-from-${DESIRED_UPSTREAM} + $ git checkout -b ${PROPOSED_BRANCH} apertis/${APERTIS_RELEASE} + $ apertis-pkg-merge-updates --upstream=debian/${DESIRED_UPSTREAM} --downstream=${PROPOSED_BRANCH} + +- If the merge fails, fix the conflicts and continue + + $ git add ... + $ git merge --continue + +- Create a new changelog entry for the new version + + $ DEBEMAIL="User Name <user@example.com>" dch -D apertis --local +apertis --no-auto-nmu "" + +- Check `debian/changelog` and update it if needed by listing all the remaining + Apertis changes then commit the changelog. + + $ DEBIAN_VERSION=$(dpkg-parsechangelog -S Version) + $ git commit -s -m "Release ${PACKAGE} version ${DEBIAN_VERSION}" debian/changelog + +- Push your changes for review + + $ git push origin ${PROPOSED_BRANCH}:${PROPOSED_BRANCH} + + Follow the instructions provided by the above command to create a merge request + +## Updating from Debian Development Repositories This is another scenario, wherein the user may need updates which are not yet released -into the Upstream Distributions' repositories. +into the Upstream Distributions' package repositories. -For example, for Apertis, we may need a very newer version of libgpiod, which may not yet -have been released into any of Debian development releases (Unstable, Testing). In -such cases, where the changes may only be available in the packaging repositories, we -need to take extra care when pulling in such updates. +For example, for Apertis, we may need a very newer version of a package, which +may not yet have been released into any of Debian development releases +(Unstable, Testing). In such cases, where the changes may only be available in +the packaging repositories. We need to take extra care when pulling in such +updates as they will not have been through the same levels of testing as +packages taken from stable or even testing releases. -Let us assume libgpiod 1.4.2 has been available in Debian's libgpiod Packaging repository but -is not released into any of the Debian releases. In such case, we can try: +- Clone the remote git packaging repository from Debian. -* Clone the remote libgpiod git packaging repository from Debian. -* Generate a source package out of the packaging repository using `gbp buildpackage -S` - * If successful, this will give us a proper *libgpiod source package*. -* Clone the Apertis libgpiod git packaging repostiory - * Use the `pristine-lfs` tool to import the source package generated from the Debian repository into Apertis packaging repository. Eg. `pristine-lfs import-dsc libgpiod-1.4.2-1.dsc` - * Note: The `import-dsc` subcommand imports the new tarball into the git repository and commits it to the `pristine-lfs` branch. While a user can commit to the branch manually by-hand, we recommend the use of `import-dsc` to import new tarballs and committing them to the packaging repository + $ PACKAGE=hello + $ DEBIAN_REPO=https://salsa.debian.org/debian/${PACKAGE}.git + $ DEBIAN_BRANCH=debian/master + $ git clone -b ${DEBIAN_BRANCH} ${DEBIAN_REPO} ${PACKAGE}-debian + $ cd ${PACKAGE}-debian -## Maintaining package from upstream sources +- Generate a source package out of the packaging repository -There are likely to be instances where it is desirable to import the latest version of a piece of software into Apertis directly from it's original authors or maintainers. -This may be as a result of the software in question not being packaged by Apertis' default upstream distribution, Debian, or their being a mismatch between the desired version in the upstream distribution and what is required for a specific goal. + $ gbp buildpackage -S --no-sign --git-debian-branch=${DEBIAN_BRANCH} -The [Apertis release flow]( {{< ref "release-flow.md#apertis-release-flow" >}} ) stipulates that each Apertis release should include the latest mainline kernel LTS release. -Due to Debian's release cadence being approximately half that of Apertis', there are 2 Apertis' releases for each Debian stable release and no guarantees that the kernel's packaged for Debian's current stable or in progress releases will align with Apertis' requirements. -As a result Apertis will need to pull from the mainline kernel LTS tree to satisfy it's requirements. + If successful, this will give us a proper source packages in the parent + directory -Such packages will require special attention to assure that they remain up-to-date with any security releases made by the upstream and updated as and when apropriate. +- Clone the Apertis git packaging repository for the same component -Unless the imported package can be used as-is without any modification, there will be a [patch series]( {{< ref "buildingpatchingandmaintainingtheapertiskernel.md#packaging" >}} ) that potentially needs tweaking to apply after the update. -The workflow set out below takes this into consideration. + $ cd .. + $ GITLAB_GROUP=pkg + $ git clone git@gitlab.apertis.org:${GITLAB_GROUP}/${PACKAGE} + $ cd ${PACKAGE} -Below we use the process of importing the Linux kernel for `v2020` as an example, where we track the `linux-5.4.y` stable branch: +- If the required `debian/` and `upstream/` branches don't yet exist in your + repository, create them based on the version that you have for instance. For + instance, if you currently have a version of Apertis based on Debian Buster + and wish to use the updated package in Bullseye: -- Using the Gitlab Web UI, create an empty project under `pkg/`, for example, `pkg/linux`. + $ CURRENT_UPSTREAM=buster + $ DESIRED_UPSTREAM=experimental + $ git push origin origin/upstream/${CURRENT_UPSTREAM}:refs/heads/upstream/${DESIRED_UPSTREAM} + $ git push origin origin/debian/${CURRENT_UPSTREAM}:refs/heads/debian/${DESIRED_UPSTREAM} -- Download the latest release tarball from upstream. For the `linux-5.4.y` stable branch, it would be `linux-5.4.115.tar.xz` from [kernel.org](https://www.kernel.org/) at the time of this writing. +- Ensure you have the required branches locally: -- Extract the tarball and enter the extracted folder + $ git branch debian/${DESIRED_UPSTREAM} origin/debian/${DESIRED_UPSTREAM} + $ git branch upstream/${DESIRED_UPSTREAM} origin/upstream/${DESIRED_UPSTREAM} - $ tar xf linux-5.4.114.tar.xz - $ cd linux-5.4.114 +- Run `gbp import-dsc` to update the `debian/` and `upstream/` branches. -- Create a new git repository and commit the whole source tree; this will create the `upstream/apertis` branch containing the untouched upstream source code: + $ NEW_DSC=$(ls -t ../*.dsc | head -n 1) + $ GBP_CONF_FILES=/dev/null gbp import-dsc --author-is-committer --author-date-is-committer-date \ + --upstream-branch=upstream/${DESIRED_UPSTREAM} --debian-branch=debian/${DESIRED_UPSTREAM} \ + --debian-tag='debian/%(version)s' --no-sign-tags --no-pristine-tar ${NEW_DSC} - $ git init - $ git checkout -b upstream/apertis - $ git add . - $ git commit +- Use the `pristine-lfs` tool to import the source package generated from the Debian repository into Apertis packaging repository. -- Commit the original tarball to the `pristine-lfs` branch: + $ pristine-lfs import-dsc ${NEW_DSC} - $ pristine-lfs commit ../linux-5.4.114.tar.xz +- Ensure that the changes to these branches are pushed to your remote `origin`. + It is important that these branches are pushed and in sync with the default + remote. -- Create the packaging branch for the Apertis version you're targetting and add packaging files + $ git push origin --follow-tags pristine-lfs debian/${DESIRED_UPSTREAM} upstream/${DESIRED_UPSTREAM} -{{% notice info %}} -Debian packaging is not covered by this document, users interested in that matter -should refer to the [Debian Policy Manual](https://www.debian.org/doc/debian-policy/) -and [Debian Developer's Reference](https://www.debian.org/doc/manuals/developers-reference/). -{{% /notice %}} +- The upstream changes now need to be merged into the apertis branch. We will + do this via a development branch that can be pushed for review. -- Add the Gitlab project you created earlier as the `origin` git remote: + $ APERTIS_RELEASE=v2021 + $ PROPOSED_BRANCH=wip/${GITLAB_GROUP}/${APERTIS_RELEASE}-update-from-${DESIRED_UPSTREAM} + $ git checkout -b ${PROPOSED_BRANCH} apertis/${APERTIS_RELEASE} + $ apertis-pkg-merge-updates --upstream=debian/${DESIRED_UPSTREAM} --downstream=${PROPOSED_BRANCH} - $ git remote add origin git@gitlab.apertis.org:pkg/linux.git +- If the merge fails, fix the conflicts and continue -- Push your branches to the repository: + $ git add ... + $ git merge --continue - $ git push --all --follow-tags origin +- Create a new changelog entry for the new version + + $ DEBEMAIL="User Name <user@example.com>" dch -D apertis --local +apertis --no-auto-nmu "" + +- Check `debian/changelog` and update it if needed by listing all the remaining + Apertis changes then commit the changelog. -- Setup the repository as instructed in the [Adding new packages from Debian](#adding-new-packages-from-debian) section: + $ DEBIAN_VERSION=$(dpkg-parsechangelog -S Version) + $ git commit -s -m "Release ${PACKAGE} version ${DEBIAN_VERSION}" debian/changelog - $ gitlab-rulez apply rulez.yaml --filter pkg/linux +- Push your changes for review -You can then subsequently update this package by following these steps: + $ git push origin ${PROPOSED_BRANCH}:${PROPOSED_BRANCH} -- Using the GitLab web UI, check to ensure that the relevant update branch exists, in the case of the Apertis `v2020` release, kernel updates should be made on the `apertis/v2020-security` branch. Create the required branch if it doesn't exist. -- Clone the existing package from Apertis GitLab and checkout the relevant branch: + Follow the instructions provided by the above command to create a merge request + +## Updating the kernel from an upstream stable git branch + +The [Apertis release flow]( {{< ref "release-flow.md#apertis-release-flow" >}}) +stipulates that each Apertis release should include the latest mainline kernel +LTS release. Due to Debian's release cadence being approximately half that of +Apertis', there are 2 Apertis releases for each Debian stable release and the +latest LTS is not always packaged by Debian. As a result it is expected that +Apertis will need to pull from the mainline kernel LTS tree to satisfy it's +requirements. For example, Apertis v2020 ships with a newer version of the +Linux kernel (5.4.x) than Debian Buster (4.9.x) on which it is based. + +In such cases, special care needs to be taken to update packages from their +respective upstreams: + +- Using the GitLab web UI, check to ensure that the relevant update branch + exists, in the case of the Apertis `v2020` release, kernel updates should be + made on the `apertis/v2020-security` branch. Create the required branch if it + doesn't exist. +- Clone the existing package from Apertis GitLab and checkout the relevant + branch: $ git clone -b apertis/v2020-security git@gitlab.apertis.org:pkg/linux.git linux-apertis -- Separately clone the Linux kernel LTS repository and checkout the relvant stable branch: +- Separately clone the Linux kernel LTS repository and checkout the relevant + stable branch: $ git clone -b stable-linux-5.4.y git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git linux-stable -- Create a `gbp pq` patch branch and switch back to normal branch. The patch branch will be needed when rebasing the Debian patches: +- Create a `gbp pq` patch branch and switch back to normal branch. The patch + branch will be needed when rebasing the Debian patches: $ cd linux-apertis $ gbp pq import $ gbp pq switch -- Determine the latest stable release and derive the Apertis version to use. To ensure collisions don't occur with any future Debian releases, we will mark the release as the zeroth "Debian" release (`-0`) and first Apertis pre-release (`~apertis1`): +- Determine the latest stable release and derive the Apertis version to use. To + ensure collisions don't occur with any future Debian releases, we will mark + the release as the zeroth "Debian" release (`-0`) and first Apertis + pre-release (`~apertis1`): - $ RELEASE=`git -C ../linux-stable describe` - $ RELEASE="${RELEASE#v}-0~apertis1" + $ KERNEL_RELEASE=`git -C ../linux-stable describe` + $ RELEASE="${KERNEL_RELEASE#v}-0~apertis1" -- Add a changelog entry for newest `linux-5.4.y` kernel release (this is needed to get `genorig.py` to use the right release): +- Add a changelog entry for newest `linux-5.4.y` kernel release (this is needed + to get `genorig.py` to use the right release): $ DEBEMAIL="User Name <user@example.com>" dch -v "$RELEASE" "" $ git add -f debian/changelog @@ -421,120 +631,51 @@ You can then subsequently update this package by following these steps: $ gbp pq rebase - This may require some manual intervention following the normal git rebasing process. + This may require some manual intervention following the normal git rebasing + process. - Export updated patch series: $ gbp pq export -- Tweak `debian/patches/series` file so that it retains the comments that `gbp pq` wants to drop. If no patches have been dropped during rebase then: +- Tweak `debian/patches/series` file so that it retains the comments that `gbp + pq` wants to drop. If no patches have been dropped during rebase then: $ git checkout debian/patches/series $ git add -f debian/patches $ git commit -s -m "Update the debian patches for $RELEASE update" -- Update changelog to released state (set distribution to apertis), document any patches that have been dropped as a result of the update and create new commit: +- Update changelog to released state (set distribution to apertis), document + any patches that have been dropped as a result of the update and create new + commit: $ dch -D apertis $ git add -f debian/changelog $ git commit -s -m "Release linux version $RELEASE" -- Run `dpkg-buildpackage` to generate the debian packaging, this is needed to use the tools to update the [pristine-lfs branch]( {{< ref "component_structure.md" >}} ): +- Run `dpkg-buildpackage` to generate the debian packaging, this is needed to + use the tools to update the + [pristine-lfs branch]( {{< ref "component_structure.md" >}} ): $ mkdir ../build $ gbp buildpackage --git-ignore-new \ --git-debian-branch=apertis/v2020-security \ --git-prebuild='debian/rules debian/control || true' \ --git-export-dir='../build' \ - -us -S + --no-sign -us -S -- Import the generated kernel tarball into pristine-lfs branch with `import-tarballs`: +- Import the generated kernel tarball into pristine-lfs branch with + `import-tarballs`: $ git clone git@gitlab.apertis.org:infrastructure/packaging-tools.git ../packaging-tools - $ ../packaging-tools/import-tarballs ../build/linux_5.4.51-0~apertis1.dsc + $ ../packaging-tools/import-tarballs ../build/<kernel .dsc file> $ git push origin pristine-lfs - Push kernel update to a branch to be reviewed: - $ git push origin apertis/v2020-security:wip/user/kernel-update - -## How to manually sync an Apertis package with a new version - -Upstream updates are usually handled automatically by the -[`ci-package-builder.yml`](https://gitlab.apertis.org/infrastructure/ci-package-builder/) -Continous Integration pipeline, which -[fetches upstream packages, merges them]({{< ref "component_guide.md#pulling-updates-or-security-fixes-from-upstream-distributions" >}}) -with the Apertis contents and directly creates Merge Requests to be reviewed by -[maintainers]({{< ref "contributions.md#the-role-of-maintainers" >}}). - -However, in some cases it is necessary to manually pull upstream contents: -1. the CI failed to merge the upstream update with the downstream changes, so a - developer must reproduce the merge and fix the conflicts -1. for some reason it in necessary to manually pull updates from a new upstream - distribution/suite - -The steps below can guide you on manually pulling upstream updates: + $ git push origin apertis/v2020-security:wip/${GITLAB_USER}/${KERNEL_RELEASE}-kernel-update -{{% notice note %}} -This guide assumes the developer is a member of the Apertis development team, -contributors who are not a member of this team will need to fork the package to -their private workspace (as documented in the -[development process]({{< ref "development_process.md" >}}) before manually -updating the package and submit a merge request from there. -{{% /notice %}} - -1. On GitLab, - [fork the project](https://docs.gitlab.com/ce/user/project/repository/forking_workflow.html) - to your personal namespace. - -1. Check out the source repository - - GITLAB_USER=${USER} - UPSTREAM_DISTRIBUTION=buster - MIRROR=https://deb.debian.org/debian - PACKAGE=glib2.0 - - git clone git@gitlab.apertis.org:${GITLAB_USER}/${PACKAGE} - cd ${PACKAGE} - -1. Only if moving to a new upstream distribution, prepare the upstream base - branches using the current upstream branches as a base: - - UPSTREAM_DISTRIBUTION=bullseye - UPSTREAM_BASE=buster - git push origin origin/upstream/${UPSTREAM_BASE}:refs/heads/upstream/${UPSTREAM_DISTRIBUTION} - git push origin origin/debian/${UPSTREAM_BASE}:refs/heads/debian/${UPSTREAM_DISTRIBUTION} - -1. Sync the upstream contents - - apertis-pkg-pull-updates --package=$PACKAGE --upstream=$UPSTREAM_DISTRIBUTION --mirror=$MIRROR - git push origin --follow-tags pristine-lfs upstream/${UPSTREAM_DISTRIBUTION} debian/${UPSTREAM_DISTRIBUTION} - -1. Merge the upstream changes - - PROPOSED_BRANCH=wip/$GITLAB_USER/update-from-${UPSTREAM_DISTRIBUTION} - TARGET_BRANCH=apertis/v2021dev1 - git checkout -b ${PROPOSED_BRANCH} ${TARGET_BRANCH} - apertis-pkg-merge-updates --upstream=debian/${UPSTREAM_DISTRIBUTION} --downstream=${PROPOSED_BRANCH} - -1. Only if the merge fails, fix the conflicts and continue - - git status - # fix conflicts - git merge --continue - dch --local co --no-auto-nmu - -1. Check `debian/changelog` and update it if needed by listing all the remaining Apertis changes - - $EDITOR debian/changelog - git commit --signoff --amend debian/changelog - -1. Push your changes for review - - git push origin --follow-tags pristine-lfs upstream/${UPSTREAM_DISTRIBUTION} debian/${UPSTREAM_DISTRIBUTION} - git push -o merge_request.create - -# Creating new modifications +# Creating New Modifications The standard [Contribution Process]({{< ref "contributions.md" >}}) applies unchanged to packaging repositories, the Apertis development team and @@ -548,17 +689,45 @@ source-building pipeline to fail. Check the [Debian Packaging](https://wiki.debi documentation to find how patches affecting code outside of the `debian/` folder should be handled. -Update `debian/changelog` separately, as the very last step when you issue -a release, by generating the changelog entries from the Git commit log. -Writing good commit messages ensures you don’t have to edit the generated -changelog entries. +## The Debian Changelog and Releases + +Beyond informing developers and interested users of what has changed between +sucessive releases of a component, the changelog controls the release process +in a number of ways: + +- **Package versioning**: The changelog is the canonical location used by the + Debian packaging process to determine the version number used for the binary + packages. +- **Release control**: The "distribution" field of a changelog entry controls + whether the component is ready to be cut as a new release. + +{{% notice info %}} +The changelog format is documented in the +[Debian Policy Manual](https://www.debian.org/doc/debian-policy/ch-source.html#s-dpkgchangelog.) +{{% /notice %}} + +It is therefore important to correctly handle the changelog file when creating +modifications to components. + +The CI pipeline generates a source package locally for each commit pushed +to the packaging repositories. You can download this package by browsing the +pipeline artifacts. The generated sources are versioned to indicate that +they are not yet suitable for release. -Submit a separate merge request on GitLab for each bug or task. To ease -the review process, in particular to avoid churn in the case of rebases, it is -recommended to leave the editing of `debian/changelog` to a dedicated merge -request once all the other MRs have been landed, see the -[section about landing downstream changes to the main -archive](#landing-downstream-changes-to-the-main-archive) below. +With the "distribution" field set to `UNRELEASED`, package sources get uploaded +to the `:snapshots` OBS project with the matching branch (that is, when targetting the `apertis/v2021` branch of a component from the `target` suite, the source package will be uploaded to the `apertis:v2021:target:snaphots` project). + +It is advisable to update the `debian/changelog` file in a separate commit, as +the very last step when you issue a release. Such changelog entries should be +generated from the Git commit log. This can be achieved by using `gbp dch`. +Writing good commit messages ensures that you don’t have to spend time editing +the generated changelog entries. + +It is best to submit a separate merge request on GitLab for each bug or task. +As performing a separate release between each merge request may not be wanted +and to avoid churn in the case of rebases (in particular to ease the review +process), it is recommended to leave the editing of `debian/changelog` to a +dedicated merge request once all the other MRs have been landed. {{% notice tip %}} In order to follow a @@ -569,98 +738,82 @@ features. This gives the possibility to receive early feedback on the downstream changes. {{% /notice %}} -If you still wish to edit `debian/changelog` for any reason, just make sure -that the changelog entry you're writing has the `distribution` field set -to `UNRELEASED`, using `gbp dch --auto --ignore-branch` to ensure the -formatting is correct. - -The CI pipeline generate a source package locally for each commit pushed -to the packaging repositories. You can download this package by browsing the -pipeline artifacts. The generated sources are versioned to indicate that -they are not yet suitable for release. - -With the `distribution` field set to `UNRELEASED`, package sources get uploaded -to the `:snapshots` OBS project matching the branch (that is, -`apertis:v2020dev0:target:snaphots` when landing changes to the -`apertis/v2020dev0` branch of a `:target` package): the following [section -about landing downstream changes to the main -archive](#landing-downstream-changes-to-the-main-archive) below describes -in detail how to set the `distribution` to land the package to the appropriate -main OBS project. +If you still wish to edit `debian/changelog` as you go along for some reason, +make sure that the changelog entry you're writing has the `distribution` field +set to `UNRELEASED` and use `gbp dch --auto --ignore-branch` to ensure the +formatting of the changelog is correct. -## Landing downstream changes to the main archive +## Landing Downstream Changes to the Main Archive Once downstream changes to a package are deemed ready to be published in the -Apertis main archive, a proper release needs to be issued. - -* Push a `wip/` branch updating `debian/changelog` - * use `GBP_CONF_FILES=/dev/null gbp dch --release -D apertis --debian-branch=apertis/v2020dev0` - to generate a release changelog entry summarizing all the changes already - landed on the `apertis/v2020dev0` branch - * ensure that the `distribution` field has been changed from `UNRELEASED` - to `apertis` -* Create a Merge Request based on your `wip/` branch for the most recent - release branch where you want to land your changes: - * for published stable release, the main branch (for instance - `apertis/v2019`) should **never** be targeted directly, but updates and - fixes should go through the `apertis/v2019-security` or - `apertis/v2019-updates` branches, see [Process after a product - release]( {{< ref "release-flow.md#process-after-a-product-release" >}} ) - for more details - * for instance, if you want to land changes to both the development and - stable releases, push your `wip/` source branch and create a merge request for the - development one first (for instance, `apertis/v2020dev0`) and then, once - merged, create a merge request for the stable one (for instance, `apertis/v2019-updates`) -* Get the Merge Request reviewed and landed -* The CI pipeline will then build-check the source package as usual and since - the `distribution` field is no longer `UNRELEASED` it will also: - * add a Git tag for the release version to the repository - * rebuild the release source package - * store the release sources in the `pristine-lfs-source` branch - * upload the release source package to the main project (for instance - `apertis:v2020dev0:target`) +Apertis main archive, a proper release needs to be issued. To achieve this create a merge request containing an update to the changelog. The description should contain details of all the changes since the last release. This can be easily achieved with `gbp dch` if the commits have been well written: + + $ APERTIS_RELEASE=v2021 + $GBP_CONF_FILES=/dev/null gbp dch --release -D apertis --debian-branch=apertis/${APERTIS_RELEASE} + +Ensure that the "distribution" field has been changed from `UNRELEASED` to +`apertis`. + +If making changes to more than one release, start with the most recent release +branch where you want to land your changes. For instance, if you want to land +changes to both the development and stable releases, submit a merge request for +the development one first (for instance, `apertis/v2020dev0`) and then, once +merged, create a merge request for the stable one (for instance, +`apertis/v2019-updates`) + +Once a merge request has been reviewed and landed, the CI pipeline will +build-check the source package as usual. Since the `distribution` field is no +longer `UNRELEASED` it will also: +* add a Git tag for the release version to the repository +* rebuild the release source package +* store the release sources in the `pristine-lfs-source` branch +* upload the release source package to the main project on OBS (for instance + `apertis:v2020dev0:target`) + +{{% notice warning %}} +Published stable release branches (for instance `apertis/v2019`) should +**never** be targeted directly. Updates to these should +[go through the `-security` or `-updates` branches]({{< ref "release-flow.md#process-after-a-product-release" >}}) +(for example `apertis/v2019-security` or `apertis/v2019-updates). +{{% /notice %}} If the `apertis/$RELEASE-updates` or `apertis/$RELEASE-security` branches for published stable releases do not exist yet, they should be created from the GitLab web UI since their protected status makes pushing forbidden. -For trivial changes it is also possible to combine the release commit in the same -MR as the changes. Again, developers need to be careful to ensure the changelog -entries are kept up-to-date when the commit messages get changed via rebase. +For trivial changes it is also possible to combine the release commit in the +same MR as the changes. Again, developers need to be careful to ensure the +changelog entries are kept up-to-date when the commit messages get changed via +rebase. -## Backporting updates or security fixes +## Backporting Updates or Security Fixes Often downstream fixes, upstream updates or security fixes need to be applied -to [multiple active releases]( {{< ref "release-flow.md" >}} ). - -Changes should be introduced in the most recent development release where they can -be tested and regressions detected with little impact, following the instructions -in the -[Landing downstream changes to the main archive](#landing-downstream-changes-to-the-main-archive) -and [Pulling updates or security fixes from upstream distributions](#pulling-updates-or-security-fixes-from-upstream-distributions) -sections. - -Once the changes have been thoroughly tested paying close attention to the QA -test results, they can then be propagated to the more stable releases, where -any mistake can impact the product teams using Apertis in the field. +to [multiple active releases]({{< ref "release-flow.md" >}}). Changes should be +introduced in the most recent development release where they can be tested and +regressions detected with little impact. Once the changes have been thoroughly +tested, paying close attention to the QA test results, they can then be +propagated to the more stable releases, where any mistake can impact the +product teams using Apertis in the field. For instance, once a fix is landed to `apertis/v2021dev0` and no regressions -are found in the subsequent QA test results, a MR should be create to land -the changes to the stable releases. +are found in the subsequent QA test results, an MR should be create to land +the changes to the relevant stable releases. If there is no divergence between the packages in the different releases and -the backport can be done with a fast-forward, a MR should be created to submit +the backport can be done with a fast-forward, an MR should be created to submit the changes from for instance `apertis/v2021dev0` to `apertis/v2020-updates` or -`apertis/v2020-security`, following the -[Landing downstream changes to the main archive](#landing-downstream-changes-to-the-main-archive) -steps, choosing the destination depending on the nature and impact of the fix. +`apertis/v2020-security`. Choose the required destination depending on the nature and impact of the fix. If package diverged across releases, a separate branch has to be created where -the fixes are cherry-picked appropriately before creating the MR. See the -[Diverging release branches](#diverging-release-branches) section for further -details about versioning divergent packages. +the fixes are cherry-picked appropriately before creating the MR. -## Diverging release branches +{{% notice warning %}} +Care needs to be taken to give these diverging release branches suitable +version numbers. +{{% /notice %}} + +## Diverging Release Branches Sometimes different downstream patches need to be applied in the different Apertis release branches. A clear case of that is the `base-files` package @@ -674,17 +827,86 @@ would lead to difficult to diagnose errors. When targeting a specific release, `~${RELEASE}.${COUNTER}` needs to be appended to the version identifier after the local build suffix: -* `0.42` → append `co0~v2020pre.0` → `0.42co0~v2020pre.0` -* `0.42co3` → bump to `co4` and append `~v2020pre.0`→ `0.42co4~v2020pre.0` -* `0.42co4~v2020pre.0` → increase the release-specific counter → `0.42co4~v2020pre.1` +| Previous Version | New release specific version (for `v2020`) | Description | +| --- | --- | --- | +| `0.42+apertis0` | `0.42+apertis0~v2020.0` | Increment Apertis release, append release specific identifier | +| `0.42+apertis0~v2020.0` | `0.42+apertis4~v2020.1` | Increment the release specific counter | -This uses the fact that `~` in Debian package numbers sorts before anything, -see the [Debian Policy §5.6.12](https://www.debian.org/doc/debian-policy/ch-controlfields.html#s-f-version) for more details. +This uses the fact that `~` in Debian package numbers +[sorts before anything](https://www.debian.org/doc/debian-policy/ch-controlfields.html#s-f-version). Adding `~` is necessary so that if a new upstream version `0.42.1` or a new -non-release-specific downstream version `0.42co4` is introduced, they will -replace the release-specific package. +non-release-specific downstream version `0.42+apertis4` is introduced, they +will replace the release-specific package. Note that `dpkg` considers `2020.0` to be newer than `2020pre.0`, so the -Apertis release identifiers can be used with no modification (if in doubt, -check with `dpkg --compare-versions 2020pre.0 '<<' 2020.0 && echo ok`). +Apertis release identifiers can be used with no modification. If in doubt, +check with `dpkg --compare-versions`: + + $ dpkg --compare-versions 0.42+apertis0~2020pre.0 '<<' 0.42+apertis0~2020.0 && echo true || echo false + true + $ dpkg --compare-versions 0.42+apertis1 '<<' 0.42+apertis0~2020.0 && echo true || echo false + false + +# Advanced Configuration +## License Scans + +As merge requests to components are submitted, the CI pipeline performs license +scans on the package. The scans are performed on all files in the package, not +just the new submission. The pipeline fails or emits a warning (depending on +the configuration) if it finds files with unknown or unclear licensing terms, +or files under licenses not allowed in the package. When such a situation +arises, it is the responsibility of the submitter to perform the review of the +license scan results and make updates to the package if necessary. + +When the license scan mistakenly identifies a file as being under an incorrect +license, or fails to process it correctly, there are three ways to fix this: + +1. Specify the correct copyright and the license in + `debian/apertis/copyright.yml`. The format of the file is specified in the + [Dpkg::Copyright::Scanner](https://manpages.debian.org/buster/libconfig-model-dpkg-perl/Dpkg::Copyright::Scanner.3pm.en.html) + manpage. In short, it’s a YAML file mapping paths to their licensing + information: + + ``` yaml + debian: + copyright: 2015, Marcel + license: Expat + src/: + copyright: 2016, Joe + license: Expat + .*/NOTICE: + skip: 1 + src/garbled/: + 'override-copyright': 2016 Marcel MeXzigue + ``` + + Patterns follow the Perl regular expression rules. + + Please also verify `debian/copyright` specifies the correct license, and if + it doesn’t, submit a patch to Debian. + +2. Add the file to the list of ignored files, + `debian/apertis/copyright.whitelist`. This file is formatted the same way as + `gitignore`, please refer to the + [gitignore](https://manpages.debian.org/buster/git-man/gitignore.5.en.html) + manpage for more information. + +3. If the file is under a license not suitable for Apertis, it can be removed + from the package by either repackaging the tarball or patching it out, in + which case the scanner will not take it into account. + +The license scanner will store the automatically generated copyright report +file under `debian/apertis/copyright`, updating the merge request when +necessary. + +## Custom Pipelines + +When using the packaging pipeline, developers cannot put their CI/CD automation +in `.gitlab-ci.yml` anymore, as the CI config path points to the +ci-package-builder definition. + +However, developers can put their jobs in the +`debian/apertis/local-gitlab-ci.yml` file and have them executed in a child +pipeline whenever the main packaging pipeline is executed. This is specially +handy to run tests before the actual packaging process begins. diff --git a/static/images/run-pipeline-button.png b/static/images/run-pipeline-button.png index 36f707d5d295e32297b8827540f4466e29642455..8b6fd4b127c09e2b7cef5dcdfb4f74037250c031 100644 GIT binary patch literal 2562 zcmV+d3jOtoP)<h;3K|Lk000e1NJLTq004^s001ut1^@s6)08;}00004b3#c}2nYxW zd<bNS0000PbVXQnQ*UN;cVTj60B3G*ZDlQUV{&C>ZgXgFbngSdJ^%m!Ds)9ybVG7w zVRUJ4ZXi@?ZDjydb!8wiF(6H0c_1<{GBF@AHaaviIx;jMLQ_<m0*mYb00~}6L_t(| zob8-%Y!l}l$3M2uKD&+$HXLcFA<S+`=dh(wGs#Tp(yFRkkc?IoRaGMuiB@Ql+6{G; z@*+~EG4TQ^tGcnNEn1OUiK(q3(3Tghsirn6lRS+Mve8I|+Jayl$Uz+J5c~Y^_QFYs zlax5Yc3E?ucmCaT_j{hZ@BN<N^T(%CRaHepqXhKdb_F#4f6&CDQ8L0}#@~J%;f<3Q zNu_h-wO(q~px5azn+&|RV++50+O^=gZf?$!&Z_+McmE;ybqtfqh(Rx)(_+u6LCr%h zpCz5n@Z+rxj=%atOoDFqcu{0I`uSCYUr%7QS~2K#3ofSd9mfDh3>b|j{&7CWk-;dh zJo&)v;i9<l#@{X?ibhQ+s~m$~hgmf7`+<=ndy!biC)4P4hN@Of<K9HCGcZ1xF1F46 zk;|)Ej-mm8PG8W&Tr_EDl#C`8jgryCqERxMSTssT6N^U4XkyVQ8BHwJrpAiDX)Vn) z-*!co&!P*7E5DkRjvY=svxYoMBF%6#!QlB6@v=HAKi<}dINXxq(4Q_cFj*NNVtp;W z9d?4phS)cx0w&sDc!*BnD*N8QL8vlr%R+g@Vzv@^tQKD;i=0vc9d?_52*k&()BWy6 z`eSAFSVnZ%B{MDuNXBaV)gw7XTt+iuHQla&@``1e$mtMIo=Bho2qt{KdJgYe&%wY= z2H%g}qY*|Wc;de_oT#?n6mR|U-@H|Aw=19`Vksh<CV1*HM_bm=RlkO2A;w@9#JaV# z*Bc0(yFsuh<eO>p*^tI=(ibkQO-ODBep`zEp)^vXlXkZSyPy&o8K-aP7IO9u{vCGO z8}ytxJwbfqI@+78cm$Qu$OL^uiK25Qw*&tMmEh?KLRkO<-X<sBM2x->0l#k@Z5s`c zNHKW!1_PtHh5pPI{4Gv=k^wQ5WbpJj1M(u}W-0h+W{UoyTZI>CZk;6ufk$k3%n+9o z^q-C~oSJ_P9WJ+%K%*6xpb}Z6ZRMcyVgVqJk}0;>>uWi<+r+W4ae|X`)*u869f5k9 zzx<m1a2f?2o+cLux20%qG81Uf6Ol7uHsRS`OJ~a^o_$CD#=c(MxSpQfR)Tf4G`Cn# z<TP=!iNN++I(?(;d-n>#6fomwdz$XEGh#8)_C!7VlU97TwFE2~LJ5$h4Ro~DGI0C? z`@XpS<m~PTcyCV~%_t0yWe}a~>1e%wLAhcIKDrnsI4zb!oh<}6*V5c%L5Zb_W5lz4 z1D&noy!uXfPIqo1@InK<j~I!MO%cf&3vGMs8vEY9Jl(ePP!+L=bxr~sAs$XJyi&E> z*5J2|^89bEa3%#{pzS#?@3q{|UiWpn!*|-zC*t2W#p`bl(I*#jDR1k8e6XvIgHKJc zv;S71%lxLZJx;uzU*JdmiNc#-W9Q({9;9Q}CfdKcK;I-F*ywt$4sYxl&(Az0!OY&5 z9;Rp4COX0wIJT^O&4Rz-Cf$D+;@D`RZLTH{Cpw&T`bOzLnJn0R-=p^tJ;4u$+4n^X z1+Z`3!ikq_>D@7LI~^zk6&X6)>m_;uo9KCVGrcc1@b_0-cw^&qAHRXT;;UvD{46>x z6o4GT;7uZkcs4BEjL_Mu(?S7I89o)IZwx$*>u6r;mB}PH`bpw;t~D9w(5DIF78`+W zg)JRo;|2oGEQ6m$Z@<mi6vs}*ku5d?4a<KoLuaG2LIH?;d4pgQT+&Q3Y^K9!LyTVM zz_d^R;^(9ET>@8wW9hangNj5JyTe9XV;;~WIgKcxOYD4Co(}CRMd3`eIC?0VTp?@= zOKsN56NygEvrQ3<X4%^)vT(QQJYp$A^TK(2Bte8VxFj=h3(rO~cEID?!jYyq1ubSo z^hgdPu$&vPSe<hyNp6pt1PdMsNZIIm(Nk1Xasp-}(lR_QMP)`qXT#IsPayDOBZnI# z+NJ9p8ois%-zrLS<!394JSQcqf>DnsaOdZk%`Xh)(>A-HM?{C+tY6$uGDYxQl1TJU zN$z6g7p-#<f`Hu!N@C%Cl`q8@$R_S0k}u+}jMrL(EdBjaIz094-6hfY&e+nEPG%$a zvd?qqv0DrjD?*QCGe9y+e5r?GHe#PADA8s{0^+GG3Mz6e2jmHU66U~2mHrWt%^)WM z`8uz^f1~145|y9skI5VePJw45J&&4Z&GAeg1p|_;xC&Ck8oU*#hIi{4>~jq@YYA-D zql_guvy@nzR{TZrT!**GhKmft)BRH<JV^u#{zq%7H@TLbBsh{s+`OKEqw?;mvNkmQ z$z}S+1=@CQA~3xsqJ(cUoDpc-QP1A37Ce%LwnsN{WT&knH(P9Qab$-BU!57RdmTM{ zHqmCuFmP&|$WkX~MA|#t>}|B-t+V29b#vHfL5W`H==nkvQAV!v=D7^6?QTAJR>JSL z;H|UL)+EvM+ynS4vKEx3?^Bs!!A8$Z9y*)sG}l>ZcCV%V@y+zMTFZJbt257%O>n4x z9RD6CT|4azeiSDjlj%NQL+>spJuf>8<&snMp9~Z9JxF_5E0AH}WE6b$eDK6{laomX z{(6z_p%RkLsLX+p`{;V%`}7zA^2niUy!z1<hGz?<>HG6}*u9zkE%hAPK4Z@#Uy=!y zd4g;PC48AZ@8vnTb3OYz9JAt3l1T<n%4Hii!@NJ4IXXYXdY=WsP|Y3w23(Q}I~gK! zw(R|`*y!e8duA5yD6IboIU;g;>0AXfo%^@Z#VAj{d4-VKgvU{s!3|B`AukaONDdQ{ zpc0QML{insVZ<5}E}H={n;|4;?@B1yT#j2)Nn&q3K5MJe4DOxC5s~j=n6oTY;&O6M zG*~97G@;QF%4KuNa<Z%=ky215(}XItS`ONN7L8?~iAAGi?tyNovM8Y_d)~fAJi3y+ zL81S{uQ-FU^oVH{@SPV6sT60zD?M2yGMdnYGL6;^X_Sm67LAh8#G+9$MPf1Nb*TAo zt124z5^A0W-{~n5i?hZ=UR~}|y2f{ryqd#VV=A&0iRI`1%_!+K`Mmbg!PQJIucD;W zy!OnNBD-$>N0XoF9pay%2}F~C!C*kA(>@utT2NJ$TrP)_&hnFoo&4n&KPWoBKr8?s zpNsLU;~~Ohx5(tQD6?8H8g#ffSo!sC4^MAfxIt!7v1n*4hBkE8C>c#G8YQENMWbZ? Y2Q!j=IsXuC;Q#;t07*qoM6N<$f`Y}x0RR91 literal 6229 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 -- GitLab