Skip to content

Build and test

Build and test #43

Workflow file for this run

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