Files
git/.github/workflows/main.yml
T
Patrick Steinhardt 3fff230cf5 ci: improve reftable test coverage
The "linux-reftable" job exercises Git with reftables as its default
backend. But this job is arguably redundant because we already have the
"linux-reftable-leaks" job that exercises reftables with the leak
sanitizer enabled, and it is unlikely that we will catch any extra bugs
with the leak sanitizer disabled.

One may thus be triggered to just drop the "linux-reftable" job in favor
of the leak-checking variant. But the latter disables a couple of other
tests that exercise git-p4, git-svn and other tools. Those tools may not
be an essential part of Git nowadays, but I don't quite feel comfortable
with reducing test coverage.

Instead, adapt the job to run reftables together with SHA256. which is
an area that we don't have test coverage for.

Signed-off-by: Patrick Steinhardt <ps@pks.im>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2026-10-15 07:24:26 -07:00

541 lines
19 KiB
YAML

name: CI
on: [push, pull_request]
env:
DEVELOPER: 1
# For pull requests, only the latest workflow run is allowed to proceed.
# Older runs are canceled when a new revision is pushed.
#
# For pushes, if more than one workflow run is triggered for the very same
# commit hash (which happens when multiple branches point to the same commit),
# only the first one is allowed to run. This allows a successful completion of
# the first run to be reused in the second run via the `skip-if-redundant`
# logic in the `config` job.
#
# For more details about the `concurrency` attribute, see:
# https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#concurrency
concurrency:
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.sha }}
cancel-in-progress: ${{ github.event_name == 'pull_request' }}
jobs:
ci-config:
name: config
if: vars.CI_BRANCHES == '' || contains(vars.CI_BRANCHES, github.ref_name)
runs-on: ubuntu-latest
outputs:
enabled: ${{ steps.check-ref.outputs.enabled }}${{ steps.skip-if-redundant.outputs.enabled }}
skip_concurrent: ${{ steps.check-ref.outputs.skip_concurrent }}
steps:
- name: try to clone ci-config branch
run: |
git -c protocol.version=2 clone \
--no-tags \
--single-branch \
-b ci-config \
--depth 1 \
--no-checkout \
--filter=blob:none \
https://github.com/${{ github.repository }} \
config-repo &&
cd config-repo &&
git checkout HEAD -- ci/config || : ignore
- id: check-ref
name: check whether CI is enabled for ref
run: |
enabled=yes
if test -x config-repo/ci/config/allow-ref
then
echo "::warning::ci/config/allow-ref is deprecated; use CI_BRANCHES instead"
if ! config-repo/ci/config/allow-ref '${{ github.ref }}'
then
enabled=no
fi
fi
skip_concurrent=yes
if test -x config-repo/ci/config/skip-concurrent &&
! config-repo/ci/config/skip-concurrent '${{ github.ref }}'
then
skip_concurrent=no
fi
echo "enabled=$enabled" >>$GITHUB_OUTPUT
echo "skip_concurrent=$skip_concurrent" >>$GITHUB_OUTPUT
- name: skip if the commit or tree was already tested
id: skip-if-redundant
uses: actions/github-script@v9
if: steps.check-ref.outputs.enabled == 'yes'
with:
github-token: ${{secrets.GITHUB_TOKEN}}
script: |
try {
// Figure out workflow ID, commit and tree
const { data: run } = await github.rest.actions.getWorkflowRun({
owner: context.repo.owner,
repo: context.repo.repo,
run_id: context.runId,
});
const workflow_id = run.workflow_id;
const head_sha = run.head_sha;
const tree_id = run.head_commit.tree_id;
// See whether there is a successful run for that commit or tree
const { data: runs } = await github.rest.actions.listWorkflowRuns({
owner: context.repo.owner,
repo: context.repo.repo,
per_page: 500,
status: 'success',
workflow_id,
});
for (const run of runs.workflow_runs) {
if (head_sha === run.head_sha) {
core.warning(`Successful run for the commit ${head_sha}: ${run.html_url}`);
core.setOutput('enabled', ' but skip');
break;
}
if (run.head_commit && tree_id === run.head_commit.tree_id) {
core.warning(`Successful run for the tree ${tree_id}: ${run.html_url}`);
core.setOutput('enabled', ' but skip');
break;
}
}
} catch (e) {
core.warning(e);
}
windows-build:
name: win build
needs: ci-config
if: needs.ci-config.outputs.enabled == 'yes'
runs-on: windows-latest
concurrency:
group: windows-build-${{ github.ref }}
cancel-in-progress: ${{ needs.ci-config.outputs.skip_concurrent == 'yes' }}
steps:
- uses: actions/checkout@v6
- uses: git-for-windows/setup-git-for-windows-sdk@v2
- name: Install GCC-compatible Rust target
shell: bash
run: |
# The hosted Windows runners ship a rustup-managed Rust whose
# default toolchain targets the MSVC ABI. That produces a
# `gitcore.lib` which the MinGW GCC used by the rest of the
# build cannot link. Install the precompiled `std` for a
# GCC-compatible target triple matching the MSYS2 subsystem;
# the Makefile selects the same triple via $(MSYSTEM) and
# passes it to `cargo build --target`.
case "$MSYSTEM" in
CLANGARM64) target=aarch64-pc-windows-gnullvm ;;
CLANG64) target=x86_64-pc-windows-gnullvm ;;
CLANG32) target=i686-pc-windows-gnullvm ;;
UCRT64) target=x86_64-pc-windows-gnu ;;
MINGW64) target=x86_64-pc-windows-gnu ;;
MINGW32) target=i686-pc-windows-gnu ;;
*) echo "::error::Unsupported MSYSTEM: $MSYSTEM"; exit 1 ;;
esac &&
rustup target add "$target" &&
# Ensure that cargo.exe is found even with the minimal SDK's restricted PATH
CARGO="$(type -p cargo.exe)" &&
echo "export PATH=\$PATH:${CARGO%/cargo.exe}" >>/etc/profile
- name: build
shell: bash
env:
HOME: ${{runner.workspace}}
NO_PERL: 1
run: . /etc/profile && ci/make-test-artifacts.sh artifacts
- name: zip up tracked files
run: git archive -o artifacts/tracked.tar.gz HEAD
- name: upload tracked files and build artifacts
uses: actions/upload-artifact@v7
with:
name: windows-artifacts
path: artifacts
windows-test:
name: win test
runs-on: windows-latest
needs: [ci-config, windows-build]
strategy:
fail-fast: false
matrix:
nr: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
concurrency:
group: windows-test-${{ matrix.nr }}-${{ github.ref }}
cancel-in-progress: ${{ needs.ci-config.outputs.skip_concurrent == 'yes' }}
steps:
- name: download tracked files and build artifacts
uses: actions/download-artifact@v8
with:
name: windows-artifacts
path: ${{github.workspace}}
- name: extract tracked files and build artifacts
shell: bash
run: tar xf artifacts.tar.gz && tar xf tracked.tar.gz
- uses: git-for-windows/setup-git-for-windows-sdk@v2
- name: test
shell: bash
run: . /etc/profile && ci/run-test-slice.sh $((${{matrix.nr}} + 1)) 10
- name: print test failures
if: failure() && env.FAILED_TEST_ARTIFACTS != ''
shell: bash
run: ci/print-test-failures.sh
- name: Upload failed tests' directories
if: failure() && env.FAILED_TEST_ARTIFACTS != ''
uses: actions/upload-artifact@v7
with:
name: failed-tests-windows-${{ matrix.nr }}
path: ${{env.FAILED_TEST_ARTIFACTS}}
vs-build:
name: win+VS build
needs: ci-config
if: github.event.repository.owner.login == 'git-for-windows' && needs.ci-config.outputs.enabled == 'yes'
env:
NO_PERL: 1
GIT_CONFIG_PARAMETERS: "'user.name=CI' 'user.email=ci@git'"
runs-on: windows-latest
concurrency:
group: vs-build-${{ github.ref }}
cancel-in-progress: ${{ needs.ci-config.outputs.skip_concurrent == 'yes' }}
steps:
- uses: actions/checkout@v6
- uses: git-for-windows/setup-git-for-windows-sdk@v2
- name: initialize vcpkg
uses: actions/checkout@v6
with:
repository: 'microsoft/vcpkg'
path: 'compat/vcbuild/vcpkg'
- name: download vcpkg artifacts
uses: git-for-windows/get-azure-pipelines-artifact@v0
with:
repository: git/git
definitionId: 9
- name: add msbuild to PATH
uses: microsoft/setup-msbuild@v3
- name: copy dlls to root
shell: cmd
run: compat\vcbuild\vcpkg_copy_dlls.bat release
- name: generate Visual Studio solution
shell: bash
run: |
cmake `pwd`/contrib/buildsystems/ -DCMAKE_PREFIX_PATH=`pwd`/compat/vcbuild/vcpkg/installed/x64-windows \
-DNO_GETTEXT=YesPlease -DPERL_TESTS=OFF -DPYTHON_TESTS=OFF -DCURL_NO_CURL_CMAKE=ON
- name: MSBuild
run: msbuild git.sln -property:Configuration=Release -property:Platform=x64 -maxCpuCount:4 -property:PlatformToolset=v142
- name: bundle artifact tar
shell: bash
env:
MSVC: 1
VCPKG_ROOT: ${{github.workspace}}\compat\vcbuild\vcpkg
run: |
mkdir -p artifacts &&
eval "$(make -n artifacts-tar INCLUDE_DLLS_IN_ARTIFACTS=YesPlease ARTIFACTS_DIRECTORY=artifacts NO_GETTEXT=YesPlease 2>&1 | grep ^tar)"
- name: zip up tracked files
run: git archive -o artifacts/tracked.tar.gz HEAD
- name: upload tracked files and build artifacts
uses: actions/upload-artifact@v7
with:
name: vs-artifacts
path: artifacts
vs-test:
name: win+VS test
runs-on: windows-latest
needs: [ci-config, vs-build]
strategy:
fail-fast: false
matrix:
nr: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
concurrency:
group: vs-test-${{ matrix.nr }}-${{ github.ref }}
cancel-in-progress: ${{ needs.ci-config.outputs.skip_concurrent == 'yes' }}
steps:
- uses: git-for-windows/setup-git-for-windows-sdk@v2
- name: download tracked files and build artifacts
uses: actions/download-artifact@v8
with:
name: vs-artifacts
path: ${{github.workspace}}
- name: extract tracked files and build artifacts
shell: bash
run: tar xf artifacts.tar.gz && tar xf tracked.tar.gz
- name: test
shell: bash
env:
NO_SVN_TESTS: 1
run: . /etc/profile && ci/run-test-slice.sh $((${{matrix.nr}} + 1)) 10
- name: print test failures
if: failure() && env.FAILED_TEST_ARTIFACTS != ''
shell: bash
run: ci/print-test-failures.sh
- name: Upload failed tests' directories
if: failure() && env.FAILED_TEST_ARTIFACTS != ''
uses: actions/upload-artifact@v7
with:
name: failed-tests-windows-vs-${{ matrix.nr }}
path: ${{env.FAILED_TEST_ARTIFACTS}}
windows-meson-build:
name: win+Meson build
needs: ci-config
if: needs.ci-config.outputs.enabled == 'yes'
runs-on: windows-latest
concurrency:
group: windows-meson-build-${{ github.ref }}
cancel-in-progress: ${{ needs.ci-config.outputs.skip_concurrent == 'yes' }}
steps:
- uses: actions/checkout@v6
- uses: actions/setup-python@v6
- name: Set up dependencies
shell: pwsh
run: pip install meson ninja
- name: Setup
shell: pwsh
run: meson setup build --vsenv -Dbuildtype=release -Dperl=disabled -Dcredential_helpers=wincred
- name: Compile
shell: pwsh
run: meson compile -C build
- name: Upload build artifacts
uses: actions/upload-artifact@v7
with:
name: windows-meson-artifacts
path: build
windows-meson-test:
name: win+Meson test
runs-on: windows-latest
needs: [ci-config, windows-meson-build]
strategy:
fail-fast: false
matrix:
nr: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
concurrency:
group: windows-meson-test-${{ matrix.nr }}-${{ github.ref }}
cancel-in-progress: ${{ needs.ci-config.outputs.skip_concurrent == 'yes' }}
steps:
- uses: actions/checkout@v6
- uses: actions/setup-python@v6
- name: Set up dependencies
shell: pwsh
run: pip install meson ninja
- name: Download build artifacts
uses: actions/download-artifact@v8
with:
name: windows-meson-artifacts
path: build
- name: Test
shell: bash
run: ci/run-test-slice-meson.sh build $((${{matrix.nr}} + 1)) 10
- name: print test failures
if: failure() && env.FAILED_TEST_ARTIFACTS != ''
shell: bash
run: ci/print-test-failures.sh
- name: Upload failed tests' directories
if: failure() && env.FAILED_TEST_ARTIFACTS != ''
uses: actions/upload-artifact@v7
with:
name: failed-tests-windows-meson-${{ matrix.nr }}
path: ${{env.FAILED_TEST_ARTIFACTS}}
regular:
name: ${{matrix.vector.jobname}} (${{matrix.vector.pool}})
needs: ci-config
if: needs.ci-config.outputs.enabled == 'yes'
concurrency:
group: ${{ matrix.vector.jobname }}-${{ matrix.vector.pool }}-${{ github.ref }}
cancel-in-progress: ${{ needs.ci-config.outputs.skip_concurrent == 'yes' }}
strategy:
fail-fast: false
matrix:
vector:
- jobname: osx-clang
cc: clang
pool: macos-14
- jobname: osx-reftable
cc: clang
pool: macos-14
- jobname: osx-gcc
cc: gcc-13
pool: macos-14
- jobname: osx-meson
cc: clang
pool: macos-14
env:
CC: ${{matrix.vector.cc}}
CC_PACKAGE: ${{matrix.vector.cc_package}}
jobname: ${{matrix.vector.jobname}}
CI_JOB_IMAGE: ${{matrix.vector.pool}}
TEST_OUTPUT_DIRECTORY: ${{github.workspace}}/t
runs-on: ${{matrix.vector.pool}}
steps:
- uses: actions/checkout@v6
- run: ci/install-dependencies.sh
- run: ci/run-build-and-tests.sh
- name: print test failures
if: failure() && env.FAILED_TEST_ARTIFACTS != ''
run: ci/print-test-failures.sh
- name: Upload failed tests' directories
if: failure() && env.FAILED_TEST_ARTIFACTS != ''
uses: actions/upload-artifact@v7
with:
name: failed-tests-${{matrix.vector.jobname}}
path: ${{env.FAILED_TEST_ARTIFACTS}}
fuzz-smoke-test:
name: fuzz smoke test
needs: ci-config
if: needs.ci-config.outputs.enabled == 'yes'
env:
CC: clang
CI_JOB_IMAGE: ubuntu-latest
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
- run: ci/install-dependencies.sh
- run: ci/run-build-and-minimal-fuzzers.sh
dockerized:
name: ${{matrix.vector.jobname}} (${{matrix.vector.image}})
needs: ci-config
if: needs.ci-config.outputs.enabled == 'yes'
concurrency:
group: dockerized-${{ matrix.vector.jobname }}-${{ matrix.vector.image }}-${{ github.ref }}
cancel-in-progress: ${{ needs.ci-config.outputs.skip_concurrent == 'yes' }}
strategy:
fail-fast: false
matrix:
vector:
- jobname: linux-sha256
image: ubuntu:rolling
cc: clang
- jobname: linux-reftable-sha256
image: ubuntu:rolling
cc: clang
- jobname: linux-feature-testbed
image: ubuntu:latest
- jobname: linux-breaking-changes
cc: gcc
image: ubuntu:rolling
- jobname: fedora-breaking-changes-meson
image: fedora:latest
- jobname: linux-leaks
image: ubuntu:rolling
cc: gcc
- jobname: linux-reftable-leaks
image: ubuntu:rolling
cc: gcc
- jobname: linux-asan-ubsan
image: ubuntu:rolling
cc: clang
- jobname: linux-meson
image: ubuntu:rolling
cc: gcc
- jobname: linux-musl-meson
image: alpine:latest
- jobname: linux32
image: i386/debian:latest
# A RHEL 8 compatible distro. Supported until 2029-05-31.
- jobname: almalinux-8
image: almalinux:8
# Supported until 2028-06-30.
- jobname: debian-12
image: debian:12
env:
jobname: ${{matrix.vector.jobname}}
CC: ${{matrix.vector.cc}}
CI_JOB_IMAGE: ${{matrix.vector.image}}
CUSTOM_PATH: /custom
runs-on: ubuntu-latest
container:
image: ${{ matrix.vector.image }}
options: ${{ github.repository_visibility == 'private' && '--pids-limit 16384 --ulimit nproc=16384:16384 --ulimit nofile=32768:32768' || '' }}
steps:
- name: prepare libc6 for actions
if: matrix.vector.jobname == 'linux32'
run: apt -q update && apt -q -y install libc6-amd64 lib64stdc++6
- name: install git in container
run: |
if command -v git
then
: # nothing to do
elif command -v apk
then
apk add --update git
elif command -v dnf
then
dnf -yq update && dnf -yq install git
else
apt-get -q update && apt-get -q -y install git
fi
- uses: actions/checkout@v6
- run: ci/install-dependencies.sh
- run: useradd builder --create-home
- run: chown -R builder .
- run: chmod a+w $GITHUB_ENV && sudo --preserve-env --set-home --user=builder ci/run-build-and-tests.sh
- name: print test failures
if: failure() && env.FAILED_TEST_ARTIFACTS != ''
run: sudo --preserve-env --set-home --user=builder ci/print-test-failures.sh
- name: Upload failed tests' directories
if: failure() && env.FAILED_TEST_ARTIFACTS != ''
uses: actions/upload-artifact@v7
with:
name: failed-tests-${{matrix.vector.jobname}}
path: ${{env.FAILED_TEST_ARTIFACTS}}
static-analysis:
needs: ci-config
if: needs.ci-config.outputs.enabled == 'yes'
env:
jobname: StaticAnalysis
CI_JOB_IMAGE: ubuntu-latest
runs-on: ubuntu-latest
concurrency:
group: static-analysis-${{ github.ref }}
cancel-in-progress: ${{ needs.ci-config.outputs.skip_concurrent == 'yes' }}
steps:
- uses: actions/checkout@v6
- run: ci/install-dependencies.sh
- run: ci/run-static-analysis.sh
- run: ci/check-directional-formatting.bash
rust-analysis:
needs: ci-config
if: needs.ci-config.outputs.enabled == 'yes'
env:
jobname: RustAnalysis
CI_JOB_IMAGE: ubuntu:rolling
runs-on: ubuntu-latest
container: ubuntu:rolling
concurrency:
group: rust-analysis-${{ github.ref }}
cancel-in-progress: ${{ needs.ci-config.outputs.skip_concurrent == 'yes' }}
steps:
- uses: actions/checkout@v6
- run: ci/install-dependencies.sh
- run: ci/run-rust-checks.sh
sparse:
needs: ci-config
if: needs.ci-config.outputs.enabled == 'yes'
env:
jobname: sparse
CI_JOB_IMAGE: ubuntu-22.04
runs-on: ubuntu-22.04
concurrency:
group: sparse-${{ github.ref }}
cancel-in-progress: ${{ needs.ci-config.outputs.skip_concurrent == 'yes' }}
steps:
- uses: actions/checkout@v6
- name: Install other dependencies
run: ci/install-dependencies.sh
- run: make sparse
documentation:
name: documentation
needs: ci-config
if: needs.ci-config.outputs.enabled == 'yes'
concurrency:
group: documentation-${{ github.ref }}
cancel-in-progress: ${{ needs.ci-config.outputs.skip_concurrent == 'yes' }}
env:
jobname: Documentation
CI_JOB_IMAGE: ubuntu-latest
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
- run: ci/install-dependencies.sh
- run: ci/test-documentation.sh