name: Nightly
on:
schedule:
- cron: '0 4 * * *'
workflow_dispatch:
permissions:
contents: write
jobs:
check-activity:
runs-on: ubuntu-latest
outputs:
has_commits: ${{ steps.check.outputs.has_commits }}
steps:
- name: Checkout
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 with:
fetch-depth: 0
- name: Check for commits in last 24h
id: check
run: |
RECENT=$(git log --oneline --since="24 hours ago" | wc -l)
if [ "$RECENT" -gt 0 ] || [ "${{ github.event_name }}" = "workflow_dispatch" ]; then
echo "has_commits=true" >> "$GITHUB_OUTPUT"
echo "Found $RECENT commit(s) in last 24h (or manual trigger)"
else
echo "has_commits=false" >> "$GITHUB_OUTPUT"
echo "No commits in last 24h — skipping nightly build"
fi
build:
needs: check-activity
if: needs.check-activity.outputs.has_commits == 'true'
strategy:
fail-fast: false
matrix:
include:
- target: x86_64-unknown-linux-gnu
runner: ubuntu-latest
- target: x86_64-apple-darwin
runner: macos-latest
- target: aarch64-apple-darwin
runner: macos-latest
- target: x86_64-pc-windows-msvc
runner: windows-latest
runs-on: ${{ matrix.runner }}
steps:
- name: Checkout
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683
- name: Checkout provable-contracts (path dep)
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 with:
repository: paiml/provable-contracts
path: provable-contracts
- name: Symlink provable-contracts for Cargo path deps
if: runner.os != 'Windows'
run: ln -sf "$GITHUB_WORKSPACE/provable-contracts" "$GITHUB_WORKSPACE/../provable-contracts"
- name: Symlink provable-contracts (Windows)
if: runner.os == 'Windows'
shell: pwsh
run: New-Item -ItemType Junction -Path "$env:GITHUB_WORKSPACE\..\provable-contracts" -Target "$env:GITHUB_WORKSPACE\provable-contracts" -Force
- name: Install Rust toolchain
uses: dtolnay/rust-toolchain@stable
with:
targets: ${{ matrix.target }}
- name: Ensure target is installed
run: rustup target add ${{ matrix.target }}
- name: Generate contract assertions — pv codegen (unix)
if: runner.os != 'Windows'
run: |
# Install pv if not present
if ! command -v pv >/dev/null 2>&1; then
cargo install provable-contracts-cli --locked || true
fi
PV=$(command -v pv 2>/dev/null || true)
if [ -z "$PV" ]; then
echo "::warning::pv not found — skipping contract generation"
else
echo "pv found at: $PV"
# Prefer master contract set from checked-out provable-contracts sibling
PC_CONTRACTS="$GITHUB_WORKSPACE/../provable-contracts/contracts"
# Generate for root src/ if mod generated_contracts exists and file is absent
if [ -f src/lib.rs ] && grep -q 'mod generated_contracts' src/lib.rs && [ ! -f src/generated_contracts.rs ]; then
if [ -d "$PC_CONTRACTS" ]; then
"$PV" codegen "$PC_CONTRACTS" -o src/generated_contracts.rs || true
elif [ -d contracts ]; then
"$PV" codegen contracts/ -o src/generated_contracts.rs || true
fi
fi
# Generate for workspace members
for src_dir in crates/*/src */src; do
if [ -d "$src_dir" ] && [ -f "$src_dir/lib.rs" ] && grep -q 'mod generated_contracts' "$src_dir/lib.rs" && [ ! -f "$src_dir/generated_contracts.rs" ]; then
member_dir=$(dirname "$src_dir")
if [ -d "$PC_CONTRACTS" ]; then
"$PV" codegen "$PC_CONTRACTS" -o "$src_dir/generated_contracts.rs" || true
elif [ -d "$member_dir/contracts" ]; then
"$PV" codegen "$member_dir/contracts" -o "$src_dir/generated_contracts.rs" || true
fi
fi
done
fi
- name: Generate contract assertions — pv codegen (windows)
if: runner.os == 'Windows'
shell: pwsh
run: |
# Install pv if not present
$pvPath = (Get-Command pv -ErrorAction SilentlyContinue)?.Source
if (-not $pvPath) {
cargo install provable-contracts-cli --locked 2>$null
$pvPath = (Get-Command pv -ErrorAction SilentlyContinue)?.Source
}
if (-not $pvPath) {
Write-Warning "pv not found — skipping contract generation"
} else {
Write-Host "pv found at: $pvPath"
$pcContracts = Join-Path $env:GITHUB_WORKSPACE "..\provable-contracts\contracts"
# Generate for root src/ if mod generated_contracts exists and file is absent
if ((Test-Path "src\lib.rs") -and (Select-String -Quiet -Pattern 'mod generated_contracts' "src\lib.rs") -and (-not (Test-Path "src\generated_contracts.rs"))) {
if (Test-Path $pcContracts) {
& $pvPath codegen $pcContracts -o src\generated_contracts.rs
} elseif (Test-Path "contracts") {
& $pvPath codegen contracts\ -o src\generated_contracts.rs
}
}
# Generate for workspace members
foreach ($srcDir in (Get-ChildItem -Path "crates\*\src","*\src" -Directory -ErrorAction SilentlyContinue)) {
$libRs = Join-Path $srcDir "lib.rs"
$genRs = Join-Path $srcDir "generated_contracts.rs"
if ((Test-Path $libRs) -and (Select-String -Quiet -Pattern 'mod generated_contracts' $libRs) -and (-not (Test-Path $genRs))) {
$memberDir = Split-Path $srcDir -Parent
$memberContracts = Join-Path $memberDir "contracts"
if (Test-Path $pcContracts) {
& $pvPath codegen $pcContracts -o $genRs
} elseif (Test-Path $memberContracts) {
& $pvPath codegen $memberContracts -o $genRs
}
}
}
}
- name: Build release binary
run: cargo build --release --features vendored-openssl --target ${{ matrix.target }}
- name: Package (unix)
if: runner.os != 'Windows'
run: |
ARCHIVE="forjar-${{ matrix.target }}"
mkdir -p "$ARCHIVE"
cp "target/${{ matrix.target }}/release/forjar" "$ARCHIVE/"
for f in README.md LICENSE LICENSE-MIT COPYING UNLICENSE; do
[ -f "$f" ] && cp "$f" "$ARCHIVE/"
done
tar czf "${ARCHIVE}.tar.gz" "$ARCHIVE"
shasum -a 256 "${ARCHIVE}.tar.gz" > "${ARCHIVE}.tar.gz.sha256"
echo "Packaged: ${ARCHIVE}.tar.gz ($(du -h "${ARCHIVE}.tar.gz" | cut -f1))"
- name: Package (windows)
if: runner.os == 'Windows'
shell: pwsh
run: |
$archive = "forjar-${{ matrix.target }}"
New-Item -ItemType Directory -Force -Path $archive
Copy-Item "target/${{ matrix.target }}/release/forjar.exe" "$archive/"
foreach ($f in @("README.md", "LICENSE", "LICENSE-MIT", "COPYING", "UNLICENSE")) {
if (Test-Path $f) { Copy-Item $f "$archive/" }
}
Compress-Archive -Path "$archive/*" -DestinationPath "$archive.zip"
$hash = (Get-FileHash "$archive.zip" -Algorithm SHA256).Hash.ToLower()
"$hash $archive.zip" | Out-File -Encoding ascii "$archive.zip.sha256"
Write-Host "Packaged: $archive.zip"
- name: Upload artifact (unix)
if: runner.os != 'Windows'
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 with:
name: forjar-${{ matrix.target }}
path: |
forjar-${{ matrix.target }}.tar.gz
forjar-${{ matrix.target }}.tar.gz.sha256
- name: Upload artifact (windows)
if: runner.os == 'Windows'
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 with:
name: forjar-${{ matrix.target }}
path: |
forjar-${{ matrix.target }}.zip
forjar-${{ matrix.target }}.zip.sha256
release:
needs: build
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683
- name: Download all artifacts
uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 with:
path: artifacts
merge-multiple: true
- name: Delete existing nightly release
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
gh release delete nightly --yes --cleanup-tag 2>/dev/null || true
- name: Create nightly release
uses: softprops/action-gh-release@da05d552573ad5aba039eaac05058a918a7bf631 with:
tag_name: nightly
name: Nightly Build
prerelease: true
make_latest: false
body: |
Automated nightly build from `main`.
**Date:** ${{ github.event.repository.updated_at || github.event.head_commit.timestamp }}
**Commit:** ${{ github.sha }}
> This is a prerelease. For stable releases, see the latest tagged version.
files: |
artifacts/*