Skip to content

About

GitHub Actions shared by cgwalters-forge workflows (secure-host-setup, tailscale)

Resources

Stars

0 stars

Watchers

0 watching

Forks

 
 

Repository files navigation

actions

This text was generated by an LLM (how cgwalters uses LLMs). cgwalters has not reviewed it yet.

jmarrero-forge's copy of cgwalters-forge/actions: its GitHub Actions, one per directory, with the two agentic-job wrappers renamed and retargeted to jmarrero-forge's deployment. Our own changes are kept to that configuration, so that the copy can follow upstream (Syncing with upstream). The text below is upstream's, but for what this copy changes; where it describes cgwalters-forge's organization (its rulesets and onboarding), that is upstream's process, not ours yet. Our work items are in jmarrero-forge/tracker.

Action Status Roadmap
lint actionlint, zizmor and the runner-label policy; this repository's CI calls it Called from each forge repository's CI
workflows-check Required workflow over a pull request's workflow files: job shape, new dangerous triggers, new zizmor ignores, linter configuration and .gitignore changes, checker references; CI runs its tests with fixture workflows An organization ruleset requires it, evaluate mode first
secure-host Runs agentic-job's attested, digest-pinned image: no later step has root or the metadata service, world-write by owner only; CI runs the two-job example, the inputs and the world-write policy on ubuntu-26.04 agentic-job's own action forwards here; opt-in egress (agentic-job#995)
app-token Mints and masks one role's GitHub App installation token, scoped to named repositories; remint.mjs mints again near expiry or after a 401; CI runs its unit tests, no real mint (no app here) Move each role to its app (tracker#766)
admit Fails unless the calling repository's owner id is in its owners.json; both reusable wrappers run it first; CI runs its unit tests Brokers and tailnet federation match the same ids
tailscale Settings by organization; CI runs its unit tests and checks the socket and CLI are closed after a join that fails, no real join (no tailnet credentials here) Replace devspace.yml's and agent.yml's tailscale/github-action steps

jmarrero-agentic-job

One reusable workflow is here too: jmarrero-agentic-job, an agent run of cgwalters-forge/agentic-job with this deployment's tailnet join, inference proxy, runner, agent and model. Our callers pin it by commit, the one jmarrero's inference broker admits (jmarrero/atomic-setup, bot/praxis-broker), so a change here reaches runs only once both move. Any public repository can call it too, and its run's identity tokens carry the same job_workflow_ref, so the inference broker and the tailnet federation must match repository_owner_id against the ids in admit/owners.json as well as that job_workflow_ref; both wrappers refuse any other owner before the agent job's runner, which the caller picks, is given the job (admit). It writes no broker address: a real agent needs the calling repository's variable INFERENCE_URL, our broker, whose audience jmarrero-praxis-broker is the default. With an inference-url other than that variable's it needs an inference-audience too, so that our broker's audience is not sent elsewhere by default (the review wrapper's variables still default apart). The agent is claude unless AGENT or the input says otherwise, with the agent's own model unless AGENT_MODEL names one. It refuses runs from a private repository, so agentic-job's opt-in for private repositories, which admits only the calling repository, stays off.

A repository gets agent runs with the workflow below, a bounds file at .github/agentic-job/dispatch.toml (and fix.toml for the fix kind), a runner configuration at .github/agentic-job/hosted.toml, and an environment that gates the apply token; jmarrero-forge/tracker has all four to copy. The file's header says what else a caller may set.

Both wrappers pin agentic-job v0.6.2, by its commit, and check inference reachability after the tailnet join, before securing the host. They still compose that tag's secure-host/internal action, which runs sandbox setup on the host, not this repository's secure-host image action that the tag's public secure-host now forwards to, so its egress proxy stays a host unit. Since v0.6.0 the agent's home no longer copies the runner image's /etc/skel, toolchains and dotfiles included. The pinned run action publishes the session endpoint itself; no extra endpoint step is needed here. Mid-run steering stays off unless the caller's runner configuration enables [session] watch-item = true. Policy derives the watched item from the dispatch wrapper's issue (in output-repo) or the review event; run needs no additional input. Upstream bounds delivery to 10 updates of 8000 characters, quoted as untrusted item text, not instructions.

