From: Alexander Sosedkin Date: Mon, 2 Mar 2026 12:51:48 +0000 (+0100) Subject: devel/ci-local.sh: add a gitlab-ci-local wrapper X-Git-Tag: 3.8.13~19^2 X-Git-Url: http://git.ipfire.org/gitweb/index.cgi?a=commitdiff_plain;h=29c1d61cd8f4187a408b602b9f4e793a4e4ebff6;p=thirdparty%2Fgnutls.git devel/ci-local.sh: add a gitlab-ci-local wrapper gitlab-ci-local doesn't play nicely with gnutls out of the box. This adds a wrapper that smoothes several wrinkles out: 1. if you're using worktrees, bootstrapping submodules fails 2. there's no way to pass arbitrary arguments like `--remote` to podman 3. `artifacts: untracked: true` doesn't work without `paths` specified 4. commit-check job is skipped by default Signed-off-by: Alexander Sosedkin --- diff --git a/.gitignore b/.gitignore index 88583f593f..8353b59213 100644 --- a/.gitignore +++ b/.gitignore @@ -192,6 +192,8 @@ fuzz/*_fuzzer *.gcda *.gcno *.gcov +.gitlab-ci-local +.gitlab-ci-local.yml /gl/* !/gl/override /GNUmakefile diff --git a/devel/ci-local.sh b/devel/ci-local.sh new file mode 100755 index 0000000000..ed55fbfa4e --- /dev/null +++ b/devel/ci-local.sh @@ -0,0 +1,91 @@ +#!/bin/bash +# Run GitLab CI jobs locally via gitlab-ci-local, working around its quirks. +# +# Usage: +# devel/ci-local.sh --needs 'fedora/test: [no-fips,no-pqc,no-ktls]' +# +# More useful gitlab-ci-local options: --privileged +# +# Dependencies: gitlab-ci-local, yq, podman or docker + +set -Eeuo pipefail; shopt -s inherit_errexit + +CI_REGISTRY="${CI_REGISTRY:-registry.gitlab.com}" +CONTAINER_EXECUTABLE="${CONTAINER_EXECUTABLE:-podman}" +SKIP_COMMIT_CHECK="${SKIP_COMMIT_CHECK:-true}" +CLONE_SUBMODULES="${CLONE_SUBMODULES:-true}" + +[[ -e .gitlab-ci.yml ]] || { echo "error: run from the git root" >&2; exit 1; } + +cleanup=() +on_exit() { + # sync .gitlab-ci-local back to the worktree for caching + if [[ -n "${srcdir:-}" ]] && [[ -d .gitlab-ci-local ]]; then + echo "copying .gitlab-ci-local back to $srcdir" >&2 + rsync -a .gitlab-ci-local "$srcdir/" + fi + [[ -z "${cleanup[*]}" ]] || rm -rf "${cleanup[@]}" +} +trap on_exit EXIT + +# Quirk 1: +# gitlab-ci-local doesn't like worktrees. rsync to a tmpdir, git init, +# run gitlab-ci-local, then rsync .gitlab-ci-local back for caching +if [[ -f .git ]]; then + srcdir=$(realpath .) + tmpdir=$(mktemp -d) + cleanup+=("$tmpdir") + rsync -a --exclude=.git . "$tmpdir/" + cd "$tmpdir" + orig_gitdir=$(sed -n 's/^gitdir: //p' "$srcdir/.git") + git init -q + cp "$orig_gitdir/index" .git/index + CLONE_SUBMODULES=false + git submodule update --init --depth 1 || true + rm -f .gitmodules + git add -A + git -c gc.autoDetach=false commit -q -m "local ci run" +fi + +# Quirk 2: +# --container-executable values like "podman --remote" need a wrapper script +if [[ "$(echo "$CONTAINER_EXECUTABLE")" = *" "* ]]; then + wrapper="$(mktemp)" + echo -e '#!/bin/sh\nexec %s "$@"\n' "$CONTAINER_EXECUTABLE" > "$wrapper" + chmod +x "$wrapper" + cleanup+=("$wrapper") + CONTAINER_EXECUTABLE="$wrapper" +fi + +# generate a gitlab-ci-local compatible .gitlab-ci-local.yml overrides file +{ + echo '# auto-generated by devel/ci-local.sh — do not edit.\n' + + # Quirk 3: + # add explicit "paths:" to "artifacts: untracked: true" without them + yq eval ' + to_entries[] | + select(.value | has("artifacts")) | + select(.value.artifacts.untracked == true) | + select(.value.artifacts | has("paths") | not) | + .key + ' .gitlab-ci.yml | while IFS= read -r key; do + echo -e "${key}:\n artifacts:\n paths:\n - ./\n" + done + + # Optional: skip commit-check for local runs by default, it's annoying + [[ "$SKIP_COMMIT_CHECK" = true ]] && \ + echo -e 'commit-check:\n rules:\n - when: never\n' + + [[ "$CLONE_SUBMODULES" = false ]] && \ + echo -e 'variables:\n GIT_SUBMODULE_STRATEGY: none\n' +} > .gitlab-ci-local.yml + +# run gitlab-ci-local with some reasonable defaults +gitlab-ci-local \ + --container-executable "$CONTAINER_EXECUTABLE" \ + --ignore-predefined-vars CI_REGISTRY \ + --variable "CI_REGISTRY=$CI_REGISTRY" \ + --no-artifacts-to-source \ + "$@" +exit $?