harness/plugins/ci-github/claude/skills/gh-test/SKILL.md
Test GitHub Actions locally using `@kie/act-js` (CLI + API), including event simulation, job-level runs, secret/env injection, and pl-repo-safe local validation.
npx skillsauth add popoffvg/dotfiles gh-testInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
Use @kie/act-js to run GitHub Actions locally as CLI or programmatic API.
.github/workflows/*.y*mlnpm i @kie/act-js
npx act-js --version
# discover jobs
npx act-js --list
# run one event
npx act-js pull_request
# run one job only
npx act-js pull_request -j lint
# custom workflows dir
npx act-js pull_request -W .github/workflows
import { Act } from "@kie/act-js";
const act = new Act(process.cwd(), ".github/workflows")
.setSecret("GITHUB_TOKEN", process.env.GITHUB_TOKEN ?? "test-token")
.setEnv("CI", "true")
.setInput("deploy-staging", "false")
.setEvent({ pull_request: { head: { ref: "feature/test" } } });
// list workflows/jobs
const workflows = await act.list("pull_request");
// run a single job
const jobResult = await act.runJob("lint");
// run all jobs for an event
const eventResult = await act.runEvent("pull_request");
new Act(cwd?, workflowFile?)setSecret() / deleteSecret() / clearSecret() / setGithubToken()setEnv() / deleteEnv() / clearEnv() / setGithubStepSummary()setInput() / deleteInput() / clearInput()setEvent(payload)list(event?)runJob(jobId, options?)runEvent(eventName, options?)runEventAndJob(eventName, jobId, options?)Run options (important):
cwd, workflowFilebindartifactServermockApimockStepslogFileverboseUse Mockapi with mockApi options when actions call HTTP(S) APIs.
Prefer this for stable tests over real network calls.
(From test/it/act.test.ts pattern)
const act = new Act();
const list = await act.list("pull_request", __dirname, "./resources");
// returns [{ jobId, jobName, workflowName, workflowFile, events }, ...]
Use this before runs to avoid wrong jobId assumptions.
(From test/it/act.test.ts)
const output = await new Act()
.setSecret("SECRET1", "secret1")
.setEnv("ENV1", "env")
.runJob("push1", { workflowFile: "./resources", cwd: __dirname });
Use for narrow, deterministic smoke tests.
(From README event section + integration test style)
const output = await new Act()
.setEvent({ pull_request: { head: { ref: "feature/my-branch" } } })
.runEvent("pull_request", { workflowFile: ".github/workflows" });
Use when workflow logic depends on github.event.* fields.
(From API surface: runEventAndJob)
await new Act().runEventAndJob("pull_request", "lint", {
workflowFile: ".github/workflows",
verbose: true,
logFile: ".tmp/act-lint.log",
});
Use when one job in a multi-job workflow is failing.
(From test/it/act.test.ts and README Mockapi section)
import { Mockapi } from "@kie/act-js";
const mockapi = new Mockapi({
google: {
baseUrl: "http://google.com",
endpoints: {
root: { get: { path: "/", method: "get", parameters: { query: [], path: [], body: [] } } },
},
},
});
await new Act().runJob("mock", {
workflowFile: "./resources",
mockApi: [mockapi.mock.google.root.get().setResponse({ status: 200, data: "mock response" })],
});
Use to remove flaky network dependencies.
(From test/it/act.test.ts + test/unit/step-mocker/step-mocker.test.ts)
await new Act("./resources").runJob("push1", {
mockSteps: {
push1: [
{ name: "secrets", mockWith: "echo secrets" },
{ run: "echo $ENV1", mockWith: "echo some env" },
],
},
});
Step matching can use id, name, uses, run, or step index.
Upstream keeps a minimal workflow example at:
.github/workflows/ci-checks.yaml (triggered on pull_request for workflow changes)Use it as a shape template for lightweight workflow tests.
https://github.com/shubhbapna/mock-github-act-js-examples/tree/main/custom-actions/javascripthttps://github.com/shubhbapna/mock-github-act-js-examples/tree/main/workflow/github-scriptFor /Users/popoffvg/Documents/git/mil/pl workflows:
lint, actionlint) before full orchestration.dev-ci-pl, rockylinux8-amd64).milaboratory/github-ci/*, github-ci-internal/*) and org secrets.workflow_dispatch with explicit input payloads (e.g. deploy-staging=false) first.Common secret names referenced in pl workflows:
MI_LICENSE, GH_CI_PAT, AWS_CI_TURBOREPO_S3_BUCKET, NPMJS_TOKENQUAY_USERNAME, QUAY_ROBOT_TOKENCOUCHDB_*setEvent / -e equivalent)logFile for API mode)A workflow change is locally verified when:
tools
Improve a whole CLAUDE.local.md — the private, per-project rules captured from user corrections. Wraps each conditional rule in a <task-relevant> block so it only surfaces for matching work, merges duplicates, generalizes one-off facts, drops stale entries, and routes raw project facts to engram. Use when the user says "improve claude.local", "clean up the local rules", "claude.local is bloated", or after the Stop hook has appended many rules.
testing
WM pipeline and conventions shared across all phases. Agents must read this before spec, impl, or verify work.
development
One entry point for spec writing, implementation, and bug fixing. Default is new (write spec → grill loop → produce notes → author TODO bodies). Other subcommands: verify (audit), revise (sync to shipped), prototype (settle a decision), code-map (diagram), impl (execute one TODO), fix (analyze cause, correct thoughts, fix behavior), help (this page). Invoke as /code <subcommand>.
development
Red-Green-Refactor cycle for bug fixes. Before fixing a bug, first write a failing test that reproduces it (Red), then make the minimal change to pass (Green), then clean up the code (Refactor). Use on any bug fix, error correction, failing test repair, or when user says "fix this bug".