Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
60 commits
Select commit Hold shift + click to select a range
0f9a8e6
feat(devshell): add gitleaks for secret scanning
cameronraysmith Oct 26, 2025
7231424
feat(justfile): add gitleaks secret scanning recipes
cameronraysmith Oct 26, 2025
fda9cfb
feat(ci): add gitleaks secrets scanning job
cameronraysmith Oct 26, 2025
39e8715
feat(ci): remove GitGuardian API key from secrets management
cameronraysmith Oct 26, 2025
60f4aa8
feat(cloudflare): implement Workers version promotion workflow
cameronraysmith Oct 26, 2025
bb1a63f
feat(ci): use optimized deployment workflow in GitHub Actions
cameronraysmith Oct 26, 2025
0d448af
fix(gitleaks): add inline allowlist for age public keys
cameronraysmith Oct 26, 2025
ed7109c
feat(gitleaks): add .gitleaksignore for false positive fingerprints
cameronraysmith Oct 26, 2025
edbbed0
feat(ci): enable preview deployments via docs-preview label
cameronraysmith Oct 26, 2025
8bddbf1
feat(scripts): add preview-version.sh script
cameronraysmith Oct 26, 2025
fcc2a1e
feat: add package discovery recipes to justfile
cameronraysmith Oct 26, 2025
e1dafdf
feat(justfile): add preview-version recipe
cameronraysmith Oct 26, 2025
0e99c8b
refactor(ci): align setup-nix action with infra reference implementation
cameronraysmith Oct 26, 2025
1dede3a
feat(ci): add reusable package-release workflow
cameronraysmith Oct 26, 2025
60a13ff
feat(just): add release-package recipe
cameronraysmith Oct 26, 2025
ea6c2c7
refactor(ci): convert to orchestrator pattern with reusable workflows
cameronraysmith Oct 26, 2025
72ec2b5
refactor(release): remove @semantic-release/git plugin
cameronraysmith Oct 26, 2025
ee9baec
fix(ci): remove invalid concurrency blocks from reusable workflow calls
cameronraysmith Oct 26, 2025
fd2e56f
fix(ci): remove GITHUB_TOKEN from package-release workflow_call secrets
cameronraysmith Oct 26, 2025
9edb311
feat(docs): enable static site generation with prerender
cameronraysmith Oct 27, 2025
23b23f8
feat(release): add beta branch for prerelease testing
cameronraysmith Oct 27, 2025
b20864a
fix(ci): sync preview-version.sh with infra improvements
cameronraysmith Oct 27, 2025
669c9d3
refactor(ci): remove semantic-release-action, use direct execution
cameronraysmith Oct 27, 2025
be5b579
refactor(ci): restructure job architecture for fast preview feedback
cameronraysmith Oct 27, 2025
a16f62b
refactor(ci): consolidate deploy-docs to single job
cameronraysmith Oct 27, 2025
707f283
fix(ci): correct setup-nix input from setup-cachix to enable-cachix
cameronraysmith Oct 27, 2025
4af8aad
fix(ci): prevent production-docs-deploy from running on PRs
cameronraysmith Oct 27, 2025
e086178
feat(ci): add skip-duplicate-actions to prevent redundant workflow runs
cameronraysmith Oct 28, 2025
4bf97f5
build(docs): add starlight-links-validator to devDependencies
cameronraysmith Oct 30, 2025
e101887
feat(docs): add linkcheck script for explicit link validation
cameronraysmith Oct 30, 2025
8ca266d
feat(docs): add conditional link validation with starlight-links-vali…
cameronraysmith Oct 30, 2025
69b20d4
feat: add docs linkcheck recipe to justfile
cameronraysmith Oct 30, 2025
3cc558a
ci(docs): add link validation step before deployment
cameronraysmith Oct 30, 2025
33705c5
build: update bun.lock with starlight-links-validator dependencies
cameronraysmith Oct 30, 2025
210da12
feat(ci): add PR fast-forward validation workflow
cameronraysmith Oct 30, 2025
106431c
feat(ci): add PR fast-forward merge workflow with /fast-forward command
cameronraysmith Oct 30, 2025
91b189b
feat(mergify): modernize configuration with 2025 best practices
cameronraysmith Oct 30, 2025
14b4868
feat(docs): add Just grammar syntax highlighting
cameronraysmith Oct 30, 2025
2e14fa8
feat(secrets): add FAST_FORWARD_PAT to ghsecrets recipe
cameronraysmith Oct 30, 2025
9fc1212
feat(nix): add playwright-web-flake input for version-locked browsers
cameronraysmith Oct 30, 2025
2368056
refactor(justfile): align docs recipes with multi-package pattern
cameronraysmith Oct 30, 2025
967b5a4
fix(ci): update package-test workflow to use docs-* recipes
cameronraysmith Oct 30, 2025
8ce2803
fix(ci): update deploy-docs workflow to use docs-linkcheck recipe
cameronraysmith Oct 30, 2025
62a2bb4
chore(nix): update flake.lock with playwright-web-flake
cameronraysmith Oct 30, 2025
e9a7a65
fix(docs): add Just grammar file and correct Starlight integration
cameronraysmith Oct 30, 2025
95108f0
fix(docs): use 'just' language identifier for syntax highlighting
cameronraysmith Oct 30, 2025
6db50d5
fix(docs): sync @playwright/test to match playwright-web-flake 1.56.1
cameronraysmith Oct 30, 2025
4af7315
chore: update bun.lock to sync playwright dependencies
cameronraysmith Oct 30, 2025
a17c5f9
feat(deps): add dependency management recipes and playwright version …
cameronraysmith Oct 30, 2025
cee488a
fix(docs): use inline code for localhost URL to avoid link validation
cameronraysmith Oct 30, 2025
8a1830f
fix(docs): link to CONTRIBUTING.md on GitHub instead of broken absolu…
cameronraysmith Oct 30, 2025
3e98640
fix(ci): disable cachix in deploy-docs workflow
cameronraysmith Oct 30, 2025
9295c88
feat(docs): add root docs/ symlink to packages/docs/src/content/docs/
cameronraysmith Oct 30, 2025
0ec4f11
feat: add per-job content-addressed caching composite action
cameronraysmith Oct 31, 2025
817b320
refactor: replace skip-check with per-job content-addressed caching
cameronraysmith Oct 31, 2025
090804c
fix(docs): conform to astro md processor reqs
cameronraysmith Oct 31, 2025
78738f2
fix(docs): allow localhost links in link validator
cameronraysmith Oct 31, 2025
9e440fc
chore(deps): upgrade wrangler from 4.42.0 to 4.45.0
cameronraysmith Oct 31, 2025
939452e
refactor(ci): remove display name override from secrets-scan job
cameronraysmith Oct 31, 2025
3208fea
docs(ci): clarify why secrets-scan uses caching despite being securit…
cameronraysmith Oct 31, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
157 changes: 157 additions & 0 deletions .github/actions/cached-ci-job/action.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,157 @@
name: Cached CI Job
description: Execute job only if not already successful for this commit SHA

inputs:
check-name:
description: Full check run name (defaults to github.job, include matrix values for matrix jobs)
required: false
default: ${{ github.job }}
path-filters:
description: Regex pattern for relevant file paths (empty means always relevant)
required: false
default: ''
force-run:
description: Force execution even if already successful
required: false
default: 'false'

outputs:
should-run:
description: Whether job should execute (true/false)
value: ${{ steps.decide.outputs.should-run }}
previously-succeeded:
description: Whether this job previously succeeded for this commit
value: ${{ steps.check-history.outputs.previously-succeeded }}
relevant-changes:
description: Whether relevant file changes were detected
value: ${{ steps.check-paths.outputs.relevant-changes }}

runs:
using: composite
steps:
- name: Query GitHub Checks API for execution history
id: check-history
uses: actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea # ratchet:actions/github-script@v7
env:
CHECK_NAME: ${{ inputs.check-name }}
with:
script: |
const checkName = process.env.CHECK_NAME;
const commit = context.sha;

core.info(`Querying execution history for: "${checkName}" @ ${commit}`);

try {
const { data: checks } = await github.rest.checks.listForRef({
owner: context.repo.owner,
repo: context.repo.repo,
ref: commit,
check_name: checkName,
});

core.info(`Found ${checks.check_runs.length} check run(s) for this commit`);

// Find any completed successful run
const successfulRun = checks.check_runs.find(run =>
run.conclusion === 'success' &&
run.status === 'completed'
);

if (successfulRun) {
core.info(`✓ Job already succeeded: ${successfulRun.html_url}`);
core.setOutput('previously-succeeded', 'true');
} else {
const failedRuns = checks.check_runs.filter(run =>
run.conclusion === 'failure' &&
run.status === 'completed'
);
if (failedRuns.length > 0) {
core.info(`✗ Found ${failedRuns.length} previous failed run(s)`);
} else {
core.info(`✗ No previous runs found`);
}
core.setOutput('previously-succeeded', 'false');
}
} catch (error) {
core.warning(`API query failed: ${error.message}`);
core.setOutput('previously-succeeded', 'false');
}

