Skip to content

ci: replace CircleCI with GitHub Actions#53

Open
dkisselev wants to merge 4 commits intomasterfrom
dk/github-actions-ci
Open

ci: replace CircleCI with GitHub Actions#53
dkisselev wants to merge 4 commits intomasterfrom
dk/github-actions-ci

Conversation

@dkisselev
Copy link

@dkisselev dkisselev commented Mar 5, 2026

Summary

Replace the dead CircleCI pipeline (Node 12 EOL) with GitHub Actions so that semantic-release can publish new versions again.

  • Add .github/workflows/ci.yml: test job (Node 20, Ruby 3.2, lint + test) on push/PR to master
  • Add .github/workflows/release.yml: test + release pipeline on push to master, using npm trusted publishing (OIDC) instead of an NPM_TOKEN secret
  • Remove .circleci/config.yml: dead pipeline using circleci/node:12 and circleci/ruby:2.7-node
  • Bump devDependencies: jest ^26^29, semantic-release ^17^24
  • Update engines.node: >=10.18>=18

No runtime dependency changes. All 17 tests pass.

Motivation

PR #51 removed the upper bound on the semantic-release peer dependency, but it was never published because CircleCI's release job runs on Node 12 (EOL) and fails. This PR restores the release pipeline so that change (and future changes) can be published to npm.

Post-merge setup

See the GitHub configuration section below for required setup before the release job will work.

GitHub configuration

  1. Create a GitHub environment called release in the repo settings (Settings → Environments → New environment)

    • Optionally add reviewers or branch protection rules to gate releases
  2. Configure npm trusted publishing on npmjs.com:

No NPM_TOKEN secret is needed — the OIDC token from GitHub Actions authenticates directly with npm.

🤖 Generated with Claude Code

dkisselev and others added 4 commits March 5, 2026 09:40
CircleCI release pipeline is dead (Node 12 EOL). Replace with GitHub
Actions workflow that runs lint + tests on PRs and publishes via
semantic-release on master.

Also bumps devDependencies (jest ^29, semantic-release ^24) and
engines.node to >=18.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Split the release job into a dedicated release.yml workflow that uses
npm trusted publishing via OIDC instead of an NPM_TOKEN secret. The
release job runs in a GitHub environment called "release" with
id-token: write permission and NPM_CONFIG_PROVENANCE enabled.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- ci.yml: run tests on PRs and master; dry-run semantic-release on PRs
- release.yml: trigger via workflow_run after CI succeeds on master

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Replace NPM_TOKEN secret with OIDC trusted publishing. The id-token
permission + release environment + NPM_CONFIG_PROVENANCE lets npm
authenticate via GitHub's OIDC provider.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@dkisselev dkisselev requested a review from a team March 5, 2026 21:13
@dryrunsecurity
Copy link

dryrunsecurity bot commented Mar 5, 2026

DryRun Security

This pull request adds a CI workflow whose 'test' job lacks an explicit job-level 'permissions' block, so it may inherit broad default GITHUB_TOKEN permissions (e.g., contents: write) and could allow untrusted PR code or compromised dependencies to perform unauthorized repository actions. To mitigate, the job should set minimal necessary permissions (for example, read-only) to limit risk.

Missing job-level permissions in .github/workflows/ci.yml (drs_394acdfe)
Vulnerability Missing job-level permissions
Description The 'test' job in the CI workflow lacks an explicit 'permissions' block, which can cause it to inherit broad default repository permissions (e.g., 'contents: write'). Since this job executes potentially untrusted code from pull requests or dependencies via 'yarn install' and 'yarn test', a malicious actor could exploit the GITHUB_TOKEN to make unauthorized changes to the repository. While pull requests from forks are restricted to read-only access by GitHub, pull requests from internal branches or compromised dependencies in the master branch could still gain write access if the repository's default settings are not restricted.

test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4


All finding details can be found in the DryRun Security Dashboard.

Copy link
Contributor

@dduugg dduugg left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

Bug — Missing fetch-depth: 0 in both workflows

Semantic-release requires the full git history to determine the next version (it walks commits to find the last tag). Both ci.yml (semantic-release-dry-run job) and release.yml (release job) use actions/checkout@v4 without fetch-depth: 0, which produces a shallow clone.

# Both jobs need this:
- uses: actions/checkout@v4
  with:
    fetch-depth: 0

Without this, npx semantic-release may mis-identify the next version or fail entirely in the release job.

Suspicious — eslint-config-gusto downgraded from ^16.0.0 to ^11.0.0

The current package.json on master has "eslint-config-gusto": "^16.0.0". This PR changes it to ^11.0.0, which is a major version downgrade. This doesn't appear intentional and may have been introduced during a rebase or conflict resolution. Worth confirming.

-    "eslint-config-gusto": "^16.0.0",
+    "eslint-config-gusto": "^11.0.0",

Minor — workflow_run trigger adds latency and complexity

Using workflow_run means the release job won't appear as a required check on the PR itself — it only fires after CI finishes on master. This is intentional and correct for a release pipeline, but worth being aware of: if CI passes but the release fails (e.g., because the release environment or npm trusted publishing isn't configured yet), the failure will show up on the commit, not on the PR.

Minor — No Ruby setup in release.yml

The release.yml job doesn't install Ruby. This is fine because semantic-release (the npm publish step) doesn't need Ruby — Ruby is only required for the gem build / gem push steps at runtime in consumer repos. The CI pipeline here just publishes the npm package itself. Just noting this as expected/intentional.


Suggested blocking items before merge:

  1. Add fetch-depth: 0 to the semantic-release-dry-run and release jobs.
  2. Confirm (and likely revert) the eslint-config-gusto version — should be ^16, not ^11.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants