Forgejo's missing essentials: cache, artifacts, toolchains, and builds without github.com
Find a file
Stephen Way cba5ebdef5
Add version-bump and fj-fanout-dispatch to the bundle
Two more from the ideas backlog, both CI-green at v1:

- fjord-version-bump-action: monotonic build number (Forgejo variable
  counter / GITHUB_RUN_NUMBER / timestamp) + version name, optionally
  written into build.gradle/Info.plist. App Store Connect and Play
  reject reused build numbers.
- fj-fanout-dispatch-action: one push, N downstream builds.
  workflow_dispatch across many repos with fj, templated inputs,
  per-target rollup. Dispatch-only for now; join-on-results is a
  follow-up.

Lists both on the bundle (mobile + fj CLI sections); marks them SHIPPED
in docs/IDEAS.md. Backlog is now down to the two infra-dependent
moonshots (deploy-console, biometric-approval).
2026-06-01 19:44:28 -07:00
.forgejo/workflows Point artifacts backend at the Helsinki bucket in backend-smoke 2026-05-31 09:34:50 -07:00
benchmarks Refresh bench results from run #1904 2026-06-01 14:12:12 +00:00
docs Add version-bump and fj-fanout-dispatch to the bundle 2026-06-01 19:44:28 -07:00
.editorconfig Brand the Fjord Actions bundle: README, compat matrix, benchmarks 2026-05-29 21:05:40 -07:00
.gitignore Brand the Fjord Actions bundle: README, compat matrix, benchmarks 2026-05-29 21:05:40 -07:00
CHANGELOG.md Add version-bump and fj-fanout-dispatch to the bundle 2026-06-01 19:44:28 -07:00
CONTRIBUTING.md Brand the Fjord Actions bundle: README, compat matrix, benchmarks 2026-05-29 21:05:40 -07:00
LICENSE Brand the Fjord Actions bundle: README, compat matrix, benchmarks 2026-05-29 21:05:40 -07:00
README.md Add version-bump and fj-fanout-dispatch to the bundle 2026-06-01 19:44:28 -07:00
SECURITY.md Brand the Fjord Actions bundle: README, compat matrix, benchmarks 2026-05-29 21:05:40 -07:00

Fjord Actions

Forgejo's missing essentials. A drop-in bundle of the actions your workflows already use, with storage you control and no runtime dependency on github.com.

Built for self-hosted Forgejo runners. Same with: surface as the GitHub originals, configured through environment variables instead of hosted services.

What's in the bundle

Component Repo Replaces One-liner
Cache rasterstate/cache-action actions/cache S3-compatible or filesystem cache. Multipart, conditional writes, segmented downloads.
Artifacts rasterstate/upload-artifact-action + rasterstate/download-artifact-action actions/upload-artifact + actions/download-artifact Named artifacts on your storage. Cross-job, cross-run, cross-repo.
Node rasterstate/setup-node-action (with optional rasterstate/setup-pnpm-action) actions/setup-node (+ pnpm/action-setup) Install from nodejs.org (or your mirror), SHASUMS-verified. npm/pnpm/yarn cache. pnpm at a pinned or packageManager version.
Python rasterstate/setup-python-action actions/setup-python CPython/PyPy via uv (python-build-standalone), configurable mirror. pip/pipenv/poetry cache.
Go rasterstate/setup-go-action actions/setup-go Install from go.dev/dl (or your mirror), sha256-verified. Module + build cache.
Rust rasterstate/setup-rust-action + rasterstate/rust-cache-action (with optional rasterstate/sccache-action) dtolnay/rust-toolchain + Swatinem/rust-cache (+ Mozilla-Actions/sccache-action) Install a toolchain via rustup (no GitHub release lookup); cargo registry, git deps, and target cache. Pair with sccache for cross-branch reuse.
Docker rasterstate/docker-build-action + rasterstate/setup-buildx-action docker/build-push-action + docker/setup-buildx-action docker buildx whose context never defaults to github.com, and a docker-container builder set up without a GitHub release download. Any OCI registry.