- name: Check for relevant file changes
id: check-paths
if: |
steps.check-history.outputs.previously-succeeded != 'true' &&
inputs.path-filters != ''
shell: bash
env:
PATH_FILTERS: ${{ inputs.path-filters }}
run: |
# Determine base ref for comparison
if [ "${{ github.event_name }}" = "pull_request" ]; then
BASE_REF="${{ github.event.pull_request.base.sha }}"
else
BASE_REF="HEAD^"
fi

echo "Checking for changes matching: $PATH_FILTERS"
echo "Comparing $BASE_REF...HEAD"

# Workflow changes always trigger all jobs
if git diff --name-only "$BASE_REF" HEAD | grep -qE '\.github/workflows/'; then
echo "relevant-changes=true" >> $GITHUB_OUTPUT
echo "✓ Workflow changes detected - job is relevant"
exit 0
fi

# Check if any relevant files changed
if git diff --name-only "$BASE_REF" HEAD | grep -qE "$PATH_FILTERS"; then
echo "relevant-changes=true" >> $GITHUB_OUTPUT
echo "✓ Relevant file changes detected"
else
echo "relevant-changes=false" >> $GITHUB_OUTPUT
echo "✗ No relevant file changes"
fi

- name: Make execution decision
id: decide
shell: bash
env:
FORCE: ${{ inputs.force-run }}
PREV_SUCCESS: ${{ steps.check-history.outputs.previously-succeeded }}
HAS_CHANGES: ${{ steps.check-paths.outputs.relevant-changes }}
HAS_FILTERS: ${{ inputs.path-filters != '' }}
run: |
echo "=== Execution Decision ==="
echo "Force run: $FORCE"
echo "Previously succeeded: $PREV_SUCCESS"
echo "Has path filters: $HAS_FILTERS"
echo "Relevant changes: $HAS_CHANGES"
echo ""

# Force run overrides everything
if [ "$FORCE" = "true" ]; then
echo "should-run=true" >> $GITHUB_OUTPUT
echo "Decision: RUN (forced by input)"
exit 0
fi

# If already succeeded for this commit, skip
if [ "$PREV_SUCCESS" = "true" ]; then
echo "should-run=false" >> $GITHUB_OUTPUT
echo "Decision: SKIP (already succeeded for this commit)"
exit 0
fi

# If we have path filters, honor them
if [ "$HAS_FILTERS" = "true" ]; then
echo "should-run=${HAS_CHANGES}" >> $GITHUB_OUTPUT
if [ "$HAS_CHANGES" = "true" ]; then
echo "Decision: RUN (relevant file changes detected)"
else
echo "Decision: SKIP (no relevant file changes)"
fi
else
# No filters means always run if not already succeeded
echo "should-run=true" >> $GITHUB_OUTPUT
echo "Decision: RUN (no path filters specified)"
fi
138 changes: 82 additions & 56 deletions .github/actions/setup-nix/action.yml
Original file line number Diff line number Diff line change
@@ -1,61 +1,86 @@
name: setup-nix
description: Setup Nix with optional disk space optimization and cachix binary cache configuration
description: setup nix using nothing-but-nix pattern with space reclamation and github actions cache

