Skip to content

Update HCR fixture for watch rebuilds #2438

Update HCR fixture for watch rebuilds

Update HCR fixture for watch rebuilds #2438

Workflow file for this run

name: Codetracer CI
on:
push:
branches:
- main
pull_request:
permissions:
contents: read
id-token: write
jobs:
windows-bootstrap-smoke:
runs-on: windows-latest
steps:
- name: Checkout
uses: actions/checkout@v5
- name: Validate env.sh syntax
shell: bash
run: |
set -euo pipefail
test -f env.sh
bash -n env.sh
- name: Validate PowerShell parser
shell: pwsh
run: |
$scriptPaths = @(
"env.ps1",
"non-nix-build/windows/toolchain-utils.ps1",
"non-nix-build/windows/ensure-rust.ps1",
"non-nix-build/windows/ensure-just.ps1",
"non-nix-build/windows/ensure-nextest.ps1",
"non-nix-build/windows/ensure-node.ps1",
"non-nix-build/windows/ensure-uv.ps1",
"non-nix-build/windows/ensure-nim.ps1",
"non-nix-build/windows/ensure-capnp.ps1",
"non-nix-build/windows/ensure-tup.ps1",
"non-nix-build/windows/ensure-ct-remote.ps1",
"non-nix-build/windows/ensure-nargo.ps1",
"non-nix-build/windows/ensure-ttd.ps1",
"non-nix-build/windows/validate-toolchain-versions.ps1",
"non-nix-build/windows/validate-env-path-entries.ps1"
)
foreach ($scriptPath in $scriptPaths) {
if (-not (Test-Path -LiteralPath $scriptPath)) {
throw "Missing required file: $scriptPath"
}
$parseErrors = $null
[void][System.Management.Automation.Language.Parser]::ParseFile(
$scriptPath,
[ref]$null,
[ref]$parseErrors
)
if ($parseErrors.Count -gt 0) {
$parseErrors | ForEach-Object { Write-Error "${scriptPath}: $($_.Message)" }
throw "PowerShell parser reported one or more errors."
}
}
- name: Validate toolchain-versions.env
shell: pwsh
run: |
pwsh -File non-nix-build/windows/validate-toolchain-versions.ps1
- name: Validate env.ps1 PATH helper
shell: pwsh
run: |
pwsh -File non-nix-build/windows/validate-env-path-entries.ps1
- name: Validate arm64 mode routing smoke checks
shell: pwsh
run: |
$windowsDir = "non-nix-build/windows"
function Invoke-BootstrapProbe {
param(
[Parameter(Mandatory = $true)][string]$Name,
[Parameter(Mandatory = $true)][hashtable]$Env,
[Parameter(Mandatory = $true)][scriptblock]$Action,
[Parameter(Mandatory = $true)][string[]]$RequiredPatterns,
[string[]]$ForbiddenPatterns = @()
)
$installRoot = Join-Path $env:RUNNER_TEMP ("codetracer-bootstrap-routing-" + $Name)
if (Test-Path -LiteralPath $installRoot) {
Remove-Item -LiteralPath $installRoot -Recurse -Force
}
New-Item -ItemType Directory -Path $installRoot -Force | Out-Null
$savedPath = $env:PATH
$savedArchOverride = $env:WINDOWS_DIY_ARCH_OVERRIDE
$savedEnv = @{}
foreach ($envKey in $Env.Keys) {
$savedEnv[$envKey] = [Environment]::GetEnvironmentVariable($envKey)
[Environment]::SetEnvironmentVariable($envKey, [string]$Env[$envKey])
}
[Environment]::SetEnvironmentVariable("WINDOWS_DIY_ARCH_OVERRIDE", "arm64")
$env:PATH = "$env:SystemRoot\System32;$env:SystemRoot"
$probeOutput = @()
try {
$probeSucceeded = $true
$probeOutput = & $Action $installRoot 2>&1
} catch {
$probeSucceeded = $false
$probeOutput = @($probeOutput) + $_.Exception.Message + ($_ | Out-String -Width 10000)
} finally {
$env:PATH = $savedPath
[Environment]::SetEnvironmentVariable("WINDOWS_DIY_ARCH_OVERRIDE", $savedArchOverride)
foreach ($envKey in $Env.Keys) {
[Environment]::SetEnvironmentVariable($envKey, $savedEnv[$envKey])
}
}
$probeText = ($probeOutput | Out-String -Width 10000)
if ($probeSucceeded) {
throw "Probe '$Name' unexpectedly succeeded. Expected a fast-fail source-route assertion."
}
foreach ($pattern in $RequiredPatterns) {
if ($probeText -notmatch $pattern) {
throw "Probe '$Name' output is missing required pattern '$pattern'."
}
}
foreach ($pattern in $ForbiddenPatterns) {
if ($probeText -match $pattern) {
throw "Probe '$Name' output matched forbidden pattern '$pattern'."
}
}
}
# Load shared modules
. "$windowsDir/toolchain-utils.ps1"
. "$windowsDir/ensure-nim.ps1"
. "$windowsDir/ensure-capnp.ps1"
. "$windowsDir/ensure-ct-remote.ps1"
# Parse toolchain versions
$toolchainPath = Join-Path $windowsDir "toolchain-versions.env"
$toolchain = @{}
foreach ($line in Get-Content -LiteralPath $toolchainPath) {
if ($line -match '^\s*#' -or [string]::IsNullOrWhiteSpace($line)) { continue }
if ($line -notmatch '^\s*([A-Za-z_][A-Za-z0-9_]*)=(.*)$') { continue }
$name = $matches[1]
$value = $matches[2].Trim()
if ($value.StartsWith('"') -and $value.EndsWith('"') -and $value.Length -ge 2) {
$value = $value.Substring(1, $value.Length - 2)
}
$toolchain[$name] = $value
}
Invoke-BootstrapProbe `
-Name "nim-auto-arm64-source-first" `
-Env @{
"NIM_WINDOWS_SOURCE_MODE" = "auto"
} `
-Action {
param($installRoot)
$arch = Get-WindowsArch
Ensure-Nim -Root $installRoot -Arch $arch -Toolchain $toolchain
} `
-RequiredPatterns @(
"NIM_WINDOWS_SOURCE_MODE=auto attempted Nim source bootstrap on 'arm64' and failed:",
"Prebuilt fallback is x64-only"
) `
-ForbiddenPatterns @(
"Falling back to pinned prebuilt asset",
"NIM_WINDOWS_SOURCE_MODE=prebuilt"
)
Invoke-BootstrapProbe `
-Name "capnp-auto-arm64-source-route" `
-Env @{
"CAPNP_WINDOWS_SOURCE_MODE" = "auto"
} `
-Action {
param($installRoot)
$arch = Get-WindowsArch
Ensure-Capnp -Root $installRoot -Arch $arch -Toolchain $toolchain
} `
-RequiredPatterns @(
"git is required for source bootstrap but was not found on PATH"
) `
-ForbiddenPatterns @(
"capnproto-c\\+\\+-win32-"
)
Invoke-BootstrapProbe `
-Name "ct-remote-auto-arm64-local-route" `
-Env @{
"CT_REMOTE_WINDOWS_SOURCE_MODE" = "auto"
"CT_REMOTE_WINDOWS_SOURCE_REPO" = (Join-Path $env:RUNNER_TEMP "codetracer-ci-missing-routes")
} `
-Action {
param($installRoot)
$arch = Get-WindowsArch
Ensure-CtRemote -Root $installRoot -Arch $arch -Toolchain $toolchain -WindowsDir $windowsDir
} `
-RequiredPatterns @(
"CT_REMOTE_WINDOWS_SOURCE_MODE=auto on 'arm64' requires local source project",
"Pinned download is x64-only"
) `
-ForbiddenPatterns @(
"Installing ct-remote from pinned download",
"Falling back to pinned download"
)
windows-named-pipe-tests:
runs-on: windows-latest
steps:
- name: Checkout
uses: actions/checkout@v5
- name: Install Rust toolchain
uses: dtolnay/rust-toolchain@stable
- name: Run Windows named-pipe transport tests
working-directory: src/tui
shell: pwsh
run: cargo test --bin simple-tui windows_named_pipe -- --nocapture
windows-rust-components:
runs-on: windows-latest
steps:
- name: Checkout
uses: actions/checkout@v5
with:
submodules: recursive
token: ${{ secrets.GH_READ_METACRAFT_PRIVATE_REPOS }}
- name: Install Rust toolchain
uses: dtolnay/rust-toolchain@stable
with:
components: clippy
- name: Install capnproto
shell: pwsh
run: choco install capnproto -y
- name: Generate tree-sitter-nim parser
shell: pwsh
run: |
npm install -g tree-sitter-cli
cd libs/tree-sitter-nim
tree-sitter generate
- name: Build db-backend
working-directory: src/db-backend
shell: bash
run: cargo build
- name: Test db-backend
working-directory: src/db-backend
shell: bash
run: cargo test
- name: Build backend-manager
working-directory: src/backend-manager
shell: bash
run: cargo build
- name: Build tui
working-directory: src/tui
shell: bash
run: cargo build
- name: Clippy db-backend
working-directory: src/db-backend
shell: bash
run: cargo clippy --all-targets -- -D warnings
- name: Clippy backend-manager
working-directory: src/backend-manager
shell: bash
run: cargo clippy --all-targets -- -D warnings
- name: Clippy tui
working-directory: src/tui
shell: bash
run: cargo clippy --all-targets -- -D warnings
- name: Test tui named pipe
working-directory: src/tui
shell: bash
run: cargo test --bin simple-tui windows_named_pipe
# Headless DAP test suite on Windows using MCR backend.
# Installs all dependencies via env.ps1, builds ct-mcr from the
# codetracer-native-recorder sibling, then runs the Rust DAP integration tests.
windows-headless-test:
runs-on: windows-latest
name: test (headless DAP, Windows)
needs:
- windows-rust-components
steps:
- name: Generate CI token
id: app-token
uses: actions/create-github-app-token@v1
with:
app-id: ${{ vars.CI_TOKEN_PROVIDER_APP_ID }}
private-key: ${{ secrets.CI_TOKEN_PROVIDER_PRIVATE_KEY }}
owner: metacraft-labs
- name: Checkout repository
uses: actions/checkout@v5
with:
submodules: recursive
token: ${{ steps.app-token.outputs.token }}
- name: Resolve codetracer-native-recorder ref
id: resolve-mcr-ref
shell: bash
run: |
PINS=".github/sibling-pins"
REF="main"
if [ -f "${PINS}" ]; then
PIN_REF="$(grep '^codetracer-native-recorder ' "${PINS}" | cut -d' ' -f2)" || true
[ -n "${PIN_REF}" ] && REF="${PIN_REF}"
fi
echo "ref=${REF}" >> "$GITHUB_OUTPUT"
- name: Clone codetracer-native-recorder
uses: metacraft-labs/metacraft-github-actions/clone-repo@main
with:
repo: metacraft-labs/codetracer-native-recorder
ref: ${{ steps.resolve-mcr-ref.outputs.ref }}
path: ${{ github.workspace }}/../codetracer-native-recorder
gh-token: ${{ steps.app-token.outputs.token }}
submodules: 'true'
- name: Bootstrap Windows dev environment
shell: pwsh
env:
WINDOWS_DIY_ENSURE_TTD: "false"
run: |
. .\env.ps1
# Export PATH and key env vars for subsequent steps
$env:PATH -split ';' | ForEach-Object {
if ($_ -ne '') { Add-Content -Path $env:GITHUB_PATH -Value $_ }
}
@(
"GCC_DIR", "GO_DIR", "GOROOT", "ZSTD_DIR", "CARGO_HOME",
"RUSTUP_HOME", "CC", "CXX", "CT_NIM_CC_FLAGS", "NIM1",
"CAPNP_DIR", "WINDOWS_DIY_SHIMS_DIR", "WINDOWS_DIY_INSTALL_ROOT",
"CODETRACER_REPO_ROOT_PATH", "CODETRACER_PREFIX",
"CODETRACER_E2E_CT_PATH"
) | ForEach-Object {
$val = [Environment]::GetEnvironmentVariable($_, "Process")
if ($val) { Add-Content -Path $env:GITHUB_ENV -Value "$_=$val" }
}
- name: Install Nim dependencies
shell: bash
run: nimble install results stew -y
- name: Build ct-mcr.exe
shell: bash
run: |
cd "${{ github.workspace }}/../codetracer-native-recorder/ct_cli"
nim c --cc:vcc \
--path:../ct_time_model/src --path:../ct_events/src \
--path:../ct_ringbuf/src --path:../ct_runtime/src \
--path:../ct_recorder/src --path:../ct_replayer/src \
--path:../ct_debugserver/src --path:../ct_trace_store/src \
--path:../ct_interpose/src --path:../ct_instrument/src \
--path:../ct_snapshot/src --path:../ct_sync/src \
-o:ct_mcr.exe src/ct_cli.nim
- name: Build ct_interpose.dll
shell: bash
run: |
cd "${{ github.workspace }}/../codetracer-native-recorder"
nim c --app:lib --cc:vcc --mm:orc \
-o:ct_interpose/ct_interpose.dll \
ct_interpose/src/ct_interpose/library_init_windows.nim
- name: Build db-backend
working-directory: src/db-backend
shell: bash
run: cargo build --release
- name: Build backend-manager
working-directory: src/backend-manager
shell: bash
run: cargo build --release
- name: Run headless DAP tests (MCR backend)
shell: bash
env:
CODETRACER_CT_MCR_CMD: ${{ github.workspace }}/../codetracer-native-recorder/ct_cli/ct_mcr.exe
CODETRACER_ALLOW_GRACEFUL_TEST_SKIPPING: "false"
CODETRACER_USE_GCC: "1"
CODETRACER_GDB_CMD: gdb
CODETRACER_GCC_CMD: gcc
CODETRACER_GPP_CMD: g++
working-directory: src/db-backend
run: |
cargo nextest run --release --test '*' \
-E 'test(~dap) and not test(~bash_flow) and not test(~zsh_flow) and not test(~javascript_flow)'
lint-bash:
runs-on: [self-hosted, nixos]
steps:
- name: Checkout
uses: actions/checkout@v5
with:
submodules: recursive
token: ${{ secrets.GH_READ_METACRAFT_PRIVATE_REPOS }}
- name: Install Nix
uses: ./.github/actions/setup-nix
with:
cachix-auth-token: ${{ secrets.CACHIX_AUTH_TOKEN }}
cachix-cache: ${{ vars.CACHIX_CACHE }}
trusted-public-keys: ${{ vars.TRUSTED_PUBLIC_KEYS }}
substituters: ${{ vars.SUBSTITUTERS }}
gh-token: ${{ secrets.GH_READ_METACRAFT_PRIVATE_REPOS }}
- run: "nix develop .#devShells.x86_64-linux.default -c ./ci/lint/bash.sh"
lint-nim:
runs-on: [self-hosted, nixos]
steps:
- name: Checkout
uses: actions/checkout@v5
with:
submodules: recursive
token: ${{ secrets.GH_READ_METACRAFT_PRIVATE_REPOS }}
- name: Install Nix
uses: ./.github/actions/setup-nix
with:
cachix-auth-token: ${{ secrets.CACHIX_AUTH_TOKEN }}
cachix-cache: ${{ vars.CACHIX_CACHE }}
trusted-public-keys: ${{ vars.TRUSTED_PUBLIC_KEYS }}
substituters: ${{ vars.SUBSTITUTERS }}
gh-token: ${{ secrets.GH_READ_METACRAFT_PRIVATE_REPOS }}
- run: "nix develop .#devShells.x86_64-linux.default -c ./ci/lint/nim.sh"
lint-nix:
runs-on: [self-hosted, nixos]
steps:
- name: Checkout
uses: actions/checkout@v5
with:
submodules: recursive
token: ${{ secrets.GH_READ_METACRAFT_PRIVATE_REPOS }}
- name: Install Nix
uses: ./.github/actions/setup-nix
with:
cachix-auth-token: ${{ secrets.CACHIX_AUTH_TOKEN }}
cachix-cache: ${{ vars.CACHIX_CACHE }}
trusted-public-keys: ${{ vars.TRUSTED_PUBLIC_KEYS }}
substituters: ${{ vars.SUBSTITUTERS }}
gh-token: ${{ secrets.GH_READ_METACRAFT_PRIVATE_REPOS }}
- run: "nix develop .#devShells.x86_64-linux.default -c ./ci/lint/nix.sh"
lint-rust:
runs-on: [self-hosted, nixos]
steps:
- name: Checkout
uses: actions/checkout@v5
with:
submodules: recursive
token: ${{ secrets.GH_READ_METACRAFT_PRIVATE_REPOS }}
- name: Install Nix
uses: ./.github/actions/setup-nix
with:
cachix-auth-token: ${{ secrets.CACHIX_AUTH_TOKEN }}
cachix-cache: ${{ vars.CACHIX_CACHE }}
trusted-public-keys: ${{ vars.TRUSTED_PUBLIC_KEYS }}
substituters: ${{ vars.SUBSTITUTERS }}
gh-token: ${{ secrets.GH_READ_METACRAFT_PRIVATE_REPOS }}
- run: "nix develop .#devShells.x86_64-linux.default -c ./ci/lint/rust.sh"
reprobuild-macos-smoke:
runs-on: [self-hosted, darwin, nix-darwin, aarch64-darwin]
steps:
- name: Checkout
uses: actions/checkout@v5
with:
token: ${{ secrets.GH_READ_METACRAFT_PRIVATE_REPOS }}
- name: Install Nix
uses: ./.github/actions/setup-nix
with:
cachix-auth-token: ${{ secrets.CACHIX_AUTH_TOKEN }}
cachix-cache: ${{ vars.CACHIX_CACHE }}
trusted-public-keys: ${{ vars.TRUSTED_PUBLIC_KEYS }}
substituters: ${{ vars.SUBSTITUTERS }}
gh-token: ${{ secrets.GH_READ_METACRAFT_PRIVATE_REPOS }}
- name: Run Reprobuild macOS smoke
run: nix develop . --command just test-reprobuild-macos-smoke
push-gpg-public-key:
runs-on: [self-hosted, nixos]
steps:
- name: Checkout
uses: actions/checkout@v5
with:
token: ${{ secrets.GH_READ_METACRAFT_PRIVATE_REPOS }}
- name: "Import GPG key for signing commits"
id: import-gpg
uses: crazy-max/ghaction-import-gpg@v6
with:
gpg_private_key: ${{ secrets.CODETRACER_AUR_GPG_PRIVATE_KEY }}
passphrase: ${{ secrets.CODETRACER_AUR_GPG_PRIVATE_KEY_PASS }}
git_config_global: true
git_user_signingkey: true
git_commit_gpgsign: true
- name: "Upload public key"
env:
AWS_ACCESS_KEY_ID: ${{ secrets.R2_CODETRACER_BUCKET_ACCESS_KEY_ID }}
AWS_SECRET_ACCESS_KEY: ${{ secrets.R2_CODETRACER_BUCKET_ACCESS_KEY }}
run: |
nix develop .#devShells.x86_64-linux.default --command gpg --armor --export > CodeTracer.pub.asc
nix develop .#devShells.x86_64-linux.default --command aws --endpoint-url=${{ secrets.R2_CODETRACER_BUCKET_S3_ENDPOINT }} s3 cp CodeTracer.pub.asc s3://${{ vars.R2_CODETRACER_BUCKET_NAME }}/CodeTracer.pub.asc
push-install-script:
runs-on: [self-hosted, nixos]
steps:
- name: Checkout
uses: actions/checkout@v5
with:
token: ${{ secrets.GH_READ_METACRAFT_PRIVATE_REPOS }}
- name: Upload script
env:
AWS_ACCESS_KEY_ID: ${{ secrets.R2_CODETRACER_BUCKET_ACCESS_KEY_ID }}
AWS_SECRET_ACCESS_KEY: ${{ secrets.R2_CODETRACER_BUCKET_ACCESS_KEY }}
run: |
nix develop .#devShells.x86_64-linux.default --command aws --endpoint-url=${{ secrets.R2_CODETRACER_BUCKET_S3_ENDPOINT }} s3 cp install-on-distributions.sh s3://${{ vars.R2_CODETRACER_BUCKET_NAME }}/install.sh
dev-build:
runs-on: [self-hosted, nixos]
needs:
- lint-bash
- lint-nim
- lint-nix
- lint-rust
steps:
- name: Checkout
uses: actions/checkout@v5
with:
submodules: recursive
token: ${{ secrets.GH_READ_METACRAFT_PRIVATE_REPOS }}
- name: Install Nix
uses: ./.github/actions/setup-nix
with:
cachix-auth-token: ${{ secrets.CACHIX_AUTH_TOKEN }}
cachix-cache: ${{ vars.CACHIX_CACHE }}
trusted-public-keys: ${{ vars.TRUSTED_PUBLIC_KEYS }}
substituters: ${{ vars.SUBSTITUTERS }}
gh-token: ${{ secrets.GH_READ_METACRAFT_PRIVATE_REPOS }}
- run: "nix develop .#devShells.x86_64-linux.default --command ./ci/build/dev.sh"
nix-build:
runs-on: [self-hosted, nixos]
needs:
- lint-bash
- lint-nim
- lint-nix
- lint-rust
steps:
- name: Checkout
uses: actions/checkout@v5
with:
submodules: recursive
token: ${{ secrets.GH_READ_METACRAFT_PRIVATE_REPOS }}
- name: Install Nix
uses: ./.github/actions/setup-nix
with:
cachix-auth-token: ${{ secrets.CACHIX_AUTH_TOKEN }}
cachix-cache: ${{ vars.CACHIX_CACHE }}
trusted-public-keys: ${{ vars.TRUSTED_PUBLIC_KEYS }}
substituters: ${{ vars.SUBSTITUTERS }}
gh-token: ${{ secrets.GH_READ_METACRAFT_PRIVATE_REPOS }}
- run: "nix develop .#devShells.x86_64-linux.default --command ./ci/build/nix.sh"
build-python-packages:
needs:
- lint-bash
- lint-nim
- lint-nix
- lint-rust
strategy:
fail-fast: false
matrix:
include:
- name: linux-amd64
runner: ubuntu-latest
target_os: linux
arch: amd64
plat_name: manylinux_2_17_x86_64
# - name: linux-arm64
# runner: ubuntu-22.04-arm64
# target_os: linux
# arch: arm64
# plat_name: manylinux_2_17_aarch64
- name: macos-amd64
runner: macos-15-intel
target_os: macos
arch: amd64
plat_name: macosx_10_9_x86_64
- name: macos-arm64
runner: macos-14
target_os: macos
arch: arm64
plat_name: macosx_11_0_arm64
runs-on: ${{ matrix.runner }}
steps:
- name: Check out repository
uses: actions/checkout@v5
with:
submodules: 'true'
token: ${{ secrets.GH_READ_METACRAFT_PRIVATE_REPOS }}
- name: Set up Python
uses: actions/setup-python@v6
with:
python-version: '3.11'
- name: Install Python build backend
run: python -m pip install --upgrade build
- name: Install nim
run: |
set -euo pipefail
wget https://nim-lang.org/download/nim-2.2.6.tar.xz
tar xf nim-2.2.6.tar.xz
pushd nim-2.2.6
sh build.sh
bin/nim c koch
./koch boot -d:release
export PATH="$(pwd)/bin:${PATH}"
popd
- name: Get sqlite
run: |
set -euo pipefail
wget https://sqlite.org/2025/sqlite-amalgamation-3500400.zip
unzip sqlite-amalgamation-3500400.zip
cp sqlite-amalgamation-3500400/sqlite3.c .
- name: Install libssl and libbpf (Linux)
if: ${{ matrix.target_os == 'linux' }}
run: |
sudo apt-get update
sudo apt-get install -y libssl-dev libbpf-dev libelf-dev
- name: Install libssl (MacOS)
if: ${{ matrix.target_os == 'macos' }}
run: |
git clone https://github.com/openssl/openssl
pushd openssl
git checkout openssl-3.5.4
./Configure --prefix=$(pwd)/../openssl-res
make -j$(sysctl -n hw.ncpu)
make install_sw
popd
- name: Install zlib (Linux)
if: ${{ matrix.target_os == 'linux' }}
run: |
sudo apt-get update
sudo apt-get install -y zlib1g-dev
- name: Install zlib (MacOS)
if: ${{ matrix.target_os == 'macos' }}
run: |
wget https://zlib.net/zlib-1.3.2.tar.gz
tar xf zlib-1.3.2.tar.gz
pushd zlib-1.3.2
./configure --static --prefix=$(pwd)/../zlib-res
make -j$(sysctl -n hw.ncpu)
make install
popd
- name: Build codetracer binaries (Linux)
if: ${{ matrix.target_os == 'linux' }}
shell: bash
run: |
set -euo pipefail
TARGET_DIR="build-python/src/ct/bin/${{ matrix.target_os }}-${{ matrix.arch }}"
mkdir -p "${TARGET_DIR}"
./nim-2.2.6/bin/nim -d:release \
--d:asyncBackend=asyncdispatch \
--dynlibOverride:std -d:staticStd \
--mm:refc --hints:on --warnings:off \
--boundChecks:on \
-d:useOpenssl3 \
-d:ssl \
-d:chronicles_sinks=json -d:chronicles_line_numbers=true \
-d:chronicles_timestamps=UnixTime \
-d:ctTest -d:testing --hint"[XDeclaredButNotUsed]":off \
-d:builtWithNix \
-d:ctEntrypoint \
-d:pythonPackage \
-d:libcPath=libc \
-d:pathToNodeModules=../node_modules \
--nimcache:nimcache \
-d:staticSqlite \
-d:useLibzipSrc \
--passL:"-Wl,-Bstatic -L/usr/lib/x86_64-linux-gnu -l:libz.a -Wl,-Bdynamic" \
--dynlibOverride:ssl --dynlibOverride:crypto \
--passL:"-Wl,-Bstatic -L/usr/lib/x86_64-linux-gnu -l:libssl.a -l:libcrypto.a -Wl,-Bdynamic" \
--out:"${TARGET_DIR}/ct" c ./src/ct/codetracer.nim
./nim-2.2.6/bin/nim \
-d:release -d:asyncBackend=asyncdispatch \
--mm:refc --hints:off --warnings:off \
--debugInfo --lineDir:on \
--boundChecks:on --stacktrace:on --linetrace:on \
-d:chronicles_sinks=json -d:chronicles_line_numbers=true \
-d:chronicles_timestamps=UnixTime \
-d:ssl \
-d:ctTest -d:testing --hint"[XDeclaredButNotUsed]":off \
-d:libcPath=libc \
-d:builtWithNix \
-d:ctEntrypoint \
-d:pythonPackage \
--nimcache:nimcache \
-d:staticSqlite \
-d:useLibzipSrc \
--passL:"-Wl,-Bstatic -L/usr/lib/x86_64-linux-gnu -l:libz.a -Wl,-Bdynamic" \
--dynlibOverride:ssl --dynlibOverride:crypto \
--passL:"-Wl,-Bstatic -L/usr/lib/x86_64-linux-gnu -l:libssl.a -l:libcrypto.a -Wl,-Bdynamic" \
--out:"${TARGET_DIR}/db-backend-record" c ./src/ct/db_backend_record.nim
./build-python/scripts/download_ct_remote.sh \
"${{ matrix.target_os }}" \
"${{ matrix.arch }}" \
"${TARGET_DIR}"
- name: Build codetracer binaries (MacOS)
if: ${{ matrix.target_os == 'macos' }}
run: |
set -euo pipefail
TARGET_DIR="build-python/src/ct/bin/${{ matrix.target_os }}-${{ matrix.arch }}"
mkdir -p "${TARGET_DIR}"
./nim-2.2.6/bin/nim -d:release \
--d:asyncBackend=asyncdispatch \
--dynlibOverride:std -d:staticStd \
--mm:refc --hints:on --warnings:off \
--boundChecks:on \
-d:useOpenssl3 \
-d:ssl \
-d:chronicles_sinks=json -d:chronicles_line_numbers=true \
-d:chronicles_timestamps=UnixTime \
-d:ctTest -d:testing --hint"[XDeclaredButNotUsed]":off \
-d:builtWithNix \
-d:ctEntrypoint \
-d:pythonPackage \
-d:libcPath=libc \
-d:pathToNodeModules=../node_modules \
--nimcache:nimcache \
-d:staticSqlite \
-d:useLibzipSrc \
--passL:"$(pwd)/zlib-res/lib/libz.a" \
--dynlibOverride:ssl --dynlibOverride:crypto \
--passL:"$(pwd)/openssl-res/lib/libssl.a $(pwd)/openssl-res/lib/libcrypto.a" \
--out:"${TARGET_DIR}/ct" c ./src/ct/codetracer.nim
./nim-2.2.6/bin/nim \
-d:release -d:asyncBackend=asyncdispatch \
--mm:refc --hints:off --warnings:off \
--debugInfo --lineDir:on \
--boundChecks:on --stacktrace:on --linetrace:on \
-d:chronicles_sinks=json -d:chronicles_line_numbers=true \
-d:chronicles_timestamps=UnixTime \
-d:ssl \
-d:ctTest -d:testing --hint"[XDeclaredButNotUsed]":off \
-d:libcPath=libc \
-d:builtWithNix \
-d:ctEntrypoint \
-d:pythonPackage \
--nimcache:nimcache \
-d:staticSqlite \
-d:useLibzipSrc \
--passL:"$(pwd)/zlib-res/lib/libz.a" \
--dynlibOverride:ssl --dynlibOverride:crypto \
--passL:"$(pwd)/openssl-res/lib/libssl.a $(pwd)/openssl-res/lib/libcrypto.a" \
--out:"${TARGET_DIR}/db-backend-record" c ./src/ct/db_backend_record.nim
./build-python/scripts/download_ct_remote.sh \
"${{ matrix.target_os }}" \
"${{ matrix.arch }}" \
"${TARGET_DIR}"
- name: Build wheel
run: |
set -euo pipefail
pushd build-python
python -m build --wheel -C--build-option=--plat-name=${{ matrix.plat_name }}
popd
- name: Upload distributions
uses: actions/upload-artifact@v5
with:
name: python-dist-${{ matrix.name }}
path: build-python/dist/*.whl
if-no-files-found: error
appimage-build:
runs-on: [self-hosted, nixos]
needs:
- lint-bash
- lint-nim
- lint-nix
- lint-rust
steps:
- name: Checkout
uses: actions/checkout@v5
with:
submodules: recursive
token: ${{ secrets.GH_READ_METACRAFT_PRIVATE_REPOS }}
- name: Install Nix
uses: ./.github/actions/setup-nix
with:
cachix-auth-token: ${{ secrets.CACHIX_AUTH_TOKEN }}
cachix-cache: ${{ vars.CACHIX_CACHE }}
trusted-public-keys: ${{ vars.TRUSTED_PUBLIC_KEYS }}
substituters: ${{ vars.SUBSTITUTERS }}
gh-token: ${{ secrets.GH_READ_METACRAFT_PRIVATE_REPOS }}
- name: "Import GPG key for signing commits"
id: import-gpg
uses: crazy-max/ghaction-import-gpg@v6
with:
gpg_private_key: ${{ secrets.CODETRACER_AUR_GPG_PRIVATE_KEY }}
passphrase: ${{ secrets.CODETRACER_AUR_GPG_PRIVATE_KEY_PASS }}
git_config_global: true
git_user_signingkey: true
git_commit_gpgsign: true
- name: Build
run: "nix develop .#devShells.x86_64-linux.default --command ./ci/build/appimage.sh"
- name: Upload artifact
env:
AWS_ACCESS_KEY_ID: ${{ secrets.R2_CODETRACER_BUCKET_ACCESS_KEY_ID }}
AWS_SECRET_ACCESS_KEY: ${{ secrets.R2_CODETRACER_BUCKET_ACCESS_KEY }}
run: |
nix develop .#devShells.x86_64-linux.default --command gpg --armor --detach-sign CodeTracer.AppImage
nix develop .#devShells.x86_64-linux.default --command aws --endpoint-url=${{ secrets.R2_CODETRACER_BUCKET_S3_ENDPOINT }} s3 cp CodeTracer.AppImage s3://${{ vars.R2_CODETRACER_BUCKET_NAME }}/CodeTracer-${{ github.ref_name }}-amd64.AppImage
nix develop .#devShells.x86_64-linux.default --command aws --endpoint-url=${{ secrets.R2_CODETRACER_BUCKET_S3_ENDPOINT }} s3 cp CodeTracer.AppImage.asc s3://${{ vars.R2_CODETRACER_BUCKET_NAME }}/CodeTracer-${{ github.ref_name }}-amd64.AppImage.asc
dmg-build:
runs-on: macos-latest
needs:
- lint-bash
- lint-nim
- lint-nix
- lint-rust
steps:
- name: Checkout
uses: actions/checkout@v5
with:
submodules: recursive
token: ${{ secrets.GH_READ_METACRAFT_PRIVATE_REPOS }}
- name: "Import GPG key for signing commits"
id: import-gpg
uses: crazy-max/ghaction-import-gpg@v6
with:
gpg_private_key: ${{ secrets.CODETRACER_AUR_GPG_PRIVATE_KEY }}
passphrase: ${{ secrets.CODETRACER_AUR_GPG_PRIVATE_KEY_PASS }}
git_config_global: true
git_user_signingkey: true
git_commit_gpgsign: true
- name: Set up Rust toolchain
uses: dtolnay/rust-toolchain@stable
- name: Build
run: ./ci/build/dmg.sh
- name: Install AWS CLI
run: brew install awscli
- name: Upload artifact
env:
AWS_ACCESS_KEY_ID: ${{ secrets.R2_CODETRACER_BUCKET_ACCESS_KEY_ID }}
AWS_SECRET_ACCESS_KEY: ${{ secrets.R2_CODETRACER_BUCKET_ACCESS_KEY }}
run: |
gpg --armor --detach-sign non-nix-build/CodeTracer.dmg
# for now apply workaround from https://community.cloudflare.com/t/an-error-occurred-internalerror-when-calling-the-putobject-operation/764905/11:
# adding `--checksum-algorithm CRC32`
aws --endpoint-url=${{ secrets.R2_CODETRACER_BUCKET_S3_ENDPOINT }} s3 cp ./non-nix-build/CodeTracer.dmg s3://${{ vars.R2_CODETRACER_BUCKET_NAME }}/CodeTracer-${{ github.ref_name }}-arm64.dmg --checksum-algorithm CRC32
aws --endpoint-url=${{ secrets.R2_CODETRACER_BUCKET_S3_ENDPOINT }} s3 cp ./non-nix-build/CodeTracer.dmg.asc s3://${{ vars.R2_CODETRACER_BUCKET_NAME }}/CodeTracer-${{ github.ref_name }}-arm64.dmg.asc --checksum-algorithm CRC32
dmg-lib-check:
runs-on: macos-latest
needs:
- dmg-build
steps:
- name: Install AWS CLI
run: brew install awscli
- name: Install 7zip
run: brew install sevenzip
- name: Download artifact
env:
AWS_ACCESS_KEY_ID: ${{ secrets.R2_CODETRACER_BUCKET_ACCESS_KEY_ID }}
AWS_SECRET_ACCESS_KEY: ${{ secrets.R2_CODETRACER_BUCKET_ACCESS_KEY }}
run: |
aws --endpoint-url=${{ secrets.R2_CODETRACER_BUCKET_S3_ENDPOINT }} s3 cp s3://${{ vars.R2_CODETRACER_BUCKET_NAME }}/CodeTracer-${{ github.ref_name }}-arm64.dmg ./CodeTracer.dmg
- name: Extract dmg
env:
AWS_ACCESS_KEY_ID: ${{ secrets.R2_CODETRACER_BUCKET_ACCESS_KEY_ID }}
AWS_SECRET_ACCESS_KEY: ${{ secrets.R2_CODETRACER_BUCKET_ACCESS_KEY }}
run: |
7zz x ./CodeTracer.dmg
- name: Check if ct starts
env:
AWS_ACCESS_KEY_ID: ${{ secrets.R2_CODETRACER_BUCKET_ACCESS_KEY_ID }}
AWS_SECRET_ACCESS_KEY: ${{ secrets.R2_CODETRACER_BUCKET_ACCESS_KEY }}
run: |
./CodeTracer/CodeTracer.app/Contents/MacOS/bin/ct --version
appimage-lib-check:
runs-on: ubuntu-latest
needs:
- appimage-build
steps:
- name: Install AWS CLI
if: ${{ startsWith(github.ref, 'refs/tags/') && !github.event['codetracer-ci'] }}
run: sudo snap install aws-cli --classic
- name: Install FUSE
run: sudo apt-get install -y fuse libfuse2
- name: Download artifact
env:
AWS_ACCESS_KEY_ID: ${{ secrets.R2_CODETRACER_BUCKET_ACCESS_KEY_ID }}
AWS_SECRET_ACCESS_KEY: ${{ secrets.R2_CODETRACER_BUCKET_ACCESS_KEY }}
run: |
aws --endpoint-url=${{ secrets.R2_CODETRACER_BUCKET_S3_ENDPOINT }} s3 cp s3://${{ vars.R2_CODETRACER_BUCKET_NAME }}/CodeTracer-${{ github.ref_name }}-amd64.AppImage ./CodeTracer.AppImage
- name: Check if ct starts
env:
AWS_ACCESS_KEY_ID: ${{ secrets.R2_CODETRACER_BUCKET_ACCESS_KEY_ID }}
AWS_SECRET_ACCESS_KEY: ${{ secrets.R2_CODETRACER_BUCKET_ACCESS_KEY }}
run: |
chmod +x ./CodeTracer.AppImage
./CodeTracer.AppImage --version
test-non-gui:
strategy:
fail-fast: false
matrix:
include:
- platform: nixos
runner: [self-hosted, nixos]
- platform: macos
runner: macos-latest
runs-on: ${{ matrix.runner }}
# macOS tests are new and may have pre-existing failures; don't block PRs
continue-on-error: ${{ matrix.platform == 'macos' }}
needs:
- lint-bash
- lint-nim
- lint-nix
- lint-rust
steps:
- name: Checkout
uses: actions/checkout@v5
with:
submodules: recursive
token: ${{ secrets.GH_READ_METACRAFT_PRIVATE_REPOS }}
# --- NixOS setup ---
- name: Install Nix
if: matrix.platform == 'nixos'
uses: ./.github/actions/setup-nix
with:
cachix-auth-token: ${{ secrets.CACHIX_AUTH_TOKEN }}
cachix-cache: ${{ vars.CACHIX_CACHE }}
trusted-public-keys: ${{ vars.TRUSTED_PUBLIC_KEYS }}
substituters: ${{ vars.SUBSTITUTERS }}
gh-token: ${{ secrets.GH_READ_METACRAFT_PRIVATE_REPOS }}
# --- macOS setup ---
- name: Install just (macOS)
if: matrix.platform == 'macos'
run: brew install just
- name: Set up Python 3.12 (macOS)
if: matrix.platform == 'macos'
uses: actions/setup-python@v5
with:
python-version: '3.12'
- name: Set up Rust toolchain (macOS)
if: matrix.platform == 'macos'
uses: dtolnay/rust-toolchain@stable
- name: Install cargo-nextest (macOS)
if: matrix.platform == 'macos'
run: curl -LsSf https://get.nexte.st/latest/mac | tar zxf - -C ${CARGO_HOME:-~/.cargo}/bin
- name: Build (non-nix)
if: matrix.platform == 'macos'
run: ./non-nix-build/build.sh
- name: Clone python-recorder (macOS)
if: matrix.platform == 'macos'
uses: metacraft-labs/metacraft-github-actions/clone-repo@main
with:
repo: metacraft-labs/codetracer-python-recorder
ref: main
path: ${{ github.workspace }}/../codetracer-python-recorder
gh-token: ${{ secrets.GH_READ_METACRAFT_PRIVATE_REPOS }}
- name: Clone ruby-recorder (macOS)
if: matrix.platform == 'macos'
uses: metacraft-labs/metacraft-github-actions/clone-repo@main
with:
repo: metacraft-labs/codetracer-ruby-recorder
ref: main
path: ${{ github.workspace }}/../codetracer-ruby-recorder
gh-token: ${{ secrets.GH_READ_METACRAFT_PRIVATE_REPOS }}
# Runs all Rust tests including flow integration tests for all languages.
# WASM flow tests skip automatically if wazero or wasm32-wasip1 target
# are not available. Stylus flow tests are #[ignore] and need a devnode.
# Cross-repo tests (rr) run in the separate test-ui-tests-rr job.
- name: Run tests
run: ./ci/test/non-gui.sh
env:
CODETRACER_CI_PLATFORM: ${{ matrix.platform }}
test-ui-tests:
strategy:
fail-fast: false
matrix:
include:
- platform: nixos
runner: [self-hosted, nixos]
- platform: macos
runner: macos-latest
runs-on: ${{ matrix.runner }}
# macOS tests are new and may have pre-existing failures; don't block PRs
continue-on-error: ${{ matrix.platform == 'macos' }}
steps:
- name: Checkout
uses: actions/checkout@v5
with:
submodules: recursive
token: ${{ secrets.GH_READ_METACRAFT_PRIVATE_REPOS }}
# --- NixOS setup ---
- name: Install Nix
if: matrix.platform == 'nixos'
uses: ./.github/actions/setup-nix
with:
cachix-auth-token: ${{ secrets.CACHIX_AUTH_TOKEN }}
cachix-cache: ${{ vars.CACHIX_CACHE }}
trusted-public-keys: ${{ vars.TRUSTED_PUBLIC_KEYS }}
substituters: ${{ vars.SUBSTITUTERS }}
gh-token: ${{ secrets.GH_READ_METACRAFT_PRIVATE_REPOS }}
- name: Build CodeTracer (nix)
if: matrix.platform == 'nixos'
run: nix build --print-build-logs '.?submodules=1#codetracer' --override-input codetracer-trace-format path:./libs/codetracer-trace-format
# --- macOS setup ---
- name: Install just (macOS)
if: matrix.platform == 'macos'
run: brew install just
- name: Set up Python 3.12 (macOS)
if: matrix.platform == 'macos'
uses: actions/setup-python@v5
with:
python-version: '3.12'
- name: Set up Rust toolchain (macOS)
if: matrix.platform == 'macos'
uses: dtolnay/rust-toolchain@stable
- name: Build CodeTracer (non-nix)
if: matrix.platform == 'macos'
run: ./non-nix-build/build.sh
- name: Clone python-recorder (macOS)
if: matrix.platform == 'macos'
uses: metacraft-labs/metacraft-github-actions/clone-repo@main
with:
repo: metacraft-labs/codetracer-python-recorder
ref: main
path: ${{ github.workspace }}/../codetracer-python-recorder
gh-token: ${{ secrets.GH_READ_METACRAFT_PRIVATE_REPOS }}
- name: Clone ruby-recorder (macOS)
if: matrix.platform == 'macos'
uses: metacraft-labs/metacraft-github-actions/clone-repo@main
with:
repo: metacraft-labs/codetracer-ruby-recorder
ref: main
path: ${{ github.workspace }}/../codetracer-ruby-recorder
gh-token: ${{ secrets.GH_READ_METACRAFT_PRIVATE_REPOS }}
- name: Run TypeScript Playwright UI tests (DB-based only)
run: ./ci/test/ui-tests-db.sh
env:
CODETRACER_CI_PLATFORM: ${{ matrix.platform }}
CODETRACER_DB_TESTS_ONLY: "1"
test-ui-tests-rr:
runs-on: [self-hosted, nixos]
timeout-minutes: 120
steps:
- name: Checkout
uses: actions/checkout@v5
with:
submodules: recursive
token: ${{ secrets.GH_READ_METACRAFT_PRIVATE_REPOS }}
- name: Install Nix
uses: ./.github/actions/setup-nix
with:
cachix-auth-token: ${{ secrets.CACHIX_AUTH_TOKEN }}
cachix-cache: ${{ vars.CACHIX_CACHE }}
trusted-public-keys: ${{ vars.TRUSTED_PUBLIC_KEYS }}
substituters: ${{ vars.SUBSTITUTERS }}
gh-token: ${{ secrets.GH_READ_METACRAFT_PRIVATE_REPOS }}
- name: Build CodeTracer
run: nix build --print-build-logs '.?submodules=1#codetracer' --override-input codetracer-trace-format path:./libs/codetracer-trace-format
- name: Setup rr-backend
env:
GH_TOKEN: ${{ secrets.GH_READ_METACRAFT_PRIVATE_REPOS }}
run: ./ci/setup-rr-backend.sh
- name: Run TypeScript Playwright UI tests (RR-based only)
env:
CODETRACER_E2E_CT_PATH: ${{ github.workspace }}/result/bin/ct
CODETRACER_RR_BACKEND_PATH: ${{ github.workspace }}/../codetracer-native-backend
CODETRACER_RR_BACKEND_PRESENT: "1"
CODETRACER_RR_TESTS_ONLY: "1"
PLAYWRIGHT_GLOBAL_TIMEOUT: "10800000"
run: "nix develop .#devShells.x86_64-linux.default --command just test-gui"
- name: Upload test artifacts
if: failure()
uses: actions/upload-artifact@v5
with:
name: ui-tests-rr-artifacts
path: |
tsc-ui-tests/test-results/
tsc-ui-tests/playwright-report/
retention-days: 14
if-no-files-found: ignore
visual-replay-regression-gate:
runs-on: [self-hosted, nixos]
timeout-minutes: 180
steps:
- name: Checkout CodeTracer
uses: actions/checkout@v5
with:
submodules: recursive
token: ${{ secrets.GH_READ_METACRAFT_PRIVATE_REPOS }}
- name: Install Nix
uses: ./.github/actions/setup-nix
with:
cachix-auth-token: ${{ secrets.CACHIX_AUTH_TOKEN }}
cachix-cache: ${{ vars.CACHIX_CACHE }}
trusted-public-keys: ${{ vars.TRUSTED_PUBLIC_KEYS }}
substituters: ${{ vars.SUBSTITUTERS }}
gh-token: ${{ secrets.GH_READ_METACRAFT_PRIVATE_REPOS }}
- name: Resolve codetracer-visual-replay ref
id: visual-replay-ref
shell: bash
run: |
set -euo pipefail
PINS=".github/sibling-pins"
if [[ ! -f "$PINS" ]]; then
echo "Missing $PINS" >&2
exit 1
fi
REF="$(awk '$1 == "codetracer-visual-replay" { print $2; exit }' "$PINS")"
if [[ -z "$REF" ]]; then
echo "Missing codetracer-visual-replay pin in $PINS" >&2
exit 1
fi
echo "ref=$REF" >> "$GITHUB_OUTPUT"
echo "Resolved codetracer-visual-replay ref: $REF"
- name: Clone codetracer-visual-replay
uses: metacraft-labs/metacraft-github-actions/clone-repo@main
with:
repo: metacraft-labs/codetracer-visual-replay
ref: ${{ steps.visual-replay-ref.outputs.ref }}
path: ${{ github.workspace }}/../codetracer-visual-replay
gh-token: ${{ secrets.GH_READ_METACRAFT_PRIVATE_REPOS }}
- name: Restore codetracer-visual-replay sibling pins
shell: bash
env:
TOKEN: ${{ secrets.GH_READ_METACRAFT_PRIVATE_REPOS }}
run: |
set -euo pipefail
PINS="${{ github.workspace }}/../codetracer-visual-replay/.github/sibling-pins"
if [[ ! -f "$PINS" ]]; then
echo "Missing visual replay sibling pins: $PINS" >&2
exit 1
fi
for required in \
codetracer-native-backend \
codetracer-native-recorder \
codetracer-native-test-programs \
codetracer-visual-replay-fixtures; do
if ! awk -v repo="$required" '$1 == repo { found = 1 } END { exit found ? 0 : 1 }' "$PINS"; then
echo "Missing required visual replay sibling pin: $required" >&2
exit 1
fi
done
while IFS=' ' read -r name sha branch; do
[[ -z "$name" ]] && continue
dest="${{ github.workspace }}/../${name}"
echo "Restoring ${name}@${sha}"
rm -rf "$dest"
git clone --no-checkout --filter=blob:none \
"https://x-access-token:${TOKEN}@github.com/metacraft-labs/${name}.git" \
"$dest"
git -C "$dest" fetch --depth 1 origin "$sha"
git -C "$dest" checkout --detach "$sha"
echo "${name}: $(git -C "$dest" rev-parse HEAD)"
if [[ "$(git -C "$dest" rev-parse HEAD)" != "$sha" ]]; then
echo "${name} did not restore to pinned SHA ${sha}" >&2
exit 1
fi
done < "$PINS"
- name: Run visual replay regression gate
env:
CODETRACER_VISUAL_REPLAY_REPO_PATH: ${{ github.workspace }}/../codetracer-visual-replay
PLAYWRIGHT_GLOBAL_TIMEOUT: "10800000"
run: |
nix develop .#devShells.x86_64-linux.default --command just test-visual-replay-gate
- name: Upload visual replay artifacts
if: failure()
uses: actions/upload-artifact@v5
with:
name: visual-replay-regression-artifacts
path: |
src/tests/gui/test-results/
src/tests/gui/playwright-report/
src/tests/gui/test-stats/
storybook/storybook-static/
storybook/dist/
../codetracer-visual-replay/tests/output/
../codetracer-visual-replay/bench-results/
/tmp/*_diff.rgba
/tmp/*_sw.rgba
/tmp/*_hw.rgba
retention-days: 14
if-no-files-found: ignore
publish-pypi:
needs:
- build-python-packages
- test-non-gui
- test-ui-tests
- create-release
if: startsWith(github.ref, 'refs/tags/')
runs-on: ubuntu-latest
steps:
- name: Download built distributions
uses: actions/download-artifact@v6
with:
path: dist
merge-multiple: true
- name: Publish to TestPyPI
uses: pypa/gh-action-pypi-publish@release/v1
with:
packages_dir: dist
repository-url: https://test.pypi.org/legacy/
- name: Publish to PyPI
uses: pypa/gh-action-pypi-publish@release/v1
with:
packages_dir: dist
push-to-cachix:
runs-on: [self-hosted, nixos]
needs:
- test-non-gui
- test-ui-tests
- appimage-lib-check
- dmg-lib-check
if: "github.ref == 'refs/heads/main' && ${{ !github.event.codetracer-ci }}"

Check warning on line 1339 in .github/workflows/codetracer.yml

View workflow run for this annotation

GitHub Actions / Codetracer CI

Workflow syntax warning

.github/workflows/codetracer.yml (Line: 1339, Col: 9): Conditional expression contains literal text outside replacement tokens. This will cause the expression to always evaluate to truthy. Did you mean to put the entire expression inside ${{ }}?
steps:
- name: Checkout
uses: actions/checkout@v5
with:
submodules: recursive
token: ${{ secrets.GH_READ_METACRAFT_PRIVATE_REPOS }}
- name: Install Nix
uses: ./.github/actions/setup-nix
with:
cachix-auth-token: ${{ secrets.CACHIX_AUTH_TOKEN }}
cachix-cache: ${{ vars.CACHIX_CACHE }}
trusted-public-keys: ${{ vars.TRUSTED_PUBLIC_KEYS }}
substituters: ${{ vars.SUBSTITUTERS }}
gh-token: ${{ secrets.GH_READ_METACRAFT_PRIVATE_REPOS }}
- run: "nix develop .#devShells.x86_64-linux.default --command ./ci/deploy/build-nix-and-push-to-cachix.sh"
build-and-deploy-docs:
runs-on: [self-hosted, nixos]
needs: [push-to-cachix]
if: ${{ github.ref == 'refs/heads/main' && !github.event['codetracer-ci'] }}
permissions:
contents: "write"
steps:
- name: Checkout
uses: actions/checkout@v5
with:
submodules: recursive
token: ${{ secrets.GH_READ_METACRAFT_PRIVATE_REPOS }}
- name: Install Nix
uses: ./.github/actions/setup-nix
with:
cachix-auth-token: ${{ secrets.CACHIX_AUTH_TOKEN }}
cachix-cache: ${{ vars.CACHIX_CACHE }}
trusted-public-keys: ${{ vars.TRUSTED_PUBLIC_KEYS }}
substituters: ${{ vars.SUBSTITUTERS }}
gh-token: ${{ secrets.GH_READ_METACRAFT_PRIVATE_REPOS }}
- run: |
git config user.name "github-actions[bot]"
git config user.email "41898282+github-actions[bot]@users.noreply.github.com"
git config init.defaultBranch main
git remote set-url origin https://x-access-token:${{ secrets.CODETRACER_PUSH_GITHUB_TOKEN }}@github.com/metacraft-labs/codetracer
nix develop .#devShells.x86_64-linux.default --command ./ci/deploy/docs.sh
push-tag:
runs-on: [ self-hosted, nixos ]
needs: [ dev-build, nix-build, appimage-build, dmg-build ]
permissions:
contents: "write"
outputs:
tag: ${{ steps.tag.outputs.tag }}
steps:
- name: Checkout
uses: actions/checkout@v5
with:
submodules: recursive
token: ${{ secrets.GH_READ_METACRAFT_PRIVATE_REPOS }}
- name: Install Nix
uses: metacraft-labs/nixos-modules/.github/install-nix@main
with:
cachix-auth-token: ${{ secrets.CACHIX_AUTH_TOKEN }}
cachix-cache: ${{ vars.CACHIX_CACHE }}
trusted-public-keys: ${{ vars.TRUSTED_PUBLIC_KEYS }}
substituters: ${{ vars.SUBSTITUTERS }}
- name: Configure Nix for private repos
run: |
mkdir -p ~/.config/nix
echo "access-tokens = github.com=${{ secrets.GH_READ_METACRAFT_PRIVATE_REPOS }}" >> ~/.config/nix/nix.conf
git config --global url."https://x-access-token:${{ secrets.GH_READ_METACRAFT_PRIVATE_REPOS }}@github.com/".insteadOf "git@github.com:"
git config --global url."https://x-access-token:${{ secrets.GH_READ_METACRAFT_PRIVATE_REPOS }}@github.com/".insteadOf "ssh://git@github.com/"
git config --global url."https://x-access-token:${{ secrets.GH_READ_METACRAFT_PRIVATE_REPOS }}@github.com/".insteadOf "https://github.com/"
- name: Create tag
if: ${{ github.ref == 'refs/heads/main' }}
id: tag
run: |
YEAR=$(bash -c 'grep "CodeTracerYear\*" src/ct/version.nim | sed "s/.*CodeTracerYear\* = //g"')
MONTH=$(bash -c "printf '%02d' \$(grep \"CodeTracerMonth\*\" src/ct/version.nim | sed \"s/.*CodeTracerMonth\* = //g\")")
BUILD=$(bash -c 'grep "CodeTracerBuild\*" src/ct/version.nim | sed "s/.*CodeTracerBuild\* = //g"')
git config user.name "github-actions[bot]"
git config user.email "41898282+github-actions[bot]@users.noreply.github.com"
git config init.defaultBranch main
git remote set-url origin https://x-access-token:${{ secrets.CODETRACER_PUSH_GITHUB_TOKEN }}@github.com/metacraft-labs/codetracer
git tag -a "$YEAR.$MONTH.$BUILD" -m "Release $YEAR.$MONTH.$BUILD" || echo "Tag already exists"
(git push origin "$YEAR.$MONTH.$BUILD" && echo "tag=$YEAR.$MONTH.$BUILD" >> $GITHUB_OUTPUT) || echo "Tag already exists"
create-release:
runs-on: [ self-hosted, nixos ]
needs: [ push-tag ]
if: ${{ ((startsWith(github.ref, 'refs/tags/') && !contains(github.ref_name, '-')) || needs.push-tag.outputs.tag != '') && !github.event['codetracer-ci'] }}
permissions:
contents: "write"
steps:
- name: Checkout
uses: actions/checkout@v5
with:
token: ${{ secrets.GH_READ_METACRAFT_PRIVATE_REPOS }}
- name: Install Nix
uses: metacraft-labs/nixos-modules/.github/install-nix@main
with:
cachix-auth-token: ${{ secrets.CACHIX_AUTH_TOKEN }}
cachix-cache: ${{ vars.CACHIX_CACHE }}
trusted-public-keys: ${{ vars.TRUSTED_PUBLIC_KEYS }}
substituters: ${{ vars.SUBSTITUTERS }}
- name: Configure Nix for private repos
run: |
mkdir -p ~/.config/nix
echo "access-tokens = github.com=${{ secrets.GH_READ_METACRAFT_PRIVATE_REPOS }}" >> ~/.config/nix/nix.conf
git config --global url."https://x-access-token:${{ secrets.GH_READ_METACRAFT_PRIVATE_REPOS }}@github.com/".insteadOf "git@github.com:"
git config --global url."https://x-access-token:${{ secrets.GH_READ_METACRAFT_PRIVATE_REPOS }}@github.com/".insteadOf "ssh://git@github.com/"
git config --global url."https://x-access-token:${{ secrets.GH_READ_METACRAFT_PRIVATE_REPOS }}@github.com/".insteadOf "https://github.com/"
- name: "Import GPG key for signing commits"
id: import-gpg
uses: crazy-max/ghaction-import-gpg@v6
with:
gpg_private_key: ${{ secrets.CODETRACER_AUR_GPG_PRIVATE_KEY }}
passphrase: ${{ secrets.CODETRACER_AUR_GPG_PRIVATE_KEY_PASS }}
git_config_global: true
git_user_signingkey: true
git_commit_gpgsign: true
- name: Create resource tarball
run: |
nix develop .#devShells.x86_64-linux.default --command bash -c "tar cfJ resources.tar.xz resources/"
nix develop .#devShells.x86_64-linux.default --command bash -c "gpg --detach-sign resources.tar.xz"
- name: Upload latest
env:
AWS_ACCESS_KEY_ID: ${{ secrets.R2_CODETRACER_BUCKET_ACCESS_KEY_ID }}
AWS_SECRET_ACCESS_KEY: ${{ secrets.R2_CODETRACER_BUCKET_ACCESS_KEY }}
run: |
nix develop .#devShells.x86_64-linux.default --command wget "https://downloads.codetracer.com/CodeTracer-main-arm64.dmg"
nix develop .#devShells.x86_64-linux.default --command wget "https://downloads.codetracer.com/CodeTracer-main-arm64.dmg.asc"
nix develop .#devShells.x86_64-linux.default --command wget "https://downloads.codetracer.com/CodeTracer-main-amd64.AppImage"
nix develop .#devShells.x86_64-linux.default --command wget "https://downloads.codetracer.com/CodeTracer-main-amd64.AppImage.asc"
nix develop .#devShells.x86_64-linux.default --command aws --endpoint-url=${{ secrets.R2_CODETRACER_BUCKET_S3_ENDPOINT }} s3 cp CodeTracer-main-arm64.dmg s3://${{ vars.R2_CODETRACER_BUCKET_NAME }}/CodeTracer-${{ needs.push-tag.outputs.tag }}-arm64.dmg --checksum-algorithm CRC32
nix develop .#devShells.x86_64-linux.default --command aws --endpoint-url=${{ secrets.R2_CODETRACER_BUCKET_S3_ENDPOINT }} s3 cp CodeTracer-main-arm64.dmg.asc s3://${{ vars.R2_CODETRACER_BUCKET_NAME }}/CodeTracer-${{ needs.push-tag.outputs.tag }}-arm64.dmg.asc --checksum-algorithm CRC32
nix develop .#devShells.x86_64-linux.default --command aws --endpoint-url=${{ secrets.R2_CODETRACER_BUCKET_S3_ENDPOINT }} s3 cp CodeTracer-main-amd64.AppImage s3://${{ vars.R2_CODETRACER_BUCKET_NAME }}/CodeTracer-${{ needs.push-tag.outputs.tag }}-amd64.AppImage --checksum-algorithm CRC32
nix develop .#devShells.x86_64-linux.default --command aws --endpoint-url=${{ secrets.R2_CODETRACER_BUCKET_S3_ENDPOINT }} s3 cp CodeTracer-main-amd64.AppImage.asc s3://${{ vars.R2_CODETRACER_BUCKET_NAME }}/CodeTracer-${{ needs.push-tag.outputs.tag }}-amd64.AppImage.asc --checksum-algorithm CRC32
nix develop .#devShells.x86_64-linux.default --command aws --endpoint-url=${{ secrets.R2_CODETRACER_BUCKET_S3_ENDPOINT }} s3 cp CodeTracer-main-arm64.dmg s3://${{ vars.R2_CODETRACER_BUCKET_NAME }}/CodeTracer-latest-arm64.dmg --checksum-algorithm CRC32
nix develop .#devShells.x86_64-linux.default --command aws --endpoint-url=${{ secrets.R2_CODETRACER_BUCKET_S3_ENDPOINT }} s3 cp CodeTracer-main-arm64.dmg.asc s3://${{ vars.R2_CODETRACER_BUCKET_NAME }}/CodeTracer-latest-arm64.dmg.asc --checksum-algorithm CRC32
nix develop .#devShells.x86_64-linux.default --command aws --endpoint-url=${{ secrets.R2_CODETRACER_BUCKET_S3_ENDPOINT }} s3 cp CodeTracer-main-amd64.AppImage s3://${{ vars.R2_CODETRACER_BUCKET_NAME }}/CodeTracer-latest-amd64.AppImage --checksum-algorithm CRC32
nix develop .#devShells.x86_64-linux.default --command aws --endpoint-url=${{ secrets.R2_CODETRACER_BUCKET_S3_ENDPOINT }} s3 cp CodeTracer-main-amd64.AppImage.asc s3://${{ vars.R2_CODETRACER_BUCKET_NAME }}/CodeTracer-latest-amd64.AppImage.asc --checksum-algorithm CRC32
- name: Get changelog text
id: changelog
run: |
nix develop .#devShells.x86_64-linux.default --command bash -c "awk '/^## /{if (p) exit; p=1} p' CHANGELOG.md > release_changelog.md"
echo "\
We're actively working on multiple exciting features, which are not fully released yet. Stay tuned!
Available downloads:
<a href="https://downloads.codetracer.com/CodeTracer-${{ needs.push-tag.outputs.tag }}-arm64.dmg"><img width="75px" height="100px" src="https://upload.wikimedia.org/wikipedia/commons/1/1b/Apple_logo_grey.svg"></a>
<a href="https://deb.codetracer.com/"><img width="100px" height="100px" src="https://upload.wikimedia.org/wikipedia/commons/9/9e/UbuntuCoF.svg"></a>
<a href="https://deb.codetracer.com/"><img width="100px" height="100px" src="https://upload.wikimedia.org/wikipedia/commons/6/66/Openlogo-debianV2.svg"></a>
<a href="https://rpm.codetracer.com/"><img width="100px" height="100px" src="https://upload.wikimedia.org/wikipedia/commons/d/d8/Red_Hat_logo.svg"></a>
<a href="https://rpm.codetracer.com/"><img width="100px" height="100px" src="https://upload.wikimedia.org/wikipedia/commons/3/3f/Fedora_logo.svg"></a>
<a href="https://github.com/metacraft-labs/metacraft-overlay"><img width="100px" height="100px" src="https://upload.wikimedia.org/wikipedia/commons/4/48/Gentoo_Linux_logo_matte.svg"></a>
<a href="https://aur.archlinux.org/packages/codetracer"><img width="100px" height="100px" src="https://upload.wikimedia.org/wikipedia/commons/1/13/Arch_Linux_%22Crystal%22_icon.svg"></a>
<a href="https://downloads.codetracer.com/CodeTracer-${{ needs.push-tag.outputs.tag }}-amd64.AppImage"><img width="100px" height="100px" src="https://upload.wikimedia.org/wikipedia/commons/7/73/App-image-logo.svg"></a>
Key signatures:
[![Download macOS Signature](https://img.shields.io/badge/Download-macOS%20Signature-blue?style=for-the-badge)](https://downloads.codetracer.com/CodeTracer-${{ needs.push-tag.outputs.tag }}-arm64.dmg.asc)
[![Download AppImage Signature](https://img.shields.io/badge/Download-AppImage%20Signature-blue?style=for-the-badge)](https://downloads.codetracer.com/CodeTracer-${{ needs.push-tag.outputs.tag }}-amd64.AppImage.asc)
[![Download PGP Key](https://img.shields.io/badge/Download-PGP%20key-blue?style=for-the-badge)](https://downloads.codetracer.com/CodeTracer.pub.asc)" >> release_changelog.md
- name: Create Release
uses: softprops/action-gh-release@v2
with:
body_path: "release_changelog.md"
draft: true
prerelease: false
files: |
resources.tar.xz
resources.tar.xz.asc
generate_release_notes: false
tag_name: "${{ needs.push-tag.outputs.tag }}"