Seven build pillars, plus the automation actions below, one philosophy: what you check in is what runs, what you store is yours.

Workflow & repo automation

The same philosophy applied to release and repo-management actions: they talk to your Forgejo API, not api.github.com, so a Forgejo secrets.GITHUB_TOKEN just works (no PAT).

Component Repo Replaces One-liner
Release rasterstate/forgejo-release-action softprops/action-gh-release Create/update a release and upload assets via the Forgejo API. No hand-rolled curl.
Script rasterstate/forgejo-script actions/github-script Inline JS with a Forgejo api client, context, and core.
Pull requests rasterstate/create-pull-request-action peter-evans/create-pull-request Commit changes to a branch, push, open/update a PR.
Stale rasterstate/forgejo-stale-action actions/stale Mark and close stale issues/PRs on a schedule.
Labeler rasterstate/forgejo-labeler-action actions/labeler Label PRs by changed-file globs.

Fjord Pages

Publish a static site to Fjord Pages, the managed static hosting that ships with a Fjord forge, straight from a workflow.

Component Repo Replaces One-liner
Pages rasterstate/pages-deploy-action actions/deploy-pages Build (optional) and deploy to Fjord Pages: begin → stream files → commit.

Phone-in-the-loop & mobile

Things GitHub Actions structurally can't do on hardware you control: push CI to your phone, gate a deploy on a tap, and sign Apple artifacts on your own macs. The first two ride the Fjord relay; the third needs a self-hosted mac runner.

Component Repo Replaces One-liner
Notify rasterstate/fjord-notify-action (no GitHub equivalent) Push a rich CI notification to the Fjord mobile app, with a Forgejo comment fallback.
Approval gate rasterstate/fjord-approval-gate-action GitHub environment protection rules (self-hostable) Pause a deploy until an authorized human approves from the app or a /approve comment. Fail-closed.
Apple codesign rasterstate/apple-codesign-action hand-rolled keychain + codesign + notarytool Sign and notarize macOS/iOS artifacts on a self-hosted mac runner, with a throwaway keychain.
Distribute rasterstate/fjord-distribute-action (no GitHub equivalent) Self-hosted TestFlight: upload a signed .ipa/.apk to your S3, build the install manifest + QR, push "tap to install" to the app.
Version bump rasterstate/fjord-version-bump-action (no GitHub equivalent) A monotonic build number (Forgejo variable counter / run-number / timestamp) + version name, optionally written into build.gradle/Info.plist.

More sketched but unbuilt: see docs/IDEAS.md (a live mobile deploy console, biometric-signed approvals, more of the fj-on-the-runner family).

fj CLI on the runner

Component Repo Replaces One-liner
Setup fj rasterstate/setup-fj-action (no GitHub equivalent) Install a checksum-verified fj CLI from your Forgejo releases and auth it, so steps can fj pr/fj run/fj api.
Fan-out dispatch rasterstate/fj-fanout-dispatch-action (no GitHub equivalent) One push, N downstream builds: workflow_dispatch across many repos with fj, templated inputs, per-target rollup.

Quick start