inputs:
installer:
description: |
Nix installation strategy:
- 'full' (default): Aggressive disk cleanup + DeterminateSystems installer
- 'quick': Lightweight install with nixbuild/nix-quick-install-action
nix installation strategy:
- 'full' (default): space reclamation + cache + cachix for builds
- 'quick': minimal install for simple tasks (no space reclamation, no caching overhead)
type: string
required: false
default: full
system:
description: Nix system to configure (e.g., x86_64-linux, aarch64-darwin)
description: nix system to configure (e.g., x86_64-linux, aarch64-darwin)
type: string
required: false
default: x86_64-linux
extra-conf:
description: Additional nix.conf configuration
required: true
sandbox:
description: enable nix sandbox builds
type: string
default: "true"
cache-key:
description: primary cache key (auto-generated from nix files if not provided)
type: string
required: false
default: system-features = nixos-test benchmark big-parallel kvm
setup-cachix:
description: Setup cachix binary cache after Nix installation (requires SOPS_AGE_KEY in env)
default: ""
gc-max-store-size-linux:
description: max nix store size on linux before garbage collection (e.g., 5G, 10G)
type: string
default: "5G"
gc-max-store-size-macos:
description: max nix store size on macos before garbage collection (e.g., 5G, 10G)
type: string
default: "5G"
enable-cachix:
description: enable cachix binary cache
type: boolean
required: false
default: false
cachix-auth:
description: Authenticate with cachix for pushing (requires setup-cachix=true)
type: boolean
cachix-name:
description: cachix cache name
type: string
required: false
cachix-auth-token:
description: cachix auth token
type: string
required: false
cachix-skip-push:
description: skip pushing to cachix (read-only)
type: boolean
default: false

outputs:
cache-hit:
description: whether the primary cache key was hit
value: ${{ steps.cache.outputs.hit-primary-key }}
cache-key:
description: the cache key that was used
value: ${{ steps.cache.outputs.primary-key }}

runs:
using: composite
steps:
# Full installer: Aggressive disk cleanup + DeterminateSystems
- name: Reclaim disk space (Linux)
- name: reclaim space (linux)
if: runner.os == 'Linux' && inputs.installer == 'full'
uses: wimpysworld/nothing-but-nix@main
uses: wimpysworld/nothing-but-nix@10c936d9e46521bf923f75458e0cbd4fa309300d # ratchet:wimpysworld/nothing-but-nix@main
with:
hatchet-protocol: rampage
hatchet-protocol: carve
nix-permission-edict: true

- name: Reclaim disk space (macOS)
- name: reclaim space (darwin)
if: runner.os == 'macOS' && inputs.installer == 'full'
shell: bash
run: |
echo "::group::Disk space before cleanup"
echo "::group::disk space (before)"
sudo df -h
echo "::endgroup::"

echo "::group::Disable Spotlight indexing"
echo "::group::disable mds"
sudo mdutil -i off -a || echo "mdutil failed"
sudo launchctl unload -w /System/Library/LaunchDaemons/com.apple.metadata.mds.plist \
|| echo "launchctl unload failed"
|| echo "launchctl unload failed"
echo "::endgroup::"

echo "Starting background cleanup to reclaim disk space..."
echo "Background space expansion started. /nix will grow as space becomes available."
sudo rm -rf \
/Applications/Xcode_* \
/Library/Developer/CoreSimulator \
Expand All @@ -67,44 +92,45 @@ runs:
/Users/runner/Library/Developer/CoreSimulator \
/Users/runner/hostedtoolcache &

