mirror of
https://github.com/git-for-windows/git.git
synced 2026-02-04 03:33:01 -06:00
Introduce a CI check that verifies that our Rust code is well-formatted. This check uses `cargo fmt`, which is a wrapper around rustfmt(1) that executes formatting for all Rust source files. rustfmt(1) itself is the de-facto standard for formatting code in the Rust ecosystem. The rustfmt(1) tool allows to tweak the final format in theory. In practice though, the Rust ecosystem has aligned on style "editions". These editions only exist to ensure that any potential changes to the style don't cause reformats to existing code bases. Other than that, most Rust projects out there accept this default style of a specific edition. Let's do the same and use that default style. It may not be anyone's favorite, but it is consistent and by making it part of our CI we also enforce it right from the start. Note that we don't have to pick a specific style edition here, as the edition is automatically derived from the edition we have specified in our "Cargo.toml" file. The implemented script looks somewhat weird as we perfom manual error handling instead of using something like `set -e`. The intent here is that subsequent commits will add more checks, and we want to execute all of these checks regardless of whether or not a previous check failed. Signed-off-by: Patrick Steinhardt <ps@pks.im> Signed-off-by: Junio C Hamano <gitster@pobox.com>
506 lines
17 KiB
YAML
506 lines
17 KiB
YAML
name: CI
|
|
|
|
on: [push, pull_request]
|
|
|
|
env:
|
|
DEVELOPER: 1
|
|
|
|
# If more than one workflow run is triggered for the very same commit hash
|
|
# (which happens when multiple branches pointing to the same commit), only
|
|
# the first one is allowed to run, the second will be kept in the "queued"
|
|
# state. 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.
|
|
#
|
|
# The only caveat is that if a workflow run is triggered for the same commit
|
|
# hash that another run is already being held, that latter run will be
|
|
# canceled. 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.sha }}
|
|
|
|
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@v7
|
|
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@v4
|
|
- uses: git-for-windows/setup-git-for-windows-sdk@v1
|
|
- 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@v4
|
|
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@v4
|
|
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@v1
|
|
- name: test
|
|
shell: bash
|
|
run: . /etc/profile && ci/run-test-slice.sh ${{matrix.nr}} 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@v4
|
|
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@v4
|
|
- uses: git-for-windows/setup-git-for-windows-sdk@v1
|
|
- name: initialize vcpkg
|
|
uses: actions/checkout@v4
|
|
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@v2
|
|
- 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@v4
|
|
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@v1
|
|
- name: download tracked files and build artifacts
|
|
uses: actions/download-artifact@v4
|
|
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}} 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@v4
|
|
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@v4
|
|
- uses: actions/setup-python@v5
|
|
- 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@v4
|
|
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@v4
|
|
- uses: actions/setup-python@v5
|
|
- name: Set up dependencies
|
|
shell: pwsh
|
|
run: pip install meson ninja
|
|
- name: Download build artifacts
|
|
uses: actions/download-artifact@v4
|
|
with:
|
|
name: windows-meson-artifacts
|
|
path: build
|
|
- name: Test
|
|
shell: pwsh
|
|
run: meson test -C build --no-rebuild --print-errorlogs --slice "$(1+${{ matrix.nr }})/10"
|
|
|
|
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-13
|
|
- jobname: osx-reftable
|
|
cc: clang
|
|
pool: macos-13
|
|
- jobname: osx-gcc
|
|
cc: gcc-13
|
|
pool: macos-13
|
|
- jobname: osx-meson
|
|
cc: clang
|
|
pool: macos-13
|
|
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@v4
|
|
- 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@v4
|
|
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@v4
|
|
- 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
|
|
image: ubuntu:rolling
|
|
cc: clang
|
|
- jobname: linux-TEST-vars
|
|
image: ubuntu:20.04
|
|
cc: gcc
|
|
cc_package: gcc-8
|
|
- 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
|
|
# Supported until 2025-04-02.
|
|
- jobname: linux32
|
|
image: i386/ubuntu:focal
|
|
# A RHEL 8 compatible distro. Supported until 2029-05-31.
|
|
- jobname: almalinux-8
|
|
image: almalinux:8
|
|
# Supported until 2026-08-31.
|
|
- jobname: debian-11
|
|
image: debian:11
|
|
env:
|
|
jobname: ${{matrix.vector.jobname}}
|
|
CC: ${{matrix.vector.cc}}
|
|
CI_JOB_IMAGE: ${{matrix.vector.image}}
|
|
CUSTOM_PATH: /custom
|
|
runs-on: ubuntu-latest
|
|
container: ${{matrix.vector.image}}
|
|
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@v4
|
|
- run: ci/install-dependencies.sh
|
|
- run: useradd builder --create-home
|
|
- run: chown -R builder .
|
|
- run: 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@v4
|
|
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-22.04
|
|
runs-on: ubuntu-22.04
|
|
concurrency:
|
|
group: static-analysis-${{ github.ref }}
|
|
cancel-in-progress: ${{ needs.ci-config.outputs.skip_concurrent == 'yes' }}
|
|
steps:
|
|
- uses: actions/checkout@v4
|
|
- 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@v4
|
|
- 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@v4
|
|
- 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@v4
|
|
- run: ci/install-dependencies.sh
|
|
- run: ci/test-documentation.sh
|