Build and test #43
Workflow file for this run
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
name: Build and test | |
on: | |
push: | |
# Empty configuration means use default (ie. test all branches) | |
branches-ignore: | |
# Everything would have passed bors before going into devel | |
- devel | |
# Bors temporary branches | |
- staging.tmp | |
- trying.tmp | |
- staging-squash-merge.tmp | |
# Github Merge Queue temporary branches | |
- gh-readonly-queue/** | |
pull_request: | |
# Only take PRs to devel | |
branches: | |
- devel | |
# Type of events to run CI on | |
types: | |
- opened | |
- synchronize | |
- reopened | |
- ready_for_review | |
merge_group: | |
# Test all additions to merge queue | |
workflow_call: | |
# Allow the workflow to be reused elsewhere | |
# Run every script actions in bash | |
defaults: | |
run: | |
shell: bash | |
jobs: | |
cancel: | |
if: github.event == 'merge_group' || github.event == 'pull_request' | |
name: Cancel previous runs (Merge Queue/PR) | |
runs-on: ubuntu-latest | |
permissions: | |
actions: write | |
steps: | |
- uses: pierreraffa/[email protected] | |
pre_run: | |
name: Provide additional context for the workflow | |
runs-on: ubuntu-latest | |
outputs: | |
skip: ${{ steps.skip_result.outputs.result }} | |
target_matrix: ${{ steps.matrix.outputs.result }} | |
shared_builder: ${{ steps.matrix.outputs.shared }} | |
steps: | |
- id: skip_result | |
name: Whether to skip checks | |
run: | | |
if [[ '${{ github.event.pull_request.draft }}' == true ]]; then | |
echo "Pull request is in draft state, skipping" | |
echo "result=true" >> $GITHUB_OUTPUT | |
else | |
echo "result=false" >> $GITHUB_OUTPUT | |
fi | |
- id: matrix | |
name: Obtain build target matrix | |
run: | | |
# This matrix will be shared by the jobs following it. | |
# | |
# The schema is: | |
# [ | |
# { | |
# name: String, ## The name of the target being tested | |
# runner: String ## The runner to use of this target | |
# shared_builder?: Bool ## Whether this target should be used to | |
# ## build artifacts shared between | |
# ## platforms. Only one target may have | |
# ## this attribute. | |
# } | |
# ] | |
cat << "EOF" > matrix.json | |
[ | |
{ | |
"name": "Linux", | |
"runner": "ubuntu-20.04", | |
"shared_builder": true | |
}, | |
{ | |
"name": "macOS", | |
"runner": "macos-12" | |
}, | |
{ | |
"name": "macOS (M1)", | |
"runner": "macos-14" | |
}, | |
{ | |
"name": "Windows", | |
"runner": "windows-2022" | |
} | |
] | |
EOF | |
# Use jq to compact the matrix into one line to be used as the result | |
echo "result=$(jq -c . matrix.json)" >> $GITHUB_OUTPUT | |
# Isolate the shared builder into its own thing as well | |
echo "shared=$(jq -c '.[] | select(.shared_builder)' matrix.json)" >> $GITHUB_OUTPUT | |
binaries: | |
needs: [pre_run] | |
if: needs.pre_run.outputs.skip != 'true' | |
strategy: | |
fail-fast: false | |
matrix: | |
target: ${{ fromJson(needs.pre_run.outputs.target_matrix) }} | |
name: Build release binaries (${{ matrix.target.name }}) | |
runs-on: ${{ matrix.target.runner }} | |
steps: | |
- uses: actions/checkout@v4 | |
with: | |
fetch-depth: 0 | |
filter: tree:0 | |
- name: Enable annotations | |
run: echo "::add-matcher::.github/nim-problem-matcher.json" | |
- name: Install MinGW (Windows) | |
if: runner.os == 'Windows' | |
uses: ./.github/actions/setup-mingw | |
- name: Setup vcpkg (Windows) | |
if: runner.os == 'Windows' | |
uses: ./.github/actions/setup-vcpkg | |
with: | |
triplet: x64-mingw-dynamic-release | |
host-triplet: x64-mingw-dynamic-release | |
revision: 2024.01.12 | |
overlay-triplets: ${{ github.workspace }}/tools/vcpkg/triplets | |
- name: Install dependencies (Windows) | |
if: runner.os == 'Windows' | |
run: vcpkg install pcre sqlite3 | |
- name: Download CA certificates (Windows) | |
if: runner.os == 'Windows' | |
run: | | |
$binPath = Join-Path $PWD "vcpkg" "installed" "x64-mingw-dynamic-release" "bin" | |
Invoke-WebRequest https://curl.se/ca/cacert.pem -OutFile (Join-Path $binPath "cacert.pem") | |
shell: pwsh | |
- name: Set Xcode version (macOS M1) | |
if: runner.os == 'macOS' && runner.arch == 'ARM64' | |
uses: maxim-lobanov/setup-xcode@v1 | |
with: | |
xcode-version: "15.0.1" | |
- name: Set macOS SDK version (macOS M1) | |
if: runner.os == 'macOS' && runner.arch == 'ARM64' | |
run: | | |
sdkpath=$(xcrun --sdk macosx14.0 --show-sdk-path) | |
echo "SDKROOT=$sdkpath" >> "$GITHUB_ENV" | |
- name: Build release binaries | |
run: ./koch.py all-strict | |
- name: Upload workspace to artifacts | |
uses: ./.github/actions/upload-compiler | |
test: | |
needs: [pre_run, binaries] | |
strategy: | |
fail-fast: false | |
matrix: | |
target: ${{ fromJson(needs.pre_run.outputs.target_matrix) }} | |
# This controls the testament "batch" feature. | |
# | |
# If any additional batches are added, increment `total_batch` as well. | |
# | |
# This feature allow us to parallelize testing. | |
batch: [0, 1] | |
# This tells testament how many batches are used. Have to be placed in | |
# an array due to how Github Actions process matrices. | |
total_batch: [2] | |
name: "Test the compiler and stdlib (${{ matrix.target.name }}, batch #${{ matrix.batch }})" | |
runs-on: ${{ matrix.target.runner }} | |
steps: | |
- uses: actions/checkout@v4 | |
with: | |
fetch-depth: 0 | |
filter: tree:0 | |
- uses: ./.github/actions/download-compiler | |
- name: Install NodeJS | |
uses: actions/setup-node@v4 | |
with: | |
node-version: "16" | |
- name: Install dependencies (Linux) | |
if: runner.os == 'Linux' | |
run: | | |
deps=( | |
# Required by ARC/ORC memory leak tests (only enabled on linux x64) | |
libc6-dbg | |
valgrind | |
) | |
sudo apt-get update | |
sudo apt-get install "${deps[@]}" | |
- name: Set Xcode version (macOS M1) | |
if: runner.os == 'macOS' && runner.arch == 'ARM64' | |
uses: maxim-lobanov/setup-xcode@v1 | |
with: | |
xcode-version: "15.0.1" | |
- name: Set macOS SDK version (macOS M1) | |
if: runner.os == 'macOS' && runner.arch == 'ARM64' | |
run: | | |
sdkpath=$(xcrun --sdk macosx14.0 --show-sdk-path) | |
echo "SDKROOT=$sdkpath" >> "$GITHUB_ENV" | |
- name: Install dependencies (macOS) | |
if: runner.os == 'macOS' | |
run: | | |
brew update | |
- name: Install MinGW (Windows) | |
if: runner.os == 'Windows' | |
uses: ./.github/actions/setup-mingw | |
- name: Add DLLs to PATH (Windows) | |
if: runner.os == 'Windows' | |
run: | | |
$binPath = Join-Path $PWD "vcpkg" "installed" "x64-mingw-dynamic-release" "bin" | |
$binPath | Out-File -Append $env:GITHUB_PATH | |
shell: pwsh | |
- name: Run tester | |
run: ./koch.py test --batch:'${{ matrix.batch }}_${{ matrix.total_batch }}' --tryFailing all | |
- name: Print all test errors | |
if: failure() | |
run: bin/nim r tools/ci_testresults | |
tooling: | |
needs: [pre_run, binaries] | |
strategy: | |
fail-fast: false | |
matrix: | |
target: ${{ fromJson(needs.pre_run.outputs.target_matrix) }} | |
name: Build and test tooling (${{ matrix.target.name }}) | |
runs-on: ${{ matrix.target.runner }} | |
steps: | |
- uses: actions/checkout@v4 | |
with: | |
fetch-depth: 0 | |
filter: tree:0 | |
- name: Install MinGW (Windows) | |
if: runner.os == 'Windows' | |
uses: ./.github/actions/setup-mingw | |
- name: Add DLLs to PATH (Windows) | |
if: runner.os == 'Windows' | |
run: | | |
$binPath = Join-Path $PWD "vcpkg" "installed" "x64-mingw-dynamic-release" "bin" | |
$binPath | Out-File -Append $env:GITHUB_PATH | |
shell: pwsh | |
- name: Set Xcode version (macOS M1) | |
if: runner.os == 'macOS' && runner.arch == 'ARM64' | |
uses: maxim-lobanov/setup-xcode@v1 | |
with: | |
xcode-version: "15.0.1" | |
- name: Set macOS SDK version (macOS M1) | |
if: runner.os == 'macOS' && runner.arch == 'ARM64' | |
run: | | |
sdkpath=$(xcrun --sdk macosx14.0 --show-sdk-path) | |
echo "SDKROOT=$sdkpath" >> "$GITHUB_ENV" | |
- uses: ./.github/actions/download-compiler | |
- name: Enable annotations | |
run: echo "::add-matcher::.github/nim-problem-matcher.json" | |
- name: Test tooling | |
run: ./koch.py testTools | |
source: | |
needs: [pre_run, binaries] | |
name: Build source archive | |
runs-on: ${{ fromJson(needs.pre_run.outputs.shared_builder).runner }} | |
steps: | |
- uses: actions/checkout@v4 | |
with: | |
fetch-depth: 0 | |
filter: tree:0 | |
- uses: ./.github/actions/download-compiler | |
- name: Enable annotations | |
run: echo "::add-matcher::.github/nim-problem-matcher.json" | |
- name: Generate csources | |
run: ./koch.py csource -d:danger | |
- id: archive | |
name: Build release source | |
run: | | |
./koch.py archive | |
archive=build/archive/$(jq -r .name build/archive/archive.json) | |
# Rename the archive manifest to avoid collision with manifest of | |
# other archives | |
mv build/archive/archive.json build/archive/source.json | |
echo "archive=$archive" >> $GITHUB_OUTPUT | |
echo "metadata=build/archive/source.json" >> $GITHUB_OUTPUT | |
- name: Publish source archive to artifacts | |
uses: actions/upload-artifact@v4 | |
with: | |
name: source archive | |
path: | | |
${{ steps.archive.outputs.archive }} | |
${{ steps.archive.outputs.metadata }} | |
if-no-files-found: error | |
source_binaries: | |
needs: [pre_run, source] | |
strategy: | |
fail-fast: false | |
matrix: | |
target: ${{ fromJson(needs.pre_run.outputs.target_matrix) }} | |
name: Build release artifacts from source archive (${{ matrix.target.name }}) | |
runs-on: ${{ matrix.target.runner }} | |
steps: | |
- name: Get actions | |
uses: actions/checkout@v4 | |
with: | |
path: git-src | |
sparse-checkout: .github/actions | |
- name: Install MinGW (Windows) | |
if: runner.os == 'Windows' | |
uses: ./git-src/.github/actions/setup-mingw | |
- name: Set Xcode version (macOS M1) | |
if: runner.os == 'macOS' && runner.arch == 'ARM64' | |
uses: maxim-lobanov/setup-xcode@v1 | |
with: | |
xcode-version: "15.0.1" | |
- name: Set macOS SDK version (macOS M1) | |
if: runner.os == 'macOS' && runner.arch == 'ARM64' | |
run: | | |
sdkpath=$(xcrun --sdk macosx14.0 --show-sdk-path) | |
echo "SDKROOT=$sdkpath" >> "$GITHUB_ENV" | |
- name: Download source archive | |
uses: actions/download-artifact@v4 | |
with: | |
name: source archive | |
path: source-archive | |
- name: Unpack source archive | |
run: | | |
archive=source-archive/$(jq -r .name source-archive/source.json) | |
# Pipe from zstd to tar because macOS' tar does not support unpacking zstd | |
zstd -c -d "$archive" | tar -xf - --strip-components 1 | |
- name: Setup vcpkg (Windows) | |
if: runner.os == 'Windows' | |
uses: ./git-src/.github/actions/setup-vcpkg | |
with: | |
triplet: x64-mingw-dynamic-release | |
host-triplet: x64-mingw-dynamic-release | |
revision: 2024.01.12 | |
overlay-triplets: ${{ github.workspace }}/tools/vcpkg/triplets | |
- name: Install dependencies (Windows) | |
if: runner.os == 'Windows' | |
run: vcpkg install pcre sqlite3 | |
- name: Add DLLs to PATH (Windows) | |
if: runner.os == 'Windows' | |
run: | | |
$binPath = Join-Path $PWD "vcpkg" "installed" "x64-mingw-dynamic-release" "bin" | |
$binPath | Out-File -Append $env:GITHUB_PATH | |
shell: pwsh | |
- name: Install DLLs to package (Windows) | |
if: runner.os == 'Windows' | |
run: | | |
$binPath = Join-Path $PWD "vcpkg" "installed" "x64-mingw-dynamic-release" "bin" | |
$binPath | Out-File -Append $env:GITHUB_PATH | |
Copy-Item (Join-Path $binPath "libpcre.dll") -Destination bin | |
shell: pwsh | |
- name: Build release binaries | |
run: ./koch.py all | |
# Note: keep synchronized with package job | |
- name: Build docs | |
run: | | |
./koch.py doc \ | |
--git.url:'https://github.com/${{ github.repository }}' \ | |
--git.commit:'${{ github.sha }}' \ | |
--git.devel:devel | |
# Remove leftover nimskullcache | |
rm -rf doc/html/nimskullcache | |
- id: package | |
name: Create release package | |
run: | | |
releasecmd=unixrelease | |
if [[ "$RUNNER_OS" == Windows ]]; then | |
releasecmd=winrelease | |
fi | |
./koch.py "$releasecmd" | |
archive=build/archive/$(jq -r .name build/archive/archive.json) | |
# Rename the archive manifest to avoid collision with other artifacts | |
os=$(jq -r .os build/archive/archive.json) | |
cpu=$(jq -r .cpu build/archive/archive.json) | |
metadata=build/archive/${os}_${cpu}.json | |
mv build/archive/archive.json "$metadata" | |
# Let the uploader know what to upload | |
echo "archive=$archive" >> $GITHUB_OUTPUT | |
echo "metadata=$metadata" >> $GITHUB_OUTPUT | |
- name: Upload release package to artifacts | |
uses: actions/upload-artifact@v4 | |
with: | |
name: binaries from source archive ${{ matrix.target.name }} | |
path: | | |
${{ steps.package.outputs.archive }} | |
${{ steps.package.outputs.metadata }} | |
if-no-files-found: error | |
package: | |
needs: [pre_run, binaries] | |
strategy: | |
fail-fast: false | |
matrix: | |
target: ${{ fromJson(needs.pre_run.outputs.target_matrix) }} | |
name: Build docs and release artifacts (${{ matrix.target.name }}) | |
runs-on: ${{ matrix.target.runner }} | |
steps: | |
- uses: actions/checkout@v4 | |
with: | |
fetch-depth: 0 | |
filter: tree:0 | |
- uses: ./.github/actions/download-compiler | |
- name: Enable annotations | |
run: echo "::add-matcher::.github/nim-problem-matcher.json" | |
- name: Install MinGW (Windows) | |
if: runner.os == 'Windows' | |
uses: ./.github/actions/setup-mingw | |
- name: Add DLLs to PATH (Windows) | |
if: runner.os == 'Windows' | |
run: | | |
$binPath = Join-Path $PWD "vcpkg" "installed" "x64-mingw-dynamic-release" "bin" | |
$binPath | Out-File -Append $env:GITHUB_PATH | |
shell: pwsh | |
- name: Install DLLs to package (Windows) | |
if: runner.os == 'Windows' | |
run: | | |
$binPath = Join-Path $PWD "vcpkg" "installed" "x64-mingw-dynamic-release" "bin" | |
$binPath | Out-File -Append $env:GITHUB_PATH | |
Copy-Item (Join-Path $binPath "libpcre.dll") -Destination bin | |
shell: pwsh | |
- name: Set Xcode version (macOS M1) | |
if: runner.os == 'macOS' && runner.arch == 'ARM64' | |
uses: maxim-lobanov/setup-xcode@v1 | |
with: | |
xcode-version: "15.0.1" | |
- name: Set macOS SDK version (macOS M1) | |
if: runner.os == 'macOS' && runner.arch == 'ARM64' | |
run: | | |
sdkpath=$(xcrun --sdk macosx14.0 --show-sdk-path) | |
echo "SDKROOT=$sdkpath" >> "$GITHUB_ENV" | |
# Note: keep synchronized with source_binaries job | |
- name: Build docs | |
run: | | |
./koch.py doc \ | |
--git.url:'https://github.com/${{ github.repository }}' \ | |
--git.commit:'${{ github.sha }}' \ | |
--git.devel:devel | |
# Remove leftover nimskullcache | |
rm -rf doc/html/nimskullcache | |
- id: package | |
name: Create release package | |
run: | | |
releasecmd=unixrelease | |
if [[ "$RUNNER_OS" == Windows ]]; then | |
releasecmd=winrelease | |
fi | |
./koch.py "$releasecmd" | |
archive=build/archive/$(jq -r .name build/archive/archive.json) | |
# Rename the archive manifest to avoid collision with other artifacts | |
os=$(jq -r .os build/archive/archive.json) | |
cpu=$(jq -r .cpu build/archive/archive.json) | |
metadata=build/archive/${os}_${cpu}.json | |
mv build/archive/archive.json "$metadata" | |
# Let the uploader know what to upload | |
echo "archive=$archive" >> $GITHUB_OUTPUT | |
echo "metadata=$metadata" >> $GITHUB_OUTPUT | |
- name: Upload release package to artifacts | |
uses: actions/upload-artifact@v4 | |
with: | |
name: release binaries ${{ matrix.target.name }} | |
path: | | |
${{ steps.package.outputs.archive }} | |
${{ steps.package.outputs.metadata }} | |
if-no-files-found: error | |
test_package: | |
needs: [pre_run, package, source_binaries] | |
name: Test release artifacts | |
runs-on: ${{ fromJSON(needs.pre_run.outputs.shared_builder).runner }} | |
steps: | |
- uses: actions/checkout@v4 | |
with: | |
fetch-depth: 0 | |
filter: tree:0 | |
- uses: ./.github/actions/download-compiler | |
- name: Enable annotations | |
run: echo "::add-matcher::.github/nim-problem-matcher.json" | |
- name: Download binaries built from source archive | |
uses: actions/download-artifact@v4 | |
with: | |
pattern: binaries from source archive* | |
path: binary-from-source | |
merge-multiple: true | |
- name: Download release package | |
uses: actions/download-artifact@v4 | |
with: | |
# Download all release binaries to the same folder | |
pattern: release binaries* | |
path: release-binary | |
merge-multiple: true | |
- name: Download release source archive | |
uses: actions/download-artifact@v4 | |
with: | |
name: source archive | |
path: source-archive | |
- name: Install tools | |
run: | | |
sudo apt-get update | |
sudo apt-get install -yqq --no-install-recommends diffoscope | |
- id: diff | |
name: Binaries from git and source archive should be the same | |
run: | | |
output_html=$RUNNER_TEMP/diffoscope.html | |
run_diff() { | |
# Exclude directory metadata as we only care about the files themselves | |
diffoscope \ | |
--html="$output_html" \ | |
--exclude-directory-metadata=yes \ | |
release-binary/ binary-from-source/ | |
} | |
if ! run_diff; then | |
echo "::error::There are differences when building from source archive compared to building from git, check the output uploaded to artifacts for more details" | |
echo "result=$output_html" >> $GITHUB_OUTPUT | |
exit 1 | |
else | |
echo "Success! Binaries built from git and source archive are the same" | |
fi | |
- name: Upload difference test result on failure | |
if: failure() && steps.diff.outputs.result != '' | |
uses: actions/upload-artifact@v4 | |
with: | |
name: differences between binary from source archive and git | |
path: ${{ steps.diff.outputs.result }} | |
- name: Verify archive manifests | |
run: | | |
# Verify them by using the manifest builder tool to create a manifest | |
# for the full bundle. | |
bin/nim c tools/release_manifest.nim | |
cd release-binary | |
../tools/release_manifest add ../source-archive/*.json *.json | |
# Print the resulting manifest | |
echo "Success! Generated manifest:" | |
jq . manifest.json | |
# This allow the publisher to run the tool directly without having to | |
# clone the compiler. | |
- name: Upload release manifest tool | |
uses: actions/upload-artifact@v4 | |
with: | |
name: release manifest tool | |
path: tools/release_manifest | |
passed: | |
name: All check passed | |
needs: | |
- binaries | |
- test | |
- tooling | |
- source | |
- source_binaries | |
- package | |
- test_package | |
if: always() | |
runs-on: ubuntu-latest | |
steps: | |
- name: Raise failure | |
if: contains(needs.*.result, 'failure') || contains(needs.*.result, 'cancelled') | |
run: | | |
echo "::error::There are failing required jobs" | |
exit 1 |