- name: Install Nix (DeterminateSystems)
if: inputs.installer == 'full'
uses: DeterminateSystems/nix-installer-action@main
- name: install nix
uses: nixbuild/nix-quick-install-action@2c9db80fb984ceb1bcaa77cdda3fdf8cfba92035 # ratchet:nixbuild/nix-quick-install-action@v34
with:
extra-conf: |
nix_conf: |
sandbox = ${{ inputs.sandbox }}
system = ${{ inputs.system }}
${{ inputs.extra-conf }}
keep-env-derivations = true
keep-outputs = true

# Quick installer: Lightweight nixbuild/nix-quick-install-action
- name: Install Nix (Quick Install)
if: inputs.installer == 'quick'
uses: nixbuild/nix-quick-install-action@master
- name: setup cache
if: runner.os == 'Linux' && inputs.installer == 'full'
id: cache
uses: nix-community/cache-nix-action@135667ec418502fa5a3598af6fb9eb733888ce6a # ratchet:nix-community/cache-nix-action@v6
with:
primary-key: ${{ inputs.cache-key != '' && inputs.cache-key || format('nix-{0}-{1}', runner.os, hashFiles('**/*.nix', '**/flake.lock')) }}
restore-prefixes-first-match: ${{ format('nix-{0}-', runner.os) }}
gc-max-store-size-linux: ${{ inputs.gc-max-store-size-linux }}
gc-max-store-size-macos: ${{ inputs.gc-max-store-size-macos }}
purge: true
purge-prefixes: ${{ format('nix-{0}-', runner.os) }}
purge-created: 0
purge-last-accessed: 0
purge-primary-key: never

- name: Report disk space (macOS post-cleanup)
- name: setup cachix
if: inputs.enable-cachix
uses: cachix/cachix-action@0fc020193b5a1fa3ac4575aa3a7d3aa6a35435ad # ratchet:cachix/cachix-action@v16
continue-on-error: true
with:
name: ${{ inputs.cachix-name }}
authToken: ${{ inputs.cachix-auth-token }}
skipPush: ${{ inputs.cachix-skip-push }}

- name: post setup-nix
if: runner.os == 'macOS' && inputs.installer == 'full'
uses: srz-zumix/post-run-action@v2
uses: srz-zumix/post-run-action@2bf288bc024acd0341914f792a811080ebd0f252 # ratchet:srz-zumix/post-run-action@v2
with:
shell: bash -e {0}
post-run: |
echo "::group::Disk space after workflow"
echo "::group::disk space (after)"
sudo df -h
echo "::endgroup::"

- name: Setup and authenticate cachix
if: inputs.setup-cachix == 'true' && inputs.cachix-auth == 'true'
shell: bash
run: |
nix develop -c sops exec-env vars/shared.yaml '
cachix authtoken "$CACHIX_AUTH_TOKEN"
cachix use "$CACHIX_CACHE_NAME"
cachix use nix-community
'

- name: Setup cachix for binary cache
if: inputs.setup-cachix == 'true' && inputs.cachix-auth != 'true'
shell: bash
run: |
nix develop -c sops exec-env vars/shared.yaml '
cachix use "$CACHIX_CACHE_NAME"
cachix use nix-community
'
29 changes: 24 additions & 5 deletions .github/mergify.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,19 +8,38 @@ pull_request_rules:
assign:
add_users:
- "{{ author }}"
- name: automatic merge when not WIP, CI passes, and at least 1 approving review
- name: automatic merge to queue
conditions:
- "#approved-reviews-by>=1"
- check-success=scan
- check-success=nix (ubuntu-latest)
- check-success=test (docs)
- base=main
- label!=work-in-progress
- -draft
- -conflict
- check-success=skip-check
- check-success=gitleaks
- check-success=set-variables
- or:
- check-success=nix
- check-skipped=nix
- or:
- check-success=test (docs)
- check-skipped=test (docs)
- check-success=PR Check Fast-forward
actions:
queue:
name: default

queue_rules:
- name: default
merge_method: fast-forward
update_method: rebase
update_bot_account: cameronraysmith
batch_size: 1
checks_timeout: 3600
queue_conditions:
- check-success=skip-check
merge_conditions:
- check-success=skip-check
commit_message_template: |
{{ title }} (#{{ number }})

{{ body }}
Loading
Loading