| actions | ||
| README.md | ||
ci-actions
Shared Forgejo Actions composite actions
for the bit-crafts org. Keeping them here (DRY) means every repo's release.yml calls the
same audited, injection-safe publish/release logic instead of copy-pasting shell.
Two actions:
| Action | Purpose |
|---|---|
actions/publish-deb |
Upload .deb package(s) to this instance's Debian registry (idempotent delete-then-upload). |
actions/forgejo-release |
Create a notes-only Forgejo Release for the current tag (marker only — binaries live in the registry). |
Using these actions (cross-repo)
Forgejo resolves cross-repo uses: by full URL. Reference an action by its absolute
URL on this instance and pin a ref:
- uses: https://git.bit-crafts.com/bit-crafts/ci-actions/actions/publish-deb@main
Pinning: consumers currently track
@main(mutable). For reproducible releases you can tag this repo (vN) and switch consumers to@vNor a commit SHA. Tracked as a TODO.
Security model (both actions)
All user-supplied inputs are bound to environment variables in the step's env: block and
referenced as "$VAR" inside run: — they are never interpolated into the shell body
(no ${{ inputs.x }} directly in run:). This blocks shell/command injection through crafted
input values. Both actions run with set -euo pipefail. forgejo-release builds its JSON
payload with python3 -c 'json.dumps(...)' reading from os.environ, so the body cannot break
out of the JSON. Endpoints are derived from ${{ github.server_url }} (the runner's own
instance URL) — no hardcoded IPs.
actions/publish-deb
Publishes one or more .deb files to the Debian package registry of this Forgejo instance.
For each matched file it DELETEs the existing (package, version, arch) (tolerating 404)
then uploads it — so re-running a release overwrites rather than 409-conflicting.
Inputs
| Input | Required | Default | Description |
|---|---|---|---|
token |
yes | — | PAT with write:package scope (e.g. secrets.PKG_TOKEN). The built-in github.token does not carry the package scope. |
path |
no | dist/*.deb |
Glob of .deb files to publish. |
owner |
no | bit-crafts |
Registry owner/org. |
user |
no | younes |
Auth username for the registry. |
distribution |
no | trixie |
Debian distribution (apt dists/<distribution>). |
component |
no | main |
Debian component. |
Fails the job if no file matches path. Prints a per-file delete/upload -> HTTP code summary.
Example
- name: Publish .deb to registry
uses: https://git.bit-crafts.com/bit-crafts/ci-actions/actions/publish-deb@main
with:
token: ${{ secrets.PKG_TOKEN }}
path: "dist/*.deb"
Consumers (apt): the registry is served at https://pkgs.bit-crafts.com →
deb https://pkgs.bit-crafts.com/api/packages/bit-crafts/debian trixie main (key at
.../debian/repository.key; one-line .list, not DEB822).
actions/forgejo-release
Creates a notes-only Forgejo Release for the tag that triggered the run. It attaches no
binary assets — the canonical artifacts are the .debs in the Debian registry; the Release
object is just a human-facing marker/changelog. It is non-fatal: on a non-2xx/409 response
it emits ::warning:: and the job still succeeds (the release is not load-bearing).
Inputs
| Input | Required | Default | Description |
|---|---|---|---|
token |
yes | — | Token with repo write. Pass the built-in ${{ github.token }}. |
user |
no | younes |
Auth username. |
body |
no | Automated release. Binaries are published to the Debian package registry. |
Release notes body. |
Behavior by HTTP status: 2xx → created · 409 → already exists (ok) · anything else → ::warning:: (job continues).
Example
- name: Create Forgejo release marker
uses: https://git.bit-crafts.com/bit-crafts/ci-actions/actions/forgejo-release@main
with:
token: ${{ github.token }}
body: "Automated release — my-project (.deb). Binary is published to the Debian package registry."
Combined release.yml (typical consumer)
name: release
on:
push:
tags: ["v*"]
concurrency:
group: release-${{ github.ref }}
cancel-in-progress: false # serialize the delete-then-upload to the registry
jobs:
package-publish:
runs-on: build-large
container: git.bit-crafts.com/bit-crafts/ci-base-c@sha256:<digest> # pin by digest for reproducibility
steps:
- uses: actions/checkout@v4
- run: |
set -euo pipefail
bash packaging/build-deb.sh "${GITHUB_REF_NAME#v}" # produces dist/*.deb
- uses: https://git.bit-crafts.com/bit-crafts/ci-actions/actions/publish-deb@main
with:
token: ${{ secrets.PKG_TOKEN }}
path: "dist/*.deb"
- uses: https://git.bit-crafts.com/bit-crafts/ci-actions/actions/forgejo-release@main
with:
token: ${{ github.token }}
Required secrets (org bit-crafts)
| Secret | Used by | Scope |
|---|---|---|
PKG_TOKEN |
publish-deb |
PAT write:package |
DEPLOY_KEY |
site deploy workflows (not these actions) | per-container SSH deploy key |
The release token (github.token) is provided automatically per run — no secret needed for forgejo-release.