name: dispatch
run-name: ${{ inputs.kind }} ${{ inputs.repo }}#${{ inputs.item }}
on:
  workflow_dispatch:
    inputs:
      task: {type: string, required: true}
      repo: {type: string, required: true}
      item: {type: string, required: true}
      kind: {type: choice, required: true, options: [implement, triage, research, review, fix]}
permissions: {}
concurrency:
  group: dispatch-${{ inputs.kind }}-${{ inputs.repo }}-${{ inputs.item }}
jobs:
  run:
    # The commit the broker's run-token policy admits.
    uses: jmarrero-forge/actions/.github/workflows/jmarrero-agentic-job.yml@COMMIT
    permissions: {contents: read, issues: write, pull-requests: write, actions: read, id-token: write}
    with:
      task: ${{ inputs.task }}
      repo: ${{ inputs.repo }}
      item: ${{ inputs.item }}
      kind: ${{ inputs.kind }}
      apply-environment: agent-apply
    secrets:
      SAFE_OUTPUTS_PAT: ${{ secrets.SAFE_OUTPUTS_PAT }}

Review

jmarrero-review is the reusable event-review wrapper. It composes agentic-job v0.6.2's policy, check, apply and review helpers, so that the tailnet and the inference broker admit this file's job_workflow_ref; agentic-job's review workflow can now run a caller's own network step instead (its #705), which callers have not moved to. It refuses private repositories, as the dispatch wrapper does. It adds our tailnet join and defaults: claude, the agent's own model, ubuntu-26.04, and our broker's audience; the inference URL is the variable INFERENCE_URL alone. AGENT_MODEL is shared with dispatched runs, so set it only for a model the reviewing agent serves too. It has no inputs. Repository/organization variables AGENT_REVIEW (the reviewing agent, apart from AGENT so that turning on dispatched runs leaves reviews alone), AGENT_MODEL, AGENT_RUNNER (JSON), INFERENCE_URL, INFERENCE_AUDIENCE, AGENT_CONFIG, AGENT_CONFIG_REPO and AGENT_CONFIG_PATH select owner-controlled configuration. Set the last two for agents needing external configuration; there is no hard-coded configuration repository. AGENT_CONFIG otherwise uses the pinned agentic-job hosted configuration. AGENTIC_JOB_TAILSCALE_OAUTH_CLIENT_ID and AGENTIC_JOB_TAILSCALE_TAGS, read by both wrappers, are the tailnet login of an organization that tailnets.json doesn't list; set, they replace a listed organization's entry too. Either way the wrappers run only for an owner that admit/owners.json lists.

Call it from the same pull_request_target and issue_comment events and job condition as this repository's caller, replacing the job's uses with:

uses: jmarrero-forge/actions/.github/workflows/jmarrero-review.yml@COMMIT

Keep that caller's six permission grants. Optional SAFE_OUTPUTS_PAT is forwarded explicitly, only to apply; it never reaches the agent or the real review submission. Keep workflow/review.toml, workflow/review-command.toml and workflow/review.md on the caller's base branch. Automatic reviews admit non-draft owner/member/collaborator PRs, preserving upstream's association rule for all authors. Otherwise-unassociated bots wait unless REVIEW_BOT_IDS lists their numeric IDs and the bounds admit their logins (including Dependabot). Use a JSON array of numbers; Actions also coerces string IDs. /review still requires write access through event policy. Only admitted agent jobs enter per-PR concurrency; new automatic events cancel the old agent, comments do not. The head is data inside the sandbox, never executed by a privileged step. Each review is bounded to 150 requests, 500 AIC and 75 agent minutes.

AGENT_REAL_REVIEWS=true opts into checked APPROVE/REQUEST_CHANGES submission with the job token, at the admitted head; unset is off. Enable GitHub Actions' permission to create/approve PRs for this feature. A stale head, cancellation or failed check cannot produce a new approval. The compatibility review status is not a merge gate or human approval.

For a new repository in this organization, put the review caller and the three workflow/review* files in its initial commit, and set the variables above (copy them from an onboarded repository such as tracker) and Actions' permission to approve pull requests when you create it. The organization's ruleset requires an approving review on main and has no bypass actors, but the first push to an empty repository isn't a pull request, so the review is in place before the first one. Added later, the onboarding pull request itself needs an approval from an organization owner, because nothing can review it yet.

A repository whose name ends in -sandbox is for agents to iterate in freely: the organization's approval ruleset excludes it, so its pull requests merge without a review. When it's ready, renaming it to drop the suffix brings it under the ruleset; the review above should be in place before that rename.

Before migrating tracker (a separate repository), admit this wrapper's job_workflow_ref, with the owner ids of admit/owners.json, in the tailnet federation and inference broker, then replace its review caller's uses as above and exercise a real review and a synchronize cancellation. No ACL, OAuth or broker policy is changed here; record those deployment changes in the private wiki when made. Removing the deployment-specific pieces from agentic-job is a separate follow-up. just test-review checks the wrapper's admission and publication boundaries; live tailnet joins and GitHub review writes are not exercised locally.

Runs may edit .github/ here, so pull requests are reviewed by this repository's caller of the wrapper above, referenced locally so that it runs as on the base branch, never as a pull request edits it, with this repository's bounds and task in workflow/, once the repository variable AGENT_REVIEW turns it on: jmarrero's broker admits no review from here yet. The ruleset on main is to require its approval, dismissed when new commits are pushed; the approval is submitted only with the repository variable AGENT_REAL_REVIEWS=true, beside the variables listed above. Dependabot's pull requests are reviewed only with its ID in REVIEW_BOT_IDS. Without .github/agentic-job/merge.toml the reviewer is told a person approves after it.

Lock new items

lock-new-items locks each newly opened issue, so that only collaborators can comment on it and agent runs on it read no outsider's comments (tracker#733). Its one step locks the item by API with the caller's job token: no PAT, and nothing of the item is read or run. Pull requests are not locked: a locked PR refuses reviews from the review job token, and the supervisor only dispatches issues. It does not cover the opener's own text, comments in the seconds before the lock, items opened by another workflow's job token or transferred in (no opened event), or items that predate the caller. A repository opts in with this one file, .github/workflows/lock.yml, as this repository's caller but for its uses:

name: lock
on:
  issues:
    types: [opened]
permissions: {}
jobs:
  lock:
    uses: cgwalters-forge/actions/.github/workflows/lock-new-items.yml@main
    permissions:
      issues: write

The same pull request exempts the file in .github/agentic-job/workflows.toml, creating it if need be, as this repository does: without that, workflows-check's shape check refuses every later pull request. Its zizmor needs the ref-pin policy for our own workflows that .github/zizmor.yml sets.

Syncing with upstream

This copy follows cgwalters-forge/actions' main, and with it the agentic-job release that upstream's wrappers pin, rather than choosing versions of its own (cgwalters-forge/harness-coordination#7). It was last synced at upstream's 018f138, with agentic-job v0.6.2; nothing runs on it yet, pending jmarrero-forge/tracker#38 (the GitHub-side setup) and #39 (the first runs).

main takes pull requests rebase-merged (a squash would fold the snapshot into our commits, and a merge commit is what this avoids), so a sync is one pull request of two parts: a commit whose tree is upstream's main at a named commit, "Sync with cgwalters-forge/actions main at SHA", then our own commits since the previous such commit, replayed on it (git cherry-pick PREVIOUS-SYNC..origin/main). Each replay merges against the upstream tree it was made on, so it conflicts only where upstream changed what we retarget. git diff SHA main is then exactly ours:

  • the wrappers' names, jmarrero-agentic-job.yml and jmarrero-review.yml, which runs' identity tokens carry;
  • admit/owners.json and tailscale/tailnets.json: our organizations, with the client ID left to AGENTIC_JOB_TAILSCALE_OAUTH_CLIENT_ID and no proxy address;
  • the defaults: claude, no broker address (INFERENCE_URL), the audience jmarrero-praxis-broker, and AGENT_REVIEW for reviews;
  • the tailnet join, this repository's action at the commit the wrapper runs at rather than at main, since the broker admits the wrapper by commit;
  • this repository's review bounds and caller, off until AGENT_REVIEW.

Once a sync merges, the callers' pins (jmarrero-forge/tracker's dispatch.yml and review.yml, jmarrero/review's review.yml) and the broker's run-token policy move to the new commit together (jmarrero/atomic-setup's bot/praxis-broker/README.md, "Moving the wrapper's pin").

Licensed under either of Apache-2.0 or MIT, at your option.

About

GitHub Actions shared by cgwalters-forge workflows (secure-host-setup, tailscale)

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages