From d93498520945639047ee95ddbda2abd58daf8726 Mon Sep 17 00:00:00 2001 From: Caleb Connolly Date: Tue, 26 Mar 2024 00:46:21 +0000 Subject: [PATCH] CI: implement scheduled auto-update pipeline (MR 4967) Introduce support for having CI automatically update packages using project access tokens and scheduled pipelines. The pipeline schedule is configured with an additional variable containing a list of packages to update, the autoupdate-fetch.sh script then calls a handler for each of these, the handler is expected to check for an update, make the necessary APKBUILD changes and commit them. After all packages have been updated, the changes are pushed to pmaports master using a project access token. [ci:skip-build] takes too long to build in CI --- .ci/autoupdate.sh | 108 ++++++++++++++++++++++++++++++++++++++++++++++ .gitlab-ci.yml | 24 ++++++++++- 2 files changed, 130 insertions(+), 2 deletions(-) create mode 100755 .ci/autoupdate.sh diff --git a/.ci/autoupdate.sh b/.ci/autoupdate.sh new file mode 100755 index 000000000..f15182360 --- /dev/null +++ b/.ci/autoupdate.sh @@ -0,0 +1,108 @@ +#!/bin/sh -e +# Description: update a list of packages +# Options: native slow +# https://postmarketos.org/pmb-ci + +if [ "$(id -u)" = 0 ]; then + set -x + apk add git openssh-keygen grep curl + wget "https://gitlab.com/postmarketOS/ci-common/-/raw/master/install_pmbootstrap.sh" + sh ./install_pmbootstrap.sh + exec su "${TESTUSER:-pmos}" -c "sh -e $0 $*" +fi + +git config --global --add safe.directory "$CI_PROJECT_DIR" +git config --global user.name "postmarketOS CI" +# pmaports +# The email address is the username of the bot (from the GitLab group members page) @noreply.gitlab.com +git config --global user.email "project_8065375_bot_13cf44ca4cd2c938688af6e3d500d9cb@noreply.gitlab.com" + +# For testing with pmaports-autoupdate-test repo +# git config --global user.email "project_58002231_bot_be2d4e9e7aba929855726aafe12940d6@noreply.gitlab.com" + +# Configure SSH key for signing +mkdir -p ~/.ssh +cp "$PMAPORTS_SSH_KEY" ~/.ssh/pmaports +chmod 600 ~/.ssh/pmaports +# Generate public key from private +ssh-keygen -t ecdsa -f ~/.ssh/pmaports -y > ~/.ssh/pmaports.pub + +git config --global gpg.format ssh +git config --global user.signingkey ~/.ssh/pmaports.pub + +export PYTHONUNBUFFERED=1 + +PKGS="$1" +if [ -z "$PKGS" ]; then + echo "Usage: $0 " + exit 1 +fi +echo "Checking for new versions of packages: $PKGS" + +update_linux_next() { + # Check for the latest -next tag + local latest + local pkgver + local new_pkgver + + # Get the current version + # shellcheck source=/dev/null + pkgver=$(. device/testing/linux-next/APKBUILD; echo "$pkgver") + + curl -s "https://gitlab.com/linux-kernel/linux-next/-/tags?format=atom" | grep -oP "(?<=)[^<]+" | tail -n +2 > /tmp/tags + + latest=$(grep -v "v" < /tmp/tags | head -n1) + if [ -z "$latest" ]; then + echo "Failed to get the latest -next tag" + exit 1 + fi + echo "Latest -next tag: $latest" + + new_pkgver=$(grep "v" < /tmp/tags | head -n1) + if [ -z "$new_pkgver" ]; then + echo "Failed to get the latest mainline tag from atom feed, reusing current pkgver" + new_pkgver="${pkgver%_git*}" + else + echo "Latest mainline tag: $new_pkgver" + # new_pkgver is like 'v6.9-rc1' but we want '6.9' + new_pkgver=$(echo "$new_pkgver" | sed -e 's/^v//' -e 's/-.*//') + fi + + new_pkgver="${new_pkgver}_git${latest#*-}" + + if [ "$pkgver" = "$new_pkgver" ]; then + echo "No new version of linux-next" + exit 0 + fi + + echo "Updating linux-next from $pkgver to $new_pkgver..." + sed -i -e "s/pkgver=$pkgver/pkgver=$new_pkgver/" device/testing/linux-next/APKBUILD + + # Update the checksums + pmbootstrap checksum linux-next + + # Commit + git add device/testing/linux-next/APKBUILD + git commit -S -m "linux-next: update to $latest" +} + +# For testing +#git remote add gitlab https://pmos-ci:"$PMAPORTS_PUSH_TOKEN"@gitlab.com/postmarketOS/pmaports-autoupdate-test.git + +git remote add gitlab https://pmos-ci:"$PMAPORTS_PUSH_TOKEN"@gitlab.com/postmarketOS/pmaports.git +git fetch gitlab +git checkout --track gitlab/master + +for pkg in $PKGS; do + case "$pkg" in + linux-next) + update_linux_next + ;; + *) + echo "Unknown package: $pkg" + exit 1 + ;; + esac +done + +git push diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 657776fc5..f37b57cc7 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -9,6 +9,7 @@ after_script: stages: - lint - build + - autoupdate # This defines the rules for when a pipeline should run. workflow: @@ -18,8 +19,8 @@ workflow: when: never # Run for merge requests - if: $CI_PIPELINE_SOURCE == "merge_request_event" - # Run scheduled pipeline for autoupdate - - if: $CI_PIPELINE_SOURCE == "schedule" + # Run scheduled pipeline for autoupdate or manually triggered pipeline + - if: $CI_PIPELINE_SOURCE == "schedule" || $CI_PIPELINE_SOURCE == "web" # device documentation wiki: @@ -165,3 +166,22 @@ build-riscv64: extends: .build script: - .ci/build-riscv64.sh + +auto-update: + stage: autoupdate + rules: + # This variable is set in the scheduled pipeline configuration. It should be a space separated list of + # package names to update. + - if: $AUTOUPDATE_PACKAGES != null && $CI_PIPELINE_SOURCE == "schedule" || $CI_PIPELINE_SOURCE == "web" + before_script: + - .ci/lib/gitlab_prepare_ci.sh + script: + - .ci/autoupdate.sh "$AUTOUPDATE_PACKAGES" + after_script: + - .ci/lib/move_logs.sh $CI_PROJECT_DIR + artifacts: + when: on_failure + paths: + - log.txt + - log_testsuite_pmaports.txt + - pmbootstrap.cfg