- TypeScript 91.8%
- JavaScript 3.6%
- Shell 2.8%
- Python 1.8%
| Filename | Latest commit message | Latest commit date |
|---|---|---|
|
|
||
| .forgejo/workflows | ||
| ai-review | ||
| appstore-metadata-sync | ||
| appstore-testflight | ||
| cargo-audit | ||
| cargo-get | ||
| cargo-publish-workspace | ||
| check-appwrite-storage | ||
| check-orphan-versions | ||
| ci-step-status | ||
| create-release-tag | ||
| detect-changes | ||
| detect-markers | ||
| dispatch-forgejo-workflow | ||
| download-artifact | ||
| download-file | ||
| download-resumable | ||
| e2e-image-smoke | ||
| examples | ||
| github_format | ||
| golangci-lint | ||
| google-play-metadata-sync | ||
| google-play-staged-rollout | ||
| helm-unittest | ||
| install-git-bash | ||
| intellitester | ||
| mint-appwrite-token | ||
| prune-appwrite-storage | ||
| pypi-publish-workspace | ||
| release-continue | ||
| release-orchestrator | ||
| release-service | ||
| resolve-version | ||
| retry | ||
| s3-cache | ||
| setup-android-sdk | ||
| setup-binaryen | ||
| setup-bun | ||
| setup-ccache | ||
| setup-container-runtime | ||
| setup-cuda-toolkit | ||
| setup-deno | ||
| setup-docker | ||
| setup-dotnet | ||
| setup-fastlane | ||
| setup-flutter | ||
| setup-go | ||
| setup-gradle | ||
| setup-helm | ||
| setup-java | ||
| setup-kind | ||
| setup-kotlin | ||
| setup-kubectl | ||
| setup-libclang | ||
| setup-msvc | ||
| setup-ninja | ||
| setup-node | ||
| setup-php | ||
| setup-pnpm | ||
| setup-podman | ||
| setup-python | ||
| setup-ruby | ||
| setup-rust | ||
| setup-sccache | ||
| setup-shell | ||
| setup-swift | ||
| setup-system-deps | ||
| setup-tauri-cli | ||
| setup-terraform | ||
| setup-uniffi-bindgen-go | ||
| setup-wasi-sdk | ||
| setup-zgit | ||
| setup-zig | ||
| setup-ztus | ||
| shared | ||
| sonarqube | ||
| stamp-versions | ||
| submit-appstore-review | ||
| tauri-build-android | ||
| tauri-build-ios | ||
| trivy | ||
| tus-upload | ||
| upload-appstore | ||
| upload-appwrite-storage | ||
| upload-artifact | ||
| upload-firebase-app-distribution | ||
| upload-google-play | ||
| verify-artifact | ||
| windows-sign-binaries | ||
| windows-trusted-signing | ||
| wrangler-deploy | ||
| zgit-workspace | ||
| zlayer-macos-daemon-pkg | ||
| .gitattributes | ||
| .gitignore | ||
| bun.lock | ||
| LICENSE | ||
| package.json | ||
| README.md | ||
| tsconfig.base.json | ||
actions
Actions for Forgejo runners because apparently they just cannot handle GitHub ones and I hate finding them
Language Setup Actions
setup-go
Install Go from official releases.
- uses: https://forge.blackleafdigital.com/Public/actions/setup-go@main
with:
go-version: '1.23' # optional, default: 1.23
cache: true # optional, default: true
setup-node
Install Node.js with package manager support.
- uses: https://forge.blackleafdigital.com/Public/actions/setup-node@main
with:
node-version: '22' # optional, default: 22
package-manager: pnpm # optional: npm, yarn, pnpm (default: npm)
cache: true # optional, default: true
setup-python
Install Python via uv (fast Python package manager).
- uses: https://forge.blackleafdigital.com/Public/actions/setup-python@main
with:
python-version: '3.12' # optional, default: 3.12
uv-version: latest # optional, default: latest
cache: true # optional, default: true
setup-rust
Install Rust toolchain via rustup with optional sccache integration.
- uses: https://forge.blackleafdigital.com/Public/actions/setup-rust@main
with:
toolchain: stable # optional, default: stable
components: rustfmt, clippy # optional
targets: x86_64-unknown-linux-musl # optional
With sccache + S3
- uses: https://forge.blackleafdigital.com/Public/actions/setup-rust@main
with:
components: rustfmt, clippy
sccache: true
sccache-s3-bucket: ${{ secrets.S3_BUCKET }}
sccache-s3-endpoint: https://${{ secrets.S3_ENDPOINT }}
sccache-s3-region: ${{ secrets.S3_REGION }}
sccache-s3-access-key-id: ${{ secrets.S3_ACCESS_KEY }}
sccache-s3-secret-access-key: ${{ secrets.S3_ACCESS_SECRET }}
sccache-key-prefix: sccache/myproject
setup-bun
Install Bun JavaScript runtime.
- uses: https://forge.blackleafdigital.com/Public/actions/setup-bun@main
with:
bun-version: latest # optional, default: latest
setup-deno
Install Deno JavaScript/TypeScript runtime.
- uses: https://forge.blackleafdigital.com/Public/actions/setup-deno@main
with:
deno-version: latest # optional, default: latest
setup-java
Install Java/JDK via Eclipse Temurin (Adoptium).
- uses: https://forge.blackleafdigital.com/Public/actions/setup-java@main
with:
java-version: '21' # optional, default: 21
distribution: temurin # optional, default: temurin
setup-dotnet
Install .NET SDK via official Microsoft installer.
- uses: https://forge.blackleafdigital.com/Public/actions/setup-dotnet@main
with:
dotnet-version: '8.0' # optional, default: 8.0
setup-zig
Install Zig compiler.
- uses: https://forge.blackleafdigital.com/Public/actions/setup-zig@main
with:
zig-version: '0.13.0' # optional, default: 0.13.0 (or 'master')
setup-swift
Install Swift toolchain.
- uses: https://forge.blackleafdigital.com/Public/actions/setup-swift@main
with:
swift-version: '5.10' # optional, default: 5.10
Tool Setup Actions
setup-kind
Install Kind (Kubernetes in Docker) with optional cluster creation.
- uses: https://forge.blackleafdigital.com/Public/actions/setup-kind@main
with:
kind-version: v0.24.0 # optional, default: v0.24.0
cluster-name: kind # optional, default: kind
wait: '120s' # optional, default: 120s
create-cluster: true # optional, default: true
setup-kubectl
Install kubectl CLI.
- uses: https://forge.blackleafdigital.com/Public/actions/setup-kubectl@main
with:
kubectl-version: stable # optional, default: stable (latest)
setup-helm
Install Helm package manager for Kubernetes.
- uses: https://forge.blackleafdigital.com/Public/actions/setup-helm@main
with:
helm-version: latest # optional, default: latest
setup-terraform
Install Terraform from HashiCorp.
- uses: https://forge.blackleafdigital.com/Public/actions/setup-terraform@main
with:
terraform-version: latest # optional, default: latest
setup-docker
Install Docker (Linux only, macOS requires Docker Desktop).
- uses: https://forge.blackleafdigital.com/Public/actions/setup-docker@main
with:
docker-version: latest # optional, default: latest
setup-podman
Install Podman container engine.
- uses: https://forge.blackleafdigital.com/Public/actions/setup-podman@main
with:
podman-version: latest # optional, default: latest (system package)
setup-sccache
Standalone sccache setup with optional S3 backend.
- uses: https://forge.blackleafdigital.com/Public/actions/setup-sccache@main
with:
version: v0.8.1 # optional
bucket: ${{ secrets.S3_BUCKET }}
endpoint: https://${{ secrets.S3_ENDPOINT }}
region: ${{ secrets.S3_REGION }}
access-key: ${{ secrets.S3_ACCESS_KEY }}
secret-key: ${{ secrets.S3_ACCESS_SECRET }}
key-prefix: sccache/myproject
setup-zgit
Download the prebuilt zgit CLI from a zGit release and add it to PATH. Resolves
latest (or a pinned v tag) via the Forgejo releases API and selects the bare
binary for the runner OS+arch (x86_64-unknown-linux-gnu,
aarch64-unknown-linux-gnu, aarch64-apple-darwin,
x86_64-pc-windows-msvc.exe). zGit is a private repo, so a Forgejo token is
required for both the release lookup and the asset download.
- uses: https://forge.blackleafdigital.com/Public/actions/setup-zgit@main
with:
version: latest # optional, default: latest (or a tag like v0.0.12)
forgejo-url: https://forge.blackleafdigital.com # optional
repo: BlackLeafDigital/zGit # optional
token: ${{ secrets.FORGEJO_TOKEN }} # required: zGit is private
registries: '[{"name":"zreg","index":"sparse+https://registry.blackleafdigital.com/cargo/","token":"${{ secrets.ZREGISTRY_TOKEN }}"}]' # optional; only the source-build fallback needs it
# outputs: cli-path, resolved-tag
When no prebuilt asset exists for the runner (currently macOS-arm64 and
Windows-arm64, whose release legs aren't attached), this action builds zgit
from source (cargo build -p zgit-cli), which pulls zparse-grammars from the
private zreg cargo registry and 401s without a token. Pass registries — a JSON
array of {"name","index","token"}, the same shape setup-rust accepts — to
authenticate that build. Only each entry's token is load-bearing (zGit's own
.cargo/config.toml already declares the indexes + the cargo:token provider);
index is accepted for setup-rust parity. This makes the source-build
order-independent of any setup-rust step. Leave it empty on platforms that have
a prebuilt binary. Parsing needs jq.
zgit-workspace
Put a zGit Project's members on disk in one step: installs zgit (via
setup-zgit), hard-verifies the super-repo is at the run commit, then
zgit project sync --frozen. Replaces the hand-rolled materialize/verify shell
scripts every zGit-Project repo used to duplicate.
- uses: actions/checkout@v4
- uses: https://forge.blackleafdigital.com/Public/actions/zgit-workspace@main
with:
token: ${{ secrets.FORGEJO_TOKEN }} # required: member repos are private
sha: ${{ github.sha }} # optional, default: github.sha
working-directory: . # optional, default: . (dir holding .zproject.toml)
version: latest # optional, default: latest
forgejo-url: https://forge.blackleafdigital.com # optional
repo: BlackLeafDigital/zGit # optional
heal-global-git-config: 'true' # optional, default: true
registries: '[{"name":"zreg","index":"sparse+https://registry.blackleafdigital.com/cargo/","token":"${{ secrets.ZREGISTRY_TOKEN }}"}]' # optional; passed through to setup-zgit's source-build
# outputs: member-count, declared-count, sync-json, zgit-version
Fails the build (never warns) when: the token is empty, git rev-parse HEAD
is not sha — the stale-warm-workspace failure mode that once shipped a binary
built from a 19-commit-old tree — or fewer members land than .zproject.toml
declares.
--frozen clones absent members so a cold runner works, never pulls present
ones so a warm runner does no network I/O, and treats any lock/pin drift as a
hard error. The token is passed through git's GIT_CONFIG_COUNT env protocol —
never in a URL, in argv, or in a persisted config file — and is scoped to the
forge host only. registries is forwarded verbatim to the setup-zgit step so
the source-build fallback authenticates the private cargo registry (see
setup-zgit above).
Submodule pin enforcement. After sync, a final step verifies every
submodule-backed member is at its committed gitlink — the 160000 SHA the
super-repo's tree records (git rev-parse HEAD:<path>), git's authoritative pin —
re-fetching from the authoritative remote and hard-checking-out the exact commit
if a warm/stale clone trails it. It enforces the gitlink, not the
.zproject.lock submodule rows: the gitlink is updated automatically on every
meta-repo commit and cannot drift, whereas a lock's submodule rows are a derived
mirror that could lag and drag a build backward. (A member with no initialized
.git is refused, not enforced, so bare submodule dirs can't leak git ops into
the super-repo.)
Windows: every
run:step here isshell: bash. On a Windows host executor with no bash on PATH, runhttps://forge.blackleafdigital.com/Public/actions/install-git-bash@mainfirst — otherwise every step of this action fails to launch.
Security & Quality Actions
cargo-get
Extract metadata (version, name, description, authors, etc.) from Cargo.toml without needing Rust installed. Handles workspace inheritance ({ workspace = true } fields).
- uses: https://forge.blackleafdigital.com/Public/actions/cargo-get@main
with:
path: . # optional, default: . (dir or Cargo.toml path)
workspace-member: mycrate # optional: specific workspace member to query
Outputs include package_name, package_version, package_version_{major,minor,patch,pre,build}, package_edition, package_rust_version, package_authors, package_description, package_license, package_publish, workspace_members, is_workspace, and more.
cargo-publish-workspace
Idempotent, rate-limit-aware publisher for Rust workspaces. Skips crates already live at the target version on crates.io and retries each crate with per-crate exponential backoff (up to 5 minutes) on HTTP 429. Publishes in topological dependency order.
- uses: https://forge.blackleafdigital.com/Public/actions/cargo-publish-workspace@main
with:
version: ${{ needs.version.outputs.version }}
registry: crates-io # optional, default: crates-io
exclude: blazen-py,blazen-node # optional: comma-separated skip list
cargo-token: ${{ secrets.CARGO_REGISTRY_TOKEN }}
max-backoff-seconds: '300' # optional, default: 300
max-attempts-per-crate: '5' # optional, default: 5
Requires setup-rust to have run earlier in the job. Outputs published, skipped, total (comma-separated lists + count).
cargo-audit
Run security audit for Rust dependencies.
- uses: https://forge.blackleafdigital.com/Public/actions/cargo-audit@main
with:
deny: unmaintained # optional: fail on unmaintained crates
trivy
Run Trivy security scanner for vulnerabilities in code, containers, and dependencies.
- uses: https://forge.blackleafdigital.com/Public/actions/trivy@main
with:
scan-type: fs # optional: fs, image, repo (default: fs)
severity: CRITICAL,HIGH # optional (default: CRITICAL,HIGH)
exit-code: '1' # optional: fail on findings (default: 1)
ignore-unfixed: false # optional: ignore unpatched vulns
format: table # optional: table, json, sarif
Scan Docker image
- uses: https://forge.blackleafdigital.com/Public/actions/trivy@main
with:
scan-type: image
image-ref: myapp:latest
severity: CRITICAL
sonarqube
Run SonarQube code quality analysis.
- uses: https://forge.blackleafdigital.com/Public/actions/sonarqube@main
with:
host-url: ${{ secrets.SONAR_HOST_URL }}
token: ${{ secrets.SONAR_TOKEN }}
project-key: my-project
project-name: My Project # optional (defaults to project-key)
sources: src # optional (default: .)
exclusions: '**/*.test.ts' # optional: patterns to exclude
ai-review
AI-powered code review using Z.AI (GLM) or other OpenAI-compatible providers.
- uses: https://forge.blackleafdigital.com/Public/actions/ai-review@main
with:
api-key: ${{ secrets.ZAI_API_KEY }}
forgejo-token: ${{ secrets.FORGEJO_TOKEN }}
forgejo-url: https://forge.blackleafdigital.com
model: glm-4.6 # optional (default: glm-4.6)
base-url: https://api.z.ai/v1 # optional (default: Z.AI)
provider: openai # optional: openai, anthropic, ollama
With OpenAI
- uses: https://forge.blackleafdigital.com/Public/actions/ai-review@main
with:
api-key: ${{ secrets.OPENAI_API_KEY }}
forgejo-token: ${{ secrets.FORGEJO_TOKEN }}
forgejo-url: https://forge.blackleafdigital.com
base-url: https://api.openai.com/v1
model: gpt-4o
Mobile App Release
End-to-end Tauri 2.x mobile release pipeline — toolchain setup, signed
builds, store uploads, TestFlight / staged rollouts, metadata sync, and
App Review submission. See examples/release-mobile.yml
for the canonical workflow that chains these actions together (parallel
iOS + Android jobs with ci-step-status gating, zrelay-notify on
success/failure, and a Forgejo release at the end).
setup-fastlane
Install fastlane (and bundler) onto the runner. Requires Ruby on PATH
(run setup-ruby first). Detects a Gemfile and falls back to
gem install fastlane when none is present.
- uses: https://forge.blackleafdigital.com/Public/actions/setup-ruby@main
with:
ruby-version: '3.3'
- uses: https://forge.blackleafdigital.com/Public/actions/setup-fastlane@main
with:
fastlane-version: latest # optional, default: latest
bundler-version: latest # optional, default: latest
gemfile-dir: . # optional, default: .
setup-tauri-cli
Install the Tauri 2.x CLI via cargo-binstall (preferred, prebuilt) or
cargo install, with optional iOS / Android Rust target installation.
- uses: https://forge.blackleafdigital.com/Public/actions/setup-tauri-cli@main
with:
tauri-version: latest # optional, default: latest
target: ios # optional: desktop | ios | android | all
use-prebuilt: true # optional, default: true (prefer cargo-binstall)
tauri-build-ios
Build a Tauri 2.x iOS app and produce a signed IPA ready for
App Store / TestFlight / ad-hoc distribution. Outputs ipa-path,
bundle-version, and bundle-short-version.
- uses: https://forge.blackleafdigital.com/Public/actions/tauri-build-ios@main
with:
bundle-id: com.blackleaf.imaige
code-sign-identity: ${{ secrets.IOS_CODE_SIGN_IDENTITY }}
provisioning-profile-name: ${{ secrets.IOS_PROVISIONING_PROFILE_NAME }}
team-id: ${{ secrets.IOS_TEAM_ID }}
target: aarch64-apple-ios # optional, default: aarch64-apple-ios
export-method: app-store # optional: app-store | ad-hoc | enterprise | development
tauri-build-android
Build a signed Android AAB (and optional APK) from a Tauri 2.x project
using the Tauri CLI + Gradle. Decodes a base64 keystore on the fly.
Outputs aab-path, apk-path, version-code, version-name.
- uses: https://forge.blackleafdigital.com/Public/actions/tauri-build-android@main
with:
package-name: com.blackleaf.imaige
keystore-base64: ${{ secrets.ANDROID_KEYSTORE_BASE64 }}
keystore-password: ${{ secrets.ANDROID_KEYSTORE_PASSWORD }}
key-alias: ${{ secrets.ANDROID_KEY_ALIAS }}
key-password: ${{ secrets.ANDROID_KEY_PASSWORD }}
targets: aarch64-linux-android # optional, CSV of Android Rust targets
build-apk: false # optional: also produce a signed APK
upload-appstore
Upload an IPA to App Store Connect (TestFlight) using API-key
authentication. With wait-for-processing: true it polls App Store
Connect until the build reaches VALID (or fails) and exposes
build-id + processing-state for downstream TestFlight / review
steps. Always emits bundle-version and bundle-short-version parsed
from the IPA.
- uses: https://forge.blackleafdigital.com/Public/actions/upload-appstore@main
with:
ipa-path: ${{ steps.build-ios.outputs.ipa-path }}
api-key-id: ${{ secrets.APP_STORE_CONNECT_API_KEY_ID }}
issuer-id: ${{ secrets.APP_STORE_CONNECT_ISSUER_ID }}
api-private-key: ${{ secrets.APP_STORE_CONNECT_API_PRIVATE_KEY }}
wait-for-processing: 'true' # optional, default: false
timeout-minutes: '60' # optional, default: 60
poll-interval-seconds: '30' # optional, default: 30
appstore-testflight
Attach a previously-uploaded build to TestFlight beta groups, set what-to-test localizations, toggle auto-notify, and optionally submit for external beta review.
- uses: https://forge.blackleafdigital.com/Public/actions/appstore-testflight@main
with:
api-key-id: ${{ secrets.APP_STORE_CONNECT_API_KEY_ID }}
issuer-id: ${{ secrets.APP_STORE_CONNECT_ISSUER_ID }}
api-private-key: ${{ secrets.APP_STORE_CONNECT_API_PRIVATE_KEY }}
bundle-id: com.blackleaf.imaige
build-version: ${{ steps.build-ios.outputs.bundle-version }}
beta-groups: 'Internal QA,External Beta'
submit-for-beta-review: auto # optional: true | false | auto
appstore-metadata-sync
Sync App Store Connect metadata, screenshots, and app preview videos
via fastlane deliver. Requires setup-fastlane to have run earlier
in the job. Reads the standard fastlane/metadata + fastlane/screenshots
directory layout.
- uses: https://forge.blackleafdigital.com/Public/actions/appstore-metadata-sync@main
with:
api-key-id: ${{ secrets.APP_STORE_CONNECT_API_KEY_ID }}
issuer-id: ${{ secrets.APP_STORE_CONNECT_ISSUER_ID }}
api-private-key: ${{ secrets.APP_STORE_CONNECT_API_PRIVATE_KEY }}
app-identifier: com.blackleaf.imaige
version-string: 1.2.3 # optional: bump to / target this version
skip-screenshots: false # optional, default: false
skip-metadata: false # optional, default: false
submit-appstore-review
Submit an App Store Connect version for review via the App Store Connect API. Supports auto-release on approval, phased rollout, and per-locale "what's new" text.
- uses: https://forge.blackleafdigital.com/Public/actions/submit-appstore-review@main
with:
api-key-id: ${{ secrets.APP_STORE_CONNECT_API_KEY_ID }}
issuer-id: ${{ secrets.APP_STORE_CONNECT_ISSUER_ID }}
api-private-key: ${{ secrets.APP_STORE_CONNECT_API_PRIVATE_KEY }}
bundle-id: com.blackleaf.imaige
version-string: 1.2.3
build-version: ${{ steps.build-ios.outputs.bundle-version }}
auto-release: 'true' # optional, default: true (AFTER_APPROVAL)
phased-release: 'false' # optional, default: false (7-day phased rollout)
upload-google-play
Upload an AAB to Google Play via the Developer API using a service
account. Supports release-track selection, staged rollout with a
user-fraction, per-locale release notes (JSON), and optional
ProGuard/R8 mapping file upload after the bundle upload.
- uses: https://forge.blackleafdigital.com/Public/actions/upload-google-play@main
with:
aab-path: ${{ steps.build-android.outputs.aab-path }}
package-name: com.blackleaf.imaige
service-account-json: ${{ secrets.GOOGLE_PLAY_SERVICE_ACCOUNT_JSON }}
track: internal # optional: internal | alpha | beta | production
user-fraction: '0.10' # optional: start a staged rollout at 10%
release-notes-json: '[{"language":"en-US","text":"Bug fixes."}]' # optional
mapping-file: app/build/outputs/mapping/release/mapping.txt # optional
google-play-staged-rollout
Adjust an existing Google Play release's staged-rollout userFraction
and status (set / halt / resume / complete) without re-uploading
the bundle. Useful for promoting an internal upload to a wider rollout
or pausing a rollout that's misbehaving.
- uses: https://forge.blackleafdigital.com/Public/actions/google-play-staged-rollout@main
with:
service-account-json: ${{ secrets.GOOGLE_PLAY_SERVICE_ACCOUNT_JSON }}
package-name: com.blackleaf.imaige
track: production
action: set # set | halt | resume | complete
user-fraction: '0.10' # required for set / resume
google-play-metadata-sync
Sync per-locale Google Play store listings (title, short / full
description, video URL) and image assets (icon, feature graphic,
phone / tablet / TV / wear screenshots) via the Play Developer API v3.
Reads the fastlane/metadata/android/<locale>/... directory layout.
- uses: https://forge.blackleafdigital.com/Public/actions/google-play-metadata-sync@main
with:
service-account-json: ${{ secrets.GOOGLE_PLAY_SERVICE_ACCOUNT_JSON }}
package-name: com.blackleaf.imaige
listings-dir: ./fastlane/metadata/android # optional, default shown
image-types: 'phoneScreenshots,featureGraphic,icon' # optional
CI / Release Orchestration
detect-markers
Parse commit-message markers into job-gating outputs. Single source of truth for
the house marker convention — replaces the inline contains(...)/bash that every
repo used to duplicate.
- id: m
uses: https://forge.blackleafdigital.com/Public/actions/detect-markers@main
with:
message: ${{ github.event.head_commit.message }} # push event
# message: ${{ github.event.workflow_run.head_commit.message }} # workflow_run
# default-bump: patch # optional
# subject-only: true # optional — see below
⚠️ The body arms the marker — and subject-only: is the fix
Every marker test is a substring/regex match over the whole string handed to
the action. When message: is empty the action falls back to git log -1, and
that fallback defaults to --pretty=%B — subject and body. So a commit
whose body merely mentions a marker as prose arms it.
This is not theoretical. A Blazen commit that documented [release], [purge]
and [v0.8.0] in its body parsed as version=0.8.0 purge=true; only the
[skip] in its subject held release at false. That repo's release chain walks
itself to a crates.io publish, which is permanent and un-replaceable.
subject-only: true # fallback reads `--pretty=%s` (subject) not `%B`
- Default is
false— today's exact behaviour, unchanged for every existing caller. This input is purely opt-in. - It affects only the
git logfallback. A non-emptymessage:is always parsed verbatim, whateversubject-onlyis set to — so a caller that passes${{ github.event.head_commit.message }}(the full message, body included) gets no protection from this input; it must pass a subject instead, or switch tomessage: ''+subject-only: true. - Truthy spellings:
true/yes/on/1, any case. Anything else is false, so a typo fails open to today's behaviour, never accidentally-on. - The step log names the source it parsed (
input/%s/%B), so a run is self-evidencing.
The message: '' trap. The fallback is keyed on the value being empty,
not on the input being absent — so an explicitly-passed message: '' re-opens
it. That is the documented ZLayer auto-tag.yaml idiom (it is how a dispatched
workflow re-derives markers off the checked-out sha), and it is deliberately
preserved. If you use it, pair it with subject-only: true.
Regardless of any of the above, the standing rule holds: never write a bracketed
marker literally in a commit message you do not intend to fire — not even in the
body. Break it up ([re + lease]) or spell it out.
| Marker | Output | Meaning |
|---|---|---|
[release] (or [release minor] / [release:major]) |
release=true |
opt into the publish/release chain |
[np] / [no-publish] |
no-publish=true → release=false |
suppress publishing |
[skip] / [skip-checks] / [skip-ci] / [skip ci] / [ci skip] |
skip=true → release=false |
skip CI/checks |
[fast] |
fast=true |
skip test/lint/audit jobs; release still fires |
[purge] |
purge=true |
force fresh rebuild / invalidate cached artifacts |
[major] / [minor] / [patch] |
bump=<x> |
bump type (default patch) |
[vX.Y.Z] (opt. -pre) |
version=X.Y.Z[-pre] |
explicit version override |
| push event + release | dry-run=false |
live publish; otherwise true |
Outputs: release, no-publish, skip, fast, purge, bump, version, dry-run.
Canonical marker-driven release pattern (push-triggered ci.yml → dispatch
release.yml, since Forgejo's on: workflow_run hook fires unreliably):
dispatch-release:
runs-on: ubuntu-latest
needs: [lint, test] # gate on green CI
if: success() && github.event_name == 'push' && github.ref == 'refs/heads/main'
steps:
- uses: actions/checkout@v4
- id: m
uses: https://forge.blackleafdigital.com/Public/actions/detect-markers@main
with:
message: ${{ github.event.head_commit.message }}
- if: steps.m.outputs.release == 'true'
uses: https://forge.blackleafdigital.com/Public/actions/dispatch-forgejo-workflow@main
with:
workflow: release.yml
ref: main
token: ${{ secrets.FORGEJO_ACTIONS_TOKEN }}
inputs-json: >-
{"version":"${{ steps.m.outputs.version }}","bump":"${{ steps.m.outputs.bump }}","dry_run":"false"}
dispatch-forgejo-workflow
Fire a Forgejo workflow_dispatch via the REST API (reliable replacement for the
flaky on: workflow_run cross-workflow trigger). Optionally polls for completion.
- uses: https://forge.blackleafdigital.com/Public/actions/dispatch-forgejo-workflow@main
with:
workflow: release.yml # required — workflow filename
ref: main # optional, default: main
inputs-json: '{"dry_run":"false"}' # optional JSON of inputs
token: ${{ secrets.FORGEJO_ACTIONS_TOKEN }} # required
wait: 'false' # optional — poll until run completes