{"id":50535488,"url":"https://github.com/arcuru/actions","last_synced_at":"2026-06-03T16:01:42.544Z","repository":{"id":358168460,"uuid":"1237049744","full_name":"arcuru/actions","owner":"arcuru","description":"Github Actions Helpers","archived":false,"fork":false,"pushed_at":"2026-05-16T02:24:53.000Z","size":34,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-05-16T04:40:55.427Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":null,"has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/arcuru.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-05-12T20:34:37.000Z","updated_at":"2026-05-16T02:24:56.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/arcuru/actions","commit_stats":null,"previous_names":["arcuru/actions"],"tags_count":2,"template":false,"template_full_name":null,"purl":"pkg:github/arcuru/actions","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/arcuru%2Factions","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/arcuru%2Factions/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/arcuru%2Factions/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/arcuru%2Factions/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/arcuru","download_url":"https://codeload.github.com/arcuru/actions/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/arcuru%2Factions/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":33872298,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-06-03T02:00:06.370Z","response_time":59,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2026-06-03T16:01:39.485Z","updated_at":"2026-06-03T16:01:42.538Z","avatar_url":"https://github.com/arcuru.png","language":null,"funding_links":[],"categories":[],"sub_categories":[],"readme":"# arcuru/actions\n\nShared GitHub Actions building blocks for the [`arcuru`](https://github.com/arcuru) repos.\n\nTwo kinds of things live here:\n\n- **Composite actions** under `.github/actions/` — small reusable steps callable from any workflow.\n- **Reusable workflows** under `.github/workflows/` — whole workflows callable via `workflow_call`, mostly the dependency-update automation.\n\nPinning is by full commit SHA, with a trailing version comment that matches the latest release tag.\n\n## Composite actions\n\n| Action | Purpose |\n|---|---|\n| [`setup-nix`](.github/actions/setup-nix/action.yml) | Install Nix with `nix-installer-action`, optionally enable Magic Nix Cache, optionally configure a custom binary cache (substituters / trusted keys / push), install `nix-fast-build`. |\n| [`setup-deps-branch`](.github/actions/setup-deps-branch/action.yml) | Create a new `deps/\u003cname\u003e` branch, or rebase an existing one onto `main`. Falls back to `reset --hard` on rebase conflict. |\n| [`commit-and-pr`](.github/actions/commit-and-pr/action.yml) | Stage, commit, push, and open or update a PR with `dependencies` + `on-hold` labels and a `hold-until: YYYY-MM-DD` body marker. |\n\nReference one from any workflow:\n\n```yaml\n- uses: arcuru/actions/.github/actions/setup-nix@\u003csha\u003e  # v0.1.0\n```\n\nThe trailing version comment is required — the `actions-update` workflow uses it to find the next release tag.\n\n### `setup-nix` inputs\n\n| Input | Default | Purpose |\n|---|---|---|\n| `enable-magic-cache` | `\"true\"` | Toggle the DeterminateSystems Magic Nix Cache step. Set to `\"false\"` if you only want a custom cache. |\n| `extra-substituters` | `\"\"` | Newline-separated substituter URLs appended to the Nix config (e.g. `https://cache.eidetica.dev`). |\n| `extra-trusted-public-keys` | `\"\"` | Newline-separated trusted public keys for those substituters. Required when `extra-substituters` is set. |\n| `signing-key` | `\"\"` | Nix store signing key PEM body. When paired with `push-target`, the action exposes a `push-args` output containing `nix-fast-build` flags for cache push. |\n| `push-target` | `\"\"` | Cache push destination URL (e.g. `s3://my-cache?region=auto\u0026endpoint=…`). |\n\nOutput `push-args` is empty unless both `signing-key` and `push-target` are set; pass it to `nix-fast-build` to push built paths back into the cache in the same step.\n\n## Reusable workflows\n\nAll six follow the same calling convention: each consumer repo ships a thin wrapper that owns the schedule, the wrapper calls the reusable workflow here.\n\n| Workflow | Trigger in wrapper | Secrets | What it does |\n|---|---|---|---|\n| [`cargo-update`](.github/workflows/cargo-update.yml) | `schedule` (monthly) | `PAT_TOKEN` | `cargo update` → PR for `Cargo.lock` |\n| [`flake-update`](.github/workflows/flake-update.yml) | `schedule` (monthly) | `PAT_TOKEN` | `nix flake update` → PR for `flake.lock` with per-input compare URLs |\n| [`actions-update`](.github/workflows/actions-update.yml) | `schedule` (monthly) | `PAT_TOKEN` | Bump every SHA-pinned `uses:` in `.github/workflows/` to the latest release tag |\n| [`security-audit`](.github/workflows/security-audit.yml) | `schedule` (daily) | — | `cargo deny check advisories`; opens a tracking issue on hit, closes it on resolution |\n| [`dependency-hold`](.github/workflows/dependency-hold.yml) | `pull_request` | — | Fails any PR on a `deps/*` branch that still has the `on-hold` label |\n| [`update-hold`](.github/workflows/update-hold.yml) | `schedule` (daily) | — | Removes `on-hold` once the PR's `hold-until: YYYY-MM-DD` marker has passed |\n| [`codeberg-mirror`](.github/workflows/codeberg-mirror.yml) | `push` | `ssh-private-key` | Mirror the caller repo to a Codeberg/Forgejo destination over SSH with ed25519 host-key pinning |\n\n### Common inputs\n\nEvery reusable workflow accepts these optional overrides (defaults preserve the simplest behaviour):\n\n| Input | Default | Purpose |\n|---|---|---|\n| `runs-on` | `ubuntu-latest` | Override the runner. Example: `ubicloud-standard-2`. |\n| `environment` | `\"\"` | Attach the job to a GitHub Actions environment so approval rules and env-scoped secrets apply. |\n\nNix-using workflows (cargo-update, flake-update, actions-update, security-audit) additionally accept:\n\n| Input | Default | Purpose |\n|---|---|---|\n| `enable-magic-cache` | `\"true\"` | Toggle DeterminateSystems Magic Nix Cache. |\n| `extra-substituters` | `\"\"` | Newline-separated extra substituter URLs. |\n| `extra-trusted-public-keys` | `\"\"` | Newline-separated trusted public keys. |\n\n### Wrapper examples\n\nDrop these into the consumer's `.github/workflows/` directory. Replace `\u003csha\u003e` with the current `arcuru/actions` commit SHA and `vX.Y.Z` with the matching tag.\n\n**`cargo-update.yml`** (also the pattern for `flake-update`, `actions-update`):\n\n```yaml\nname: \"Deps: Cargo Update\"\n\non:\n  schedule:\n    - cron: \"0 4 1 * *\"\n  workflow_dispatch:\n    inputs:\n      hold_days:\n        description: \"Days to hold before allowing merge\"\n        required: false\n        default: \"7\"\n        type: string\n\npermissions:\n  contents: read\n\njobs:\n  cargo-update:\n    uses: arcuru/actions/.github/workflows/cargo-update.yml@\u003csha\u003e  # vX.Y.Z\n    with:\n      hold-days: ${{ inputs.hold_days || '7' }}\n    secrets:\n      PAT_TOKEN: ${{ secrets.PAT_TOKEN }}\n```\n\n**Repo using a custom Nix cache** (eidetica-style):\n\n```yaml\njobs:\n  cargo-update:\n    uses: arcuru/actions/.github/workflows/cargo-update.yml@\u003csha\u003e  # vX.Y.Z\n    with:\n      runs-on: ubicloud-standard-2\n      environment: automation\n      enable-magic-cache: \"false\"\n      extra-substituters: https://cache.eidetica.dev\n      extra-trusted-public-keys: cache.eidetica.dev-1:eND5gRJlbnool3ZLCWT2H8kkygWS8JcsU76HYXbWPBI=\n    secrets:\n      PAT_TOKEN: ${{ secrets.PAT_TOKEN }}\n```\n\n**`security-audit.yml`** (also the pattern for `update-hold` — schedule-triggered, no secrets):\n\n```yaml\nname: \"Deps: Security Audit\"\n\non:\n  schedule:\n    - cron: \"0 6 * * *\"\n  workflow_dispatch:\n\npermissions:\n  contents: read\n\njobs:\n  audit:\n    uses: arcuru/actions/.github/workflows/security-audit.yml@\u003csha\u003e  # vX.Y.Z\n    secrets: inherit\n```\n\n**`dependency-hold.yml`** (PR-triggered):\n\n```yaml\nname: \"Deps: Hold Gate\"\n\non:\n  pull_request:\n    branches: [\"main\"]\n    types: [opened, synchronize, reopened, labeled, unlabeled]\n\npermissions:\n  contents: read\n\njobs:\n  hold:\n    uses: arcuru/actions/.github/workflows/dependency-hold.yml@\u003csha\u003e  # vX.Y.Z\n    secrets: inherit\n```\n\n**`codeberg-mirror.yml`** (push-triggered):\n\n```yaml\nname: \"Codeberg Sync\"\n\non:\n  push:\n    branches: [main]\n\npermissions:\n  contents: read\n\njobs:\n  mirror:\n    uses: arcuru/actions/.github/workflows/codeberg-mirror.yml@\u003csha\u003e  # vX.Y.Z\n    with:\n      environment: mirror\n      destination: git@codeberg.org:arcuru/\u003crepo\u003e.git\n    secrets:\n      ssh-private-key: ${{ secrets.GIT_SSH_PRIVATE_KEY }}\n```\n\n`codeberg-mirror` accepts `host`, `host-key`, and `host-key-algorithm` overrides for non-default forges or rotated keys. The destination repo must already exist on Codeberg; the deploy key for `secrets.ssh-private-key` must have write access. The mirror push uses `+refs/remotes/origin/*:refs/heads/*` with `--prune` scoped to that namespace, so deleted GitHub branches propagate to Codeberg without touching anything outside `refs/heads/*`.\n\n### Prerequisites in the consumer repo\n\n- `cargo-update` and `security-audit` need `nix develop --command cargo …` to work — i.e. a `flake.nix` with `cargo` (and for security-audit, `cargo-deny`) in the dev shell.\n- `flake-update` needs `flake.nix` + `flake.lock`.\n- `security-audit` needs `.config/deny.toml`.\n- `cargo-update` / `flake-update` / `actions-update` need a fine-grained `PAT_TOKEN` repo-level secret with `contents:write` + `pull-requests:write` on the calling repo. (The default `GITHUB_TOKEN` can't trigger downstream workflow runs, which would silently break the deps-hold check.)\n- The `on-hold` and `dependencies` labels need to exist in the repo (the deps PRs use them).\n- `Allow GitHub Actions to create and approve pull requests` must be enabled in Settings → Actions → General.\n\n## Security model\n\n- **No secrets stored here.** Every secret a workflow needs is passed in by the caller. The consumer's repo settings are the only place credentials live.\n- **`PAT_TOKEN` is scoped per consumer**, not shared. Each repo that wants the PR-creating deps automation needs its own fine-grained PAT covering only that repo, with the minimum scopes (`contents:write` + `pull-requests:write`).\n- **All `uses:` lines pin a full commit SHA**, with the version comment used by `actions-update` for bumps. Mutable tags like `@v1` are forbidden.\n- **No `${{ }}` interpolation inside `run:` blocks**: untrusted values reach the shell via `env:` only. This is enforced inside this repo and is the rule callers should follow too.\n- **Fork-fenced**: every workflow's privileged job has `if: github.repository_owner == 'arcuru'`. Forks running re-enabled copies of the workflow no-op cleanly.\n\n## Releases\n\nReleases are tagged from `main` as `vX.Y.Z`. Consumers should pin a full SHA *with* a matching version comment so the `actions-update` workflow can bump them.\n\nBreaking changes (input renames, removed secrets, schema changes) bump the major version. Most updates are SHA-pin bumps inside the reusable workflows or composite-action body changes — those don't require consumers to act.\n\n## Known limitations\n\n- `actions-update`'s regex parses the `OWNER/REPO@SHA # vX.Y.Z` shape used for everything but doesn't yet handle the path-prefixed `OWNER/REPO/PATH@SHA # vX.Y.Z` shape this repo uses for its own composite-action references inside the reusable workflows. Path-prefixed pins must be bumped by hand until the regex grows the second form. Filed as TODO inside the reusable `actions-update.yml`.\n- The `cargo-update` workflow assumes a single-package crate at the repo root (`Cargo.lock` only). Workspaces with multiple lockfiles need an extension.\n- `flake-update`'s per-input compare URL only works when the input source is a `github:` flake ref. Other types (`git+ssh://`, `path:`, `tarball:`) fall back to bare-SHA display.\n\n## License\n\nMIT. See [LICENSE](LICENSE).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Farcuru%2Factions","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Farcuru%2Factions","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Farcuru%2Factions/lists"}