Move release distribution to SourceHut
ober
bb6340c5d5fe841b8c5609759e6e750c93b2a762
deleted file mode 100644 --- a/.github/workflows/build-macos-libs.yml +++ /dev/null @@ -1,75 +0,0 @@ -name: Build macOS Rust Libraries - -on: - workflow_dispatch: # manual trigger from GitHub UI or gh CLI - push: - paths: - - 'jerboa-native-rs/**' - - 'support/container-dependencies.lock' - - 'support/container-inputs.sh' - - '.github/workflows/build-macos-libs.yml' - -env: - RELEASE_TAG: macos-libs-v1 - -jobs: - build: - strategy: - matrix: - include: - - runner: macos-14 # Apple Silicon (M1+) - arch: arm64 - - runner: macos-13 # Intel - arch: x86_64 - runs-on: ${{ matrix.runner }} - steps: - - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1 - - - name: Install Rust toolchain - uses: dtolnay/rust-toolchain@8fae6aadcd3e1a6f3fcb446ce7f9438c9d1349f1 # 1.94.1 - with: - toolchain: 1.94.1 - - - name: Build libjerboa_native.a - run: | - cd jerboa-native-rs - cargo build --release - ls -lh target/release/libjerboa_native.a - - - name: Materialize pinned jerboa-shell (for rust-coreutils) - run: support/container-inputs.sh fetch-git jerboa-shell - - - name: Build libjsh_coreutils.a - run: | - cd /tmp/jerboa-shell/rust-coreutils - cargo build --release - ls -lh target/release/libjsh_coreutils.a - - - name: Stage artifacts with arch suffix - run: | - cp jerboa-native-rs/target/release/libjerboa_native.a \ - libjerboa_native-macos-${{ matrix.arch }}.a - cp /tmp/jerboa-shell/rust-coreutils/target/release/libjsh_coreutils.a \ - libjsh_coreutils-macos-${{ matrix.arch }}.a - ls -lh *.a - - - name: Upload to GitHub release - env: - GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} - run: | - # Create the release if it doesn't exist yet - gh release view "$RELEASE_TAG" --repo ${{ github.repository }} >/dev/null 2>&1 || \ - gh release create "$RELEASE_TAG" \ - --repo ${{ github.repository }} \ - --title "macOS Pre-built Rust Libraries" \ - --notes "Pre-built static Rust libraries for macOS jsh builds (no Rust toolchain required). - - Assets: - - libjerboa_native — crypto, regex, compression - - libjsh_coreutils — Rust coreutils - - Built automatically by CI for arm64 (Apple Silicon) and x86_64 (Intel)." - gh release upload "$RELEASE_TAG" \ - libjerboa_native-macos-${{ matrix.arch }}.a \ - libjsh_coreutils-macos-${{ matrix.arch }}.a \ - --repo ${{ github.repository }} --clobber deleted file mode 100644 --- a/.github/workflows/ci.yml +++ /dev/null @@ -1,134 +0,0 @@ -name: CI - -on: - push: - branches: [master] - pull_request: - schedule: - # Daily security maintenance: `make audit` refreshes advisories and the - # scheduled-only deep fuzz step exercises the checked-in corpora. - - cron: '23 9 * * *' - -env: - IMAGE: docker.io/jerboa21/jerboa - -jobs: - build-and-test: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1 - - - name: Verify immutable container inputs - id: container-lock - run: | - support/container-inputs.sh check - echo "base_image=$(support/container-inputs.sh field ubuntu-24.04 3)" >> "$GITHUB_OUTPUT" - - - name: Build base image (loaded locally) - run: | - podman build --platform linux/amd64 -f Containerfile \ - --build-arg JERBOA_BASE_IMAGE="${{ steps.container-lock.outputs.base_image }}" \ - -t "${{ env.IMAGE }}:ci" . - - - name: Run core tests - run: | - podman run --rm \ - -v "${{ github.workspace }}:/workspace" -w /workspace \ - -e JERBOA=/workspace/lib -e JERBOA_HOME=/workspace \ - ${{ env.IMAGE }}:ci \ - make test SCHEME=scheme - - - name: Build libraries - run: | - podman run --rm \ - -v "${{ github.workspace }}:/workspace" -w /workspace \ - -e JERBOA=/workspace/lib -e JERBOA_HOME=/workspace \ - ${{ env.IMAGE }}:ci \ - make build SCHEME=scheme - - - name: Run production security audit - run: | - podman run --rm \ - -v "${{ github.workspace }}:/workspace" -w /workspace \ - -e JERBOA=/workspace/lib -e JERBOA_HOME=/workspace \ - ${{ env.IMAGE }}:ci \ - make audit SCHEME=scheme - - - name: Run fuzz smoke - timeout-minutes: 15 - run: | - podman run --rm \ - -v "${{ github.workspace }}:/workspace" -w /workspace \ - -e JERBOA=/workspace/lib -e JERBOA_HOME=/workspace \ - ${{ env.IMAGE }}:ci \ - make fuzz-smoke SCHEME=scheme - - - name: Run scheduled deep fuzz - if: github.event_name == 'schedule' - timeout-minutes: 60 - run: | - podman run --rm \ - -v "${{ github.workspace }}:/workspace" -w /workspace \ - -e JERBOA=/workspace/lib -e JERBOA_HOME=/workspace \ - ${{ env.IMAGE }}:ci \ - make fuzz-deep SCHEME=scheme - - - name: Run feature tests (informational) - continue-on-error: true - timeout-minutes: 10 - run: | - podman run --rm \ - -v "${{ github.workspace }}:/workspace" -w /workspace \ - -e JERBOA=/workspace/lib -e JERBOA_HOME=/workspace \ - ${{ env.IMAGE }}:ci \ - make test-features SCHEME=scheme - - - name: Check doc examples (parse-only) - # NOTE: ~20 fences across docs/ currently have real parse errors - # (mismatched parens etc). Informational until they are fixed. - continue-on-error: true - timeout-minutes: 10 - run: | - podman run --rm \ - -v "${{ github.workspace }}:/workspace" -w /workspace \ - -e JERBOA=/workspace/lib -e JERBOA_HOME=/workspace \ - ${{ env.IMAGE }}:ci \ - make check-docs SCHEME=scheme - - - name: Check doc examples (strict, imports resolved) - continue-on-error: true - timeout-minutes: 15 - run: | - podman run --rm \ - -v "${{ github.workspace }}:/workspace" -w /workspace \ - -e JERBOA=/workspace/lib -e JERBOA_HOME=/workspace \ - ${{ env.IMAGE }}:ci \ - make check-docs-strict SCHEME=scheme - - push-image: - needs: build-and-test - if: github.ref == 'refs/heads/master' && github.event_name == 'push' - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1 - - - name: Verify immutable container inputs - id: container-lock - run: | - support/container-inputs.sh check - echo "base_image=$(support/container-inputs.sh field ubuntu-24.04 3)" >> "$GITHUB_OUTPUT" - - - name: Login to container registry - run: | - podman login docker.io \ - --username "${{ secrets.REGISTRY_USERNAME }}" \ - --password-stdin <<< "${{ secrets.REGISTRY_TOKEN }}" - - - name: Build and push (latest + sha) - run: | - podman build --platform linux/amd64 -f Containerfile \ - --build-arg JERBOA_BASE_IMAGE="${{ steps.container-lock.outputs.base_image }}" \ - -t "${{ env.IMAGE }}:latest" \ - -t "${{ env.IMAGE }}:${{ github.sha }}" . - podman push "${{ env.IMAGE }}:latest" - podman push "${{ env.IMAGE }}:${{ github.sha }}" deleted file mode 100644 --- a/.github/workflows/platform-sandbox.yml +++ /dev/null @@ -1,33 +0,0 @@ -name: Platform Sandbox - -on: - workflow_dispatch: - pull_request: - paths: - - '.github/workflows/platform-sandbox.yml' - - 'lib/std/os/**' - - 'lib/std/security/**' - - 'tests/test-seatbelt.ss' - - 'tests/test-worker.ss' - push: - branches: [master] - paths: - - '.github/workflows/platform-sandbox.yml' - - 'lib/std/os/**' - - 'lib/std/security/**' - - 'tests/test-seatbelt.ss' - - 'tests/test-worker.ss' - -jobs: - macos-seatbelt: - runs-on: macos-14 - steps: - - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1 - - - name: Build Scheme libraries - run: make build - - - name: Run Seatbelt platform tests - run: | - .chez/bin/scheme --libdirs lib:vendor/jsqlite/src --script tests/test-seatbelt.ss - .chez/bin/scheme --libdirs lib:vendor/jsqlite/src --script tests/test-worker.ss deleted file mode 100644 --- a/.github/workflows/security-baseline.yml +++ /dev/null @@ -1,35 +0,0 @@ -name: Security Baseline - -on: - push: - branches: [main, master] - pull_request: - workflow_dispatch: - -permissions: - contents: read - -jobs: - baseline: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1 - - - name: Required release files - run: | - set -eu - test -f LICENSE - test -f SECURITY.md - test -f .gitignore - find . -maxdepth 1 -iname "README*" -type f | grep -q . - - - name: High-confidence secret scan - run: | - set -eu - pattern="(BEGIN (RSA|OPENSSH|EC|DSA|PRIVATE) KEY|ghp_[A-Za-z0-9_]{20,}|github_pat_[A-Za-z0-9_]{20,}|sk-(ant-api03|proj|svcacct)-[A-Za-z0-9_-]{30,}|AKIA[0-9A-Z]{16})" - matches="$(git grep -n -I -E "$pattern" -- . ":!*.png" ":!*.jpg" ":!*.jpeg" ":!*.gif" ":!*.so" ":!*.dylib" ":!*.o" ":!*.a" ":!*.boot" ":!*.tar.gz" || true)" - if [ -n "$matches" ]; then - echo "$matches" - echo "High-confidence secret pattern found." - exit 1 - fi --- a/AGENTS.md +++ b/AGENTS.md @@ -370,6 +370,19 @@ improved versions of the above. When working in a Jerboa project, **ONLY modify files in the current repo** unless the user explicitly names another path. +### Release Distribution: SourceHut Only + +**Never use GitHub Releases, GitHub release URLs, or GitHub as a fallback for +Jerboa release artifacts.** Jerboa's sole official release channel is attached +files on a versioned SourceHut git tag. Publish them with +`hut git -r ~lisp/jerboa artifact upload <file> --rev <tag>` (normally through +`make release-upload`) and download them from +`https://git.sr.ht/~lisp/jerboa/refs/download/<tag>/<artifact>`. + +Do not add a GitHub mirror or fallback when SourceHut delivery needs work; +repair or configure the SourceHut release path instead. See the SourceHut +manual: <https://man.sr.ht/git.sr.ht/#attaching-files-to-releases>. + Common sibling repos that exist but must NOT be touched without explicit instruction: - `~/mine/jerboa-mcp` — Legacy node MCP, superseded. The active MCP server now lives in THIS repo at `mcp/` + `data/`. Don't modify the legacy repo unless told. - `~/mine/jerboa-shell` — Only modify when user explicitly says to work there. --- a/docs/release-artifacts.md +++ b/docs/release-artifacts.md @@ -3,6 +3,21 @@ Jerboa publishes project-local toolchain tarballs for package repos that should build without cloning and compiling this repository first. +## Distribution Channel + +SourceHut git-tag artifacts are the only official release channel. Never +publish or download Jerboa release artifacts through GitHub Releases, including +as a mirror or fallback. Attach each signed release file to its versioned +SourceHut tag with `hut git -r ~lisp/jerboa artifact upload <file> --rev <tag>`; +`make release-upload` performs this for the complete release set. Consumers +download assets at: + +```text +https://git.sr.ht/~lisp/jerboa/refs/download/<tag>/<artifact> +``` + +See [SourceHut's release-artifact manual](https://man.sr.ht/git.sr.ht/#attaching-files-to-releases). + Each release target produces: ```text --- a/support/install.sh +++ b/support/install.sh @@ -192,19 +192,11 @@ esac file="jerboa-${version}-${target}.tar.gz" -# Release base URLs, tried in order. SourceHut is canonical, but the go-away -# anti-LLM proxy in front of git.sr.ht 404s anonymous scripted downloads of -# /refs/download/<tag>/<file>. GitHub Releases is an anonymous-CDN mirror of -# the exact same signed artifacts and serves as a fallback. Override with -# JERBOA_RELEASE_BASE (single URL) or JERBOA_RELEASE_BASES (space separated). +# Release base URL. SourceHut git-tag artifacts are the only release download +# channel. Override it with JERBOA_RELEASE_BASE when using an independently +# operated mirror. sourcehut_base="${repo_url}/refs/download/${version}" -github_base="https://github.com/ober/jerboa/releases/download/${version}" -default_bases="$sourcehut_base $github_base" -release_bases=${JERBOA_RELEASE_BASES:-${JERBOA_RELEASE_BASE:-$default_bases}} -case "$release_bases" in - *" "*) ;; # multi-base fallback path - *) release_bases="$release_bases $github_base" ;; # always keep mirror as last resort -esac +release_bases=${JERBOA_RELEASE_BASE:-$sourcehut_base} tmp_parent=$(choose_tmp_parent) tmp=$(mktemp -d "$tmp_parent/jerboa-install.XXXXXX") --- a/tests/test-supply-chain-policy.sh +++ b/tests/test-supply-chain-policy.sh @@ -50,15 +50,7 @@ awk -F '\t' ' ' support/container-dependencies.lock || fail 'container lock still has blocked release inputs' must_contain support/container-dependencies.lock 'https://static.rust-lang.org/rustup/archive/1.28.2/' -must_contain .github/workflows/build-macos-libs.yml 'container-inputs.sh fetch-git jerboa-shell' -must_contain .github/workflows/ci.yml 'support/container-inputs.sh check' -if [ "$(grep -F -- '--build-arg JERBOA_BASE_IMAGE="${{ steps.container-lock.outputs.base_image }}"' .github/workflows/ci.yml | wc -l | tr -d '[:space:]')" -ne 2 ]; then - fail 'container CI does not pass the authenticated base digest to every Podman build' -fi must_contain Makefile 'JERBOA_REQUIRE_RELEASE_SIGNATURE_VERIFICATION=1' -if grep -Eq 'git[[:space:]]+clone' .github/workflows/build-macos-libs.yml; then - fail 'macOS native build still clones a mutable jerboa-shell head' -fi if grep -Eq 'git[[:space:]]+(clone|pull)' lib/jerboa/registry.ss; then fail 'legacy package registry still resolves a mutable Git head' fi @@ -137,6 +129,23 @@ if grep -Eq 'sum_url|tar[[:space:]]+-xzf|curl' support/ensure-jerboa.sh; then fail 'project-local bootstrap bypasses the authenticated installer' fi +# Versioned Jerboa toolchains are published only as SourceHut git-tag +# artifacts. Keep the delivery path for macOS, Linux amd64, and FreeBSD amd64 +# free of GitHub release URLs and publication commands. +must_contain support/sourcehut-release-upload.sh 'hut git -r "$repo" artifact upload "$file" --rev "$version"' +for release_build in \ + .builds/release-linux-amd64.yml \ + .builds/release-freebsd-amd64.yml; do + must_contain "$release_build" 'make release-upload' + if grep -Eiq 'github.*release|releases/download|gh[[:space:]]+release' "$release_build"; then + fail "$release_build retains a GitHub release path" + fi +done +if grep -Eiq 'github.*release|releases/download|gh[[:space:]]+release' \ + support/install.sh support/sourcehut-release-upload.sh; then + fail 'Jerboa release delivery retains a GitHub release path' +fi + # Exercise the complete signed-manifest path with an ephemeral consumer key. command -v ssh-keygen >/dev/null 2>&1 || fail 'ssh-keygen is required for installer regression tests' command -v curl >/dev/null 2>&1 || fail 'curl is required for installer regression tests'