]> git.ipfire.org Git - thirdparty/gnutls.git/commitdiff
devel/ci-local.sh: add a gitlab-ci-local wrapper
authorAlexander Sosedkin <asosedkin@redhat.com>
Mon, 2 Mar 2026 12:51:48 +0000 (13:51 +0100)
committerAlexander Sosedkin <asosedki@redhat.com>
Fri, 6 Mar 2026 14:05:45 +0000 (14:05 +0000)
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 <asosedkin@redhat.com>
.gitignore
devel/ci-local.sh [new file with mode: 0755]

index 88583f593f2cf74dd6a69ed14b5e01cb6e4ed192..8353b592132b2019ca1563aa05133030c5d838a8 100644 (file)
@@ -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 (executable)
index 0000000..ed55fbf
--- /dev/null
@@ -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 $?