Skip to content

refactor(repo): move the dev-install symlinking into its own guarded script #244

refactor(repo): move the dev-install symlinking into its own guarded script

refactor(repo): move the dev-install symlinking into its own guarded script #244

Workflow file for this run

name: CI
on:
pull_request:
types: [opened, synchronize, reopened, ready_for_review]
branches: [develop, main]
workflow_dispatch:
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
jobs:
# Enforce Conventional Commits on every PR. Lightweight — stays on
# GitHub-hosted runners (no self-hosted fallback needed).
commit-lint:
name: Commit Lint
runs-on: ubuntu-latest
timeout-minutes: 5
if: github.event.pull_request.draft == false
steps:
- uses: actions/checkout@v7
with:
fetch-depth: 0
- uses: wagoid/commitlint-github-action@v6
with:
configFile: commitlint.config.mjs
# Lint the shell that puts a binary on someone's PATH: POSIX-only shellcheck
# plus canonical shfmt formatting. Both scripts here are install-path logic
# guarded by D-0004 — install.sh places a released binary, dev-install.sh
# symlinks a build-tree one — which is why they are held to a standard the
# rest of the repo's shell is not.
# Lightweight — stays on GitHub-hosted runners, same as commit-lint.
shell-lint:
name: Shell Lint (install scripts)
runs-on: ubuntu-latest
timeout-minutes: 5
if: github.event.pull_request.draft == false
steps:
- uses: actions/checkout@v7
- name: Install shfmt
uses: taiki-e/install-action@v2
with:
tool: shfmt
- name: shellcheck -s sh install.sh dev-install.sh
run: shellcheck -s sh install.sh dev-install.sh
- name: shfmt -d -s -ln posix -i 2 install.sh dev-install.sh
run: shfmt -d -s -ln posix -i 2 install.sh dev-install.sh
# Lint install.ps1: PSScriptAnalyzer at Warning severity, install.sh's Windows sibling.
# Lightweight — stays on GitHub-hosted runners, same as shell-lint above. `shell: pwsh`
# runs PowerShell 7+ (only what ubuntu-latest ships); install.ps1's own compatibility
# floor is Windows PowerShell 5.1, but PSScriptAnalyzer's rules are version-agnostic
# static analysis, so linting under pwsh here still catches what matters.
powershell-lint:
name: PowerShell Lint (install.ps1)
runs-on: ubuntu-latest
timeout-minutes: 5
if: github.event.pull_request.draft == false
steps:
- uses: actions/checkout@v7
- name: Invoke-ScriptAnalyzer install.ps1
shell: pwsh
run: |
Install-Module PSScriptAnalyzer -Force -Scope CurrentUser
Invoke-ScriptAnalyzer -Path install.ps1 -Severity Warning -EnableExit
# Dependency license gate. Renovate auto-merges minor/patch bumps, so without
# this a transitive copyleft dep can reach a release build with nobody reading
# a diff. Policy + per-crate carve-outs live in deny.toml. Licenses only —
# advisories are deliberately not gated on the PR path (see deny.toml).
licenses:
name: Dependency licenses
runs-on: ubuntu-latest
timeout-minutes: 10
if: github.event.pull_request.draft == false
steps:
- uses: actions/checkout@v7
- name: Install cargo-deny
uses: taiki-e/install-action@v2
with:
tool: cargo-deny
- name: cargo deny check licenses
run: cargo deny check licenses
# GitHub-hosted, never self-hosted. This job builds and runs a contributor's
# code (`cargo test`, `build.rs`, proc-macro expansion) straight off a
# `pull_request` trigger, so on a public repo it is arbitrary code execution
# by anyone who can get a PR approved. The org's `self-hosted,build` pool is
# persistent and lives inside our network — one poisoned PR there buys
# lateral access and a foothold that survives into later legitimate runs.
# Ephemeral GitHub-hosted runners bound that blast radius to a throwaway VM.
# `build-release.yml` still uses the self-hosted pool: it triggers only on
# `workflow_run`/`workflow_dispatch`, which a fork PR cannot reach.
rust:
name: Rust (capture layer)
runs-on: ubuntu-latest
if: github.event.pull_request.draft == false
env:
RUST_BACKTRACE: "1"
steps:
- uses: actions/checkout@v7
# Set up the Rust toolchain directly instead of via mise — mise's
# `rust = "stable"` is a silent no-op on runners without rustup. The
# GitHub-hosted images ship rustup, so this just pins stable and adds
# the components fmt/clippy need.
- name: Set up Rust toolchain
shell: bash
run: |
set -euo pipefail
rustup toolchain install stable --profile minimal
rustup default stable
rustup component add rustfmt clippy
- uses: Swatinem/rust-cache@v2
- name: fmt
run: cargo fmt --all -- --check
- name: clippy
run: cargo clippy --workspace --all-targets -- -D warnings
- name: test
run: cargo test --workspace
# Diff EVERY schema emit-schema writes, not just attestation. The cloud
# generates its Zod/TS from these files, so a stale one ships a wrong
# boundary downstream while this job stays green — which is exactly the
# hole knowledge.schema.json sat in: a KnowledgeDecision/KnowledgeSpec
# field addition leaves attestation.schema.json byte-identical.
- name: contract schemas are up to date
run: |
cargo run -q -p dira-contract --bin emit-schema
git diff --exit-code contract/*.schema.json \
|| (echo "a contract schema is stale — run 'just contract-schema'"; exit 1)
- name: signing vector fixture is up to date
run: |
cargo run -q -p dira-core --bin sign_vector > contract/testdata/signing-vector.json
git diff --exit-code contract/testdata/signing-vector.json \
|| (echo "signing-vector fixture is stale — run 'just vector'"; exit 1)
# Windows build/test lane (native, not WSL): validates the named-pipe IPC transport
# (`cli/ipc`) and everything else in the workspace on the actual target platform.
# Independent of `rust` above — fmt/contract-schema stay Linux-only intentionally
# (see module doc), so this job only runs clippy + tests.
rust-windows:
name: Rust (windows)
runs-on: windows-latest
if: github.event.pull_request.draft == false
timeout-minutes: 30
env:
RUST_BACKTRACE: "1"
steps:
- uses: actions/checkout@v7
- name: Set up Rust toolchain
shell: bash
run: |
set -euo pipefail
rustup toolchain install stable --profile minimal
rustup default stable
rustup component add clippy
- uses: Swatinem/rust-cache@v2
- name: clippy
run: cargo clippy --workspace --all-targets -- -D warnings
- name: test
run: cargo test --workspace
# Proves `.cargo/config.toml`'s `+crt-static` actually takes effect, from
# THIS branch's source (#60). build-release.yml carries the same assertion,
# but that job checks out `refs/tags/<tag>` — so it can only ever validate a
# tag that already contains the fix, never a change under review. That
# distinction cost a confused debugging round; keep both.
# Debug build: linkage is set per-target in .cargo/config.toml and applies
# to every profile, and the dependency graph is already warm from the two
# steps above, so this costs seconds.
- name: CRT is linked statically
shell: pwsh
run: |
$ErrorActionPreference = 'Stop'
cargo build --bin dira --bin dirad
if ($LASTEXITCODE -ne 0) { throw "cargo build failed (exit $LASTEXITCODE)" }
$bad = @()
foreach ($name in 'dira', 'dirad') {
$exe = "target/debug/$name.exe"
if (-not (Test-Path $exe)) { throw "expected $exe to exist" }
$text = [Text.Encoding]::ASCII.GetString([IO.File]::ReadAllBytes($exe))
foreach ($dll in 'VCRUNTIME140', 'api-ms-win-crt-runtime') {
if ($text -match [regex]::Escape($dll)) { $bad += "$name.exe imports $dll" }
}
}
if ($bad) {
throw "dynamic CRT -- these would need the VC++ Redistributable: $($bad -join '; ')"
}
Write-Host "both binaries link the CRT statically"