jobs:
  build:
    runs-on: [self-hosted, Linux]
    env:
      # One backend, used by Cache, Artifacts, and the cache step inside Setup-*.
      RASTER_CACHE_S3_BUCKET: ci-cache
      RASTER_CACHE_S3_ENDPOINT: https://fsn1.your-objectstorage.com
      RASTER_CACHE_S3_REGION: fsn1
      RASTER_CACHE_S3_ACCESS_KEY_ID: ${{ secrets.CACHE_S3_KEY_ID }}
      RASTER_CACHE_S3_SECRET_ACCESS_KEY: ${{ secrets.CACHE_S3_SECRET }}
      RASTER_ARTIFACTS_S3_BUCKET: ci-artifacts
      RASTER_ARTIFACTS_S3_ENDPOINT: https://fsn1.your-objectstorage.com
      RASTER_ARTIFACTS_S3_REGION: fsn1
      RASTER_ARTIFACTS_S3_ACCESS_KEY_ID: ${{ secrets.ARTIFACTS_S3_KEY_ID }}
      RASTER_ARTIFACTS_S3_SECRET_ACCESS_KEY: ${{ secrets.ARTIFACTS_S3_SECRET }}
    steps:
      - uses: actions/checkout@v6
      - uses: https://rasterhub.com/rasterstate/setup-node-action@v1
        with:
          node-version: '20'
          cache: npm
      - run: npm ci && npm run build
      - uses: https://rasterhub.com/rasterstate/upload-artifact-action@v1
        with:
          name: dist
          path: build/**

Compatibility matrix

Drop-in replacements. Inputs and outputs match unless noted in the per-repo MIGRATION.md.

GitHub Action Fjord Replacement Migration notes
actions/cache rasterstate/cache-action migration
actions/upload-artifact rasterstate/upload-artifact-action migration
actions/download-artifact rasterstate/download-artifact-action migration
actions/setup-node rasterstate/setup-node-action migration
pnpm/action-setup rasterstate/setup-pnpm-action migration
actions/setup-python rasterstate/setup-python-action migration
actions/setup-go rasterstate/setup-go-action migration
dtolnay/rust-toolchain rasterstate/setup-rust-action migration
Swatinem/rust-cache rasterstate/rust-cache-action migration
docker/build-push-action rasterstate/docker-build-action migration
docker/setup-buildx-action rasterstate/setup-buildx-action migration
Mozilla-Actions/sccache-action (optional) rasterstate/sccache-action Compiler cache for the Rust pillar.
softprops/action-gh-release rasterstate/forgejo-release-action migration
actions/github-script rasterstate/forgejo-script migration
peter-evans/create-pull-request rasterstate/create-pull-request-action migration
actions/stale rasterstate/forgejo-stale-action migration
actions/labeler rasterstate/forgejo-labeler-action migration

Benchmarks

The table below is regenerated by .forgejo/workflows/bench.yml on a Forgejo runner. Methodology lives in benchmarks/README.md; the GitHub Actions column is filled in manually because measuring it requires a github-hosted runner.

Last refreshed by .forgejo/workflows/bench.yml on a Forgejo runner. Backend: filesystem on local SSD unless RASTER_CACHE_S3* secrets are set._

Workload Vanilla Forgejo (cold) Fjord Actions (cold) Fjord Actions (warm) GitHub Actions
Rust 18.7s 17.1s 0.2s TBD
Node 10.6s 10.3s 6.7s TBD
Go 38.8s 36.2s 2.2s TBD

Trigger the workflow with Run workflow on the bench job, or wait for the weekly Monday morning run. New numbers land as a Refresh bench results from run #<id> commit on main.

Why Fjord Actions

  • No github.com runtime. Nothing in your hot path depends on a service you don't control. Cache, artifacts, and toolchain downloads all hit storage and mirrors you choose.
  • No PAT. The Forgejo secrets.GITHUB_TOKEN is a Forgejo token; upstream actions that call api.github.com to discover releases fail there. Every Fjord action installs from the project's official distribution (or your mirror) and verifies checksums.
  • Drop-in. The with: surface mirrors the GitHub originals. Most workflows port by changing the uses: line and adding backend env: once at the job level.
  • What you check in is what runs. Composite shell or node20-from-source; no bundled dist/ blobs, no committed node_modules.
  • One storage backend. Cache, artifacts, and toolchain caches share the same S3-compatible or filesystem store. Configure it once.

Versioning

Each component repo carries its own v1 (moving major) and v1.x.y semver tags. Workflows reference @v1 to ride patch releases; pin to a v1.x.y if you want bytewise reproducibility.

License

MIT, on every component repo and on this bundle.

Contributing

Issues, ideas, and pull requests belong on the relevant component repo. This repo is the brand, the compatibility matrix, and the benchmarks.