From d74a12b5a4ace17e64b5c068a46cf42c21352577 Mon Sep 17 00:00:00 2001 From: Andrew Noyes Date: Fri, 12 Jun 2026 11:13:32 -0400 Subject: [PATCH] Convert Jenkins CI to Gitea Actions Replace the Jenkinsfile with .gitea/workflows/ci.yml. The CI image is built from the Dockerfile and pushed to the Gitea container registry, rebuilt only when the Dockerfile or pre-commit config changes. The aarch64 release build now runs natively on an arm64 runner instead of cross-compiling, so the cross toolchain and qemu are dropped from the image. Artifacts still go to MinIO (via mc, skipped gracefully if credentials are not configured); ccache uses actions/cache instead of a host volume. --- .gitea/workflows/ci.yml | 241 ++++++++++++++++++++++++++++++++++++++++ Dockerfile | 7 +- Jenkinsfile | 151 ------------------------- 3 files changed, 245 insertions(+), 154 deletions(-) create mode 100644 .gitea/workflows/ci.yml delete mode 100644 Jenkinsfile diff --git a/.gitea/workflows/ci.yml b/.gitea/workflows/ci.yml new file mode 100644 index 0000000..53b0a30 --- /dev/null +++ b/.gitea/workflows/ci.yml @@ -0,0 +1,241 @@ +name: CI + +on: [push, pull_request] + +jobs: + build-image: + strategy: + fail-fast: false + matrix: + include: + - runner: ubuntu-latest-amd64 + arch: amd64 + - runner: ubuntu-latest-arm64 + arch: arm64 + runs-on: ${{ matrix.runner }} + steps: + - uses: actions/checkout@v4 + + - name: Log in to registry + run: docker login -u ${{ gitea.actor }} -p ${{ secrets.GITHUB_TOKEN }} git.weaselab.dev + + - name: Build and push image if changed + run: | + image=git.weaselab.dev/weaselab/conflict-set-ci + tag="$(sha256sum Dockerfile .pre-commit-config.yaml | sha256sum | cut -c 1-16)-${{ matrix.arch }}" + latest=latest-${{ matrix.arch }} + if docker manifest inspect "$image:$tag" > /dev/null 2>&1; then + if [ "$(docker manifest inspect "$image:$tag")" = "$(docker manifest inspect "$image:$latest" 2> /dev/null)" ]; then + echo "$image:$latest is up to date" + else + docker pull "$image:$tag" + docker tag "$image:$tag" "$image:$latest" + docker push "$image:$latest" + fi + else + docker build -t "$image:$tag" -t "$image:$latest" . + docker push "$image:$tag" + docker push "$image:$latest" + fi + + pre-commit: + needs: build-image + runs-on: ubuntu-latest-amd64 + container: + image: git.weaselab.dev/weaselab/conflict-set-ci:latest-amd64 + credentials: + username: ${{ gitea.actor }} + password: ${{ secrets.GITHUB_TOKEN }} + steps: + - uses: actions/checkout@v4 + + - name: Run pre-commit + env: + # use the hooks pre-installed in the image + HOME: /tmp + run: | + git config --global --add safe.directory "$PWD" + pre-commit run --all-files --show-diff-on-failure + + test: + needs: build-image + strategy: + fail-fast: false + matrix: + include: + - name: 64-bit-versions + cmake_args: -DCMAKE_CXX_FLAGS=-DUSE_64_BIT=1 + - name: debug + cmake_args: -DCMAKE_BUILD_TYPE=Debug + - name: simd-fallback + cmake_args: -DUSE_SIMD_FALLBACK=ON + - name: gcc + cmake_args: -DCMAKE_C_COMPILER=gcc -DCMAKE_CXX_COMPILER=g++ + runs-on: ubuntu-latest-amd64 + container: + image: git.weaselab.dev/weaselab/conflict-set-ci:latest-amd64 + credentials: + username: ${{ gitea.actor }} + password: ${{ secrets.GITHUB_TOKEN }} + steps: + - uses: actions/checkout@v4 + + - uses: actions/cache@v4 + with: + path: .ccache + key: ccache-${{ matrix.name }}-${{ gitea.sha }} + restore-keys: | + ccache-${{ matrix.name }}- + + - name: Build + run: | + export CCACHE_DIR="$GITHUB_WORKSPACE/.ccache" + rm -rf build + cmake -S . -B build -G Ninja -DCMAKE_CXX_COMPILER_LAUNCHER=ccache ${{ matrix.cmake_args }} + ninja -C build + ccache -s + + - name: Test + run: | + cd build + ctest --no-compress-output --test-output-size-passed 100000 --test-output-size-failed 100000 -T Test -j "$(nproc)" --timeout 90 > /dev/null + + - name: Upload test results to MinIO + if: always() + env: + MINIO_ACCESS_KEY: ${{ secrets.MINIO_ACCESS_KEY }} + MC_HOST_minio: https://${{ secrets.MINIO_ACCESS_KEY }}:${{ secrets.MINIO_SECRET_KEY }}@minio.weaselab.dev + run: | + if [ -z "$MINIO_ACCESS_KEY" ]; then + echo "MinIO credentials not configured; skipping upload" + exit 0 + fi + zstd build/Testing/*/Test.xml + mc cp build/Testing/*/Test.xml.zst "minio/jenkins/conflict-set/${{ gitea.run_number }}/${{ matrix.name }}/" + + release: + needs: build-image + strategy: + fail-fast: false + matrix: + include: + - runner: ubuntu-latest-amd64 + arch: amd64 + - runner: ubuntu-latest-arm64 + arch: arm64 + runs-on: ${{ matrix.runner }} + container: + image: git.weaselab.dev/weaselab/conflict-set-ci:latest-${{ matrix.arch }} + credentials: + username: ${{ gitea.actor }} + password: ${{ secrets.GITHUB_TOKEN }} + steps: + - uses: actions/checkout@v4 + + - uses: actions/cache@v4 + with: + path: .ccache + key: ccache-release-${{ matrix.arch }}-${{ gitea.sha }} + restore-keys: | + ccache-release-${{ matrix.arch }}- + + - name: Build + run: | + export CCACHE_DIR="$GITHUB_WORKSPACE/.ccache" + rm -rf build + cmake -S . -B build -G Ninja -DCMAKE_CXX_COMPILER_LAUNCHER=ccache -DCMAKE_CXX_FLAGS=-DNVALGRIND + ninja -C build + ccache -s + + - name: Test + run: | + cd build + ctest --no-compress-output --test-output-size-passed 100000 --test-output-size-failed 100000 -T Test -j "$(nproc)" --timeout 90 > /dev/null + + - name: Package + run: | + cd build + cpack -G DEB + cpack -G RPM + + - name: Build paper + if: matrix.arch == 'amd64' + run: | + cd paper + make + + - name: Upload artifacts to MinIO + if: always() + env: + MINIO_ACCESS_KEY: ${{ secrets.MINIO_ACCESS_KEY }} + MC_HOST_minio: https://${{ secrets.MINIO_ACCESS_KEY }}:${{ secrets.MINIO_SECRET_KEY }}@minio.weaselab.dev + run: | + if [ -z "$MINIO_ACCESS_KEY" ]; then + echo "MinIO credentials not configured; skipping upload" + exit 0 + fi + dest="minio/jenkins/conflict-set/${{ gitea.run_number }}/release-${{ matrix.arch }}/" + zstd build/Testing/*/Test.xml + mc cp build/Testing/*/Test.xml.zst "$dest" + mc cp build/*.deb build/*.rpm "$dest" + if compgen -G "paper/*.pdf" > /dev/null; then + mc cp paper/*.pdf "$dest" + fi + + coverage: + needs: build-image + runs-on: ubuntu-latest-amd64 + container: + image: git.weaselab.dev/weaselab/conflict-set-ci:latest-amd64 + credentials: + username: ${{ gitea.actor }} + password: ${{ secrets.GITHUB_TOKEN }} + steps: + - uses: actions/checkout@v4 + + - uses: actions/cache@v4 + with: + path: .ccache + key: ccache-coverage-${{ gitea.sha }} + restore-keys: | + ccache-coverage- + + - name: Build + run: | + export CCACHE_DIR="$GITHUB_WORKSPACE/.ccache" + rm -rf build + cmake -S . -B build -G Ninja -DCMAKE_CXX_COMPILER_LAUNCHER=ccache \ + -DCMAKE_C_FLAGS=--coverage -DCMAKE_CXX_FLAGS=--coverage \ + -DCMAKE_BUILD_TYPE=Debug -DDISABLE_TSAN=ON + ninja -C build + ccache -s + + - name: Test + run: | + cd build + ctest --no-compress-output --test-output-size-passed 100000 --test-output-size-failed 100000 -T Test -j "$(nproc)" --timeout 90 > /dev/null + + - name: Coverage report + run: | + gcov_args=(-f ConflictSet.cpp -f LongestCommonPrefix.h -f Metrics.h + --gcov-executable "llvm-cov gcov" --exclude-noncode-lines) + gcovr "${gcov_args[@]}" --cobertura > build/coverage.xml + gcovr "${gcov_args[@]}" + gcovr "${gcov_args[@]}" --fail-under-line 100 > /dev/null + + - name: Upload results to MinIO + if: always() + env: + MINIO_ACCESS_KEY: ${{ secrets.MINIO_ACCESS_KEY }} + MC_HOST_minio: https://${{ secrets.MINIO_ACCESS_KEY }}:${{ secrets.MINIO_SECRET_KEY }}@minio.weaselab.dev + run: | + if [ -z "$MINIO_ACCESS_KEY" ]; then + echo "MinIO credentials not configured; skipping upload" + exit 0 + fi + dest="minio/jenkins/conflict-set/${{ gitea.run_number }}/coverage/" + zstd build/Testing/*/Test.xml + mc cp build/Testing/*/Test.xml.zst "$dest" + if [ -e build/coverage.xml ]; then + mc cp build/coverage.xml "$dest" + fi diff --git a/Dockerfile b/Dockerfile index a306483..7c39cd3 100644 --- a/Dockerfile +++ b/Dockerfile @@ -8,13 +8,11 @@ RUN chmod -R 777 /tmp RUN apt-get update RUN apt-get upgrade -y RUN TZ=America/Los_Angeles DEBIAN_FRONTEND=noninteractive apt-get install -y \ - binutils-aarch64-linux-gnu \ build-essential \ ccache \ cmake \ curl \ devscripts \ - g++-aarch64-linux-gnu \ gcovr \ git \ gnupg \ @@ -24,13 +22,16 @@ RUN TZ=America/Los_Angeles DEBIAN_FRONTEND=noninteractive apt-get install -y \ ninja-build \ pre-commit \ python3-requests \ - qemu-user \ rpm \ software-properties-common \ texlive-full \ wget \ zstd +# MinIO client, for uploading build artifacts +RUN curl -Ls "https://dl.min.io/client/mc/release/linux-$(dpkg --print-architecture)/mc" \ + -o /usr/local/bin/mc && chmod +x /usr/local/bin/mc + # Install recent valgrind from source RUN curl -Ls https://sourceware.org/pub/valgrind/valgrind-3.22.0.tar.bz2 -o valgrind.tar.bz2 && \ echo "c811db5add2c5f729944caf47c4e7a65dcaabb9461e472b578765dd7bf6d2d4c valgrind.tar.bz2" > valgrind-sha.txt && \ diff --git a/Jenkinsfile b/Jenkinsfile deleted file mode 100644 index e4c1075..0000000 --- a/Jenkinsfile +++ /dev/null @@ -1,151 +0,0 @@ -def CleanBuildAndTest(String cmakeArgs) { - sh """ - export CCACHE_DIR=/ccache - rm -rf build - mkdir build - cd build - cmake .. -G Ninja -DCMAKE_CXX_COMPILER_LAUNCHER=ccache ${cmakeArgs} - ninja - ccache -s - """ - catchError { - sh ''' - cd build - ctest --no-compress-output --test-output-size-passed 100000 --test-output-size-failed 100000 -T Test -j `nproc` --timeout 90 > /dev/null - zstd Testing/*/Test.xml - ''' - } - xunit tools: [CTest(pattern: 'build/Testing/*/Test.xml')], skipPublishingChecks: false - minio bucket: 'jenkins', credentialsId: 'jenkins-minio', excludes: '', host: 'minio.weaselab.dev', includes: 'build/Testing/*/Test.xml.zst', targetFolder: '${JOB_NAME}/${BUILD_NUMBER}/${STAGE_NAME}/' -} - -pipeline { - agent any - stages { - stage('Pre-commit') { - agent { - dockerfile { - args '-v /home/jenkins/ccache:/ccache' - reuseNode true - } - } - steps { - script { - env.HOME = env.WORKSPACE - } - sh 'pre-commit run --all-files --show-diff-on-failure' - } - } - stage('64 bit versions') { - agent { - dockerfile { - args '-v /home/jenkins/ccache:/ccache' - reuseNode true - } - } - steps { - CleanBuildAndTest("-DCMAKE_CXX_FLAGS=-DUSE_64_BIT=1") - } - } - stage('Debug') { - agent { - dockerfile { - args '-v /home/jenkins/ccache:/ccache' - reuseNode true - } - } - steps { - CleanBuildAndTest("-DCMAKE_BUILD_TYPE=Debug") - } - } - stage('SIMD fallback') { - agent { - dockerfile { - args '-v /home/jenkins/ccache:/ccache' - reuseNode true - } - } - steps { - CleanBuildAndTest("-DUSE_SIMD_FALLBACK=ON") - } - } - stage('Release [clang]') { - agent { - dockerfile { - args '-v /home/jenkins/ccache:/ccache' - reuseNode true - } - } - steps { - CleanBuildAndTest("-DCMAKE_CXX_FLAGS=-DNVALGRIND") - recordIssues(tools: [clang()]) - sh ''' - cd build - cpack -G DEB - cpack -G RPM - ''' - sh ''' - cd paper - make - ''' - minio bucket: 'jenkins', credentialsId: 'jenkins-minio', excludes: '', host: 'minio.weaselab.dev', includes: 'build/*.deb,build/*.rpm,paper/*.pdf', targetFolder: '${JOB_NAME}/${BUILD_NUMBER}/${STAGE_NAME}/' - } - } - stage('gcc') { - agent { - dockerfile { - args '-v /home/jenkins/ccache:/ccache' - reuseNode true - } - } - steps { - CleanBuildAndTest("-DCMAKE_C_COMPILER=gcc -DCMAKE_CXX_COMPILER=g++") - recordIssues(tools: [gcc()]) - } - } - stage('Release [clang,aarch64]') { - agent { - dockerfile { - args '-v /home/jenkins/ccache:/ccache' - reuseNode true - } - } - steps { - CleanBuildAndTest("-DCMAKE_TOOLCHAIN_FILE=../aarch64-toolchain.cmake -DCMAKE_CXX_FLAGS=-DNVALGRIND") - sh ''' - cd build - cpack -G DEB - cpack -G RPM - ''' - minio bucket: 'jenkins', credentialsId: 'jenkins-minio', excludes: '', host: 'minio.weaselab.dev', includes: 'build/*.deb,build/*.rpm', targetFolder: '${JOB_NAME}/${BUILD_NUMBER}/${STAGE_NAME}' - } - } - stage('Coverage') { - agent { - dockerfile { - args '-v /home/jenkins/ccache:/ccache' - reuseNode true - } - } - steps { - script { - gcov_args = "-f ConflictSet.cpp -f LongestCommonPrefix.h -f Metrics.h --gcov-executable 'llvm-cov gcov' --exclude-noncode-lines" - } - CleanBuildAndTest("-DCMAKE_C_FLAGS=--coverage -DCMAKE_CXX_FLAGS=--coverage -DCMAKE_BUILD_TYPE=Debug -DDISABLE_TSAN=ON") - sh """ - gcovr ${gcov_args} --cobertura > build/coverage.xml - """ - recordCoverage qualityGates: [[criticality: 'NOTE', metric: 'MODULE']], tools: [[parser: 'COBERTURA', pattern: 'build/coverage.xml']] - sh """ - gcovr ${gcov_args} - gcovr ${gcov_args} --fail-under-line 100 > /dev/null - """ - } - } - } - post { - always { - emailext mimeType: 'text/html', body: '${SCRIPT, template="groovy-html.template"}', subject: "${env.JOB_NAME} - Build# ${env.BUILD_NUMBER} - ${currentBuild.currentResult}", to: 'andrew@weaselab.dev' - } - } -}