ci: add the shared commitlint action and switch .github to it - #40
Conversation
A composite action at .github/actions/commitlint runs wagoid/commitlint-github-action pinned to v6.2.1 with the commitlint config moved from the repository root into the action directory, so callers need no local config. wagoid is a Docker action and resolves configFile against the workspace inside its container, where the runner's _actions directory is not mounted; the action copies the config into the workspace, prints it, and removes the copy afterwards.
The workflow becomes the reference caller: pull_request trigger, contents and pull-requests read, checkout with fetch-depth 0, then the action, from the job named "Lint commit messages" that the org ruleset require-lint pins. It calls the action by local path so a PR here exercises the version of the action it carries.
CONTRIBUTING.md lists the action in the inventory and gains a section with the exact caller workflow to copy, the permissions a private repository needs, why the job name must stay "Lint commit messages" (the org ruleset require-lint pins that context), and that the caller checks out before the action.
There was a problem hiding this comment.
The shared action stages its config in a fixed caller-owned workspace path and then recursively deletes that path (.radiusred-commitlint). Because this action is intended for every org repository, an adopting repository may legitimately already contain that directory; this step would overwrite its commitlint.config.mjs and the if: always() cleanup would delete the entire directory and any unrelated caller files. Please stage the config in a collision-resistant action-owned path (for example, a run-specific directory under GITHUB_WORKSPACE) and clean up only the artifact this action created, or explicitly detect a collision and fail without modifying caller content.
Review finding on the PR: the fixed workspace path .radiusred-commitlint/ is caller-owned territory, so an adopting repository that already had it would have a file overwritten and the whole directory removed by the cleanup. The staging step now creates a fresh, uniquely named directory with mktemp -d (run id, attempt and a random suffix), which never reuses an existing path, hands it to the lint step through a step output, and the cleanup removes only that directory.
|
Addressed in The staging step now creates its own directory with Proof on this head: Deviation recorded on #39: #39 (comment) |
There was a problem hiding this comment.
Re-review of c4d0286: the requested collision-safety fix is sound. The action now atomically creates a unique workspace directory with mktemp -d, exposes only that generated relative path to commitlint, guards cleanup on the stage output, and removes exactly the directory it created. The deviation is recorded on #39. The successful new-head “Lint commit messages” run exercised the local composite action; its log shows the generated .radiusred-commitlint-33895919823-1.P85JnUy8 path passed as configFile, “Lint free!”, and cleanup of that same path. The fix commit changes only action.yml, so the earlier verification—including CONTRIBUTING.md and the rest of M5-R1/.github’s M5-R2 share—still stands.
Closes #39 — milestone radiusred/ops#17 (M5), requirements M5-R1 and the
.githubshare of M5-R2.What was done
.github/actions/commitlint/— a composite action (runs.using: composite, no inputs) that runswagoid/[email protected](exact tag, not the floating@v6) with the organisation'scommitlint.config.mjs, moved from the repository root into the action directory so callers need no local config. Other repositories reference it asuses: radiusred/.github/.github/actions/commitlint@main..github/workflows/commitlint.ymlrewritten as the reference thin caller:pull_requesttrigger,permissions: contents: read, pull-requests: read,actions/checkout@v4withfetch-depth: 0, then the action, from a job named exactlyLint commit messages. This repository calls the action by local path (./.github/actions/commitlint) so a PR here — this one — exercises the version of the action it carries.commitlint.config.mjsdeleted (moved into the action).CONTRIBUTING.md: the action in the inventory, and a "Linting commit messages in a repository" section with the exact caller file to copy, the permissions a private repository needs, why the job name must stayLint commit messages(the org rulesetrequire-lintpins that check context on every public repository's default branch, which is also why this is a composite action and not a reusable workflow), and that the caller does the checkout.reusable-release.yml,reusable-finalize-release.yml,calculate_version.How
configFilereaches the config inside the action directorywagoid/commitlint-github-actionis a Docker action. Its source resolves the input asresolve(process.env.GITHUB_WORKSPACE, getInput('configFile'))inside the container, and the runner mounts only the workspace,_github_home,_github_workflowand the file-commands directory into a step container — not_actions, wheregithub.action_pathlives. Passing a path into the action directory would therefore not be found and wagoid would fall back silently to bare config-conventional. The action instead copies the config from${{ github.action_path }}into a directory it creates itself under the workspace withmktemp -d(.radiusred-commitlint-<run id>-<attempt>.<random>/, so it never writes into or deletes a path the caller owns), prints it to the job log, passes that workspace-relative path asconfigFilethrough a step output, and removes only that directory afterwards (if: always()).Proof
The
Lint commit messagescheck on this PR runs through the new action and lints this PR's own commits. The "Place the shared commitlint config in the workspace" step in its log shows the path and the contents of the config that was linted against. The three commits were also linted locally with@commitlint/cliagainst the shipped config before pushing.Tests
The repository has no test framework; the PR's own check is the end-to-end test of the action (the copy step, the config resolution, the lint of real commits, and the check context the ruleset requires).
Decisions and deviations
@mainfor callers, exact tag for the inner action): Add the shared commitlint composite action and switch .github to it #39 (comment)mktemp -dinstead of a fixed path, after radiusred-checky's review): Add the shared commitlint composite action and switch .github to it #39 (comment)Callers checked
Only this repository calls the action so far; ops, www and infrastructure migrate in radiusred/ops#19, radiusred/www#66 and radiusred/infrastructure#255. The reusable release workflows and
calculate_version(called by tradedesk and tradedesk-dukascopy) are not touched.🤖 Generated with Claude Code