ci: migrate from CircleCI to GitHub Actions - #28
Merged
Merged
Conversation
rgamba
force-pushed
the
claude/circleci-github-actions-migration-bd642e
branch
from
September 15, 2026 19:43
96ae702 to
add6fa3
Compare
Replaces .circleci/config.yml with three workflows that reproduce the same pipeline: build.yml (Jackson matrix, format-check, examples, the jvm-build fan-in, web-build, and on main web-publish and tag-release), release.yml (tag-triggered test-then-publish to Maven Central) and a reusable jvm-build.yml shared by both so the release cannot drift from what pull requests were tested with. Differences forced by the platform: the deploy key is replaced by the run's GITHUB_TOKEN for the gh-pages push and the tag push; because a GITHUB_TOKEN push starts no workflow, tag-release dispatches release.yml on the tag explicitly (a hand-pushed tag still arrives through `push`). The skipper-publish CircleCI context becomes a GitHub environment of the same name with the same four secrets. The examples job depends on the whole Jackson matrix rather than the 2.9.10 entry alone, since a job cannot depend on a single matrix leg. Test results and reports are run artifacts, since Actions has no store_test_results.
rgamba
force-pushed
the
claude/circleci-github-actions-migration-bd642e
branch
from
September 15, 2026 20:03
add6fa3 to
147ff2e
Compare
…ronment GitHub Environments are not available on this repository, so publish-release reads the four secrets directly. Same names as the CircleCI context.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Now that the repository is public, CI moves from CircleCI to GitHub Actions. This PR reproduces the existing pipeline job for job and removes
.circleci/config.yml.Architecture
Three workflow files under
.github/workflows/:jvm-build.ymlworkflow_call) JVM build: compile, full test suite,publishToMavenLocalvalidation, Gradle cache, test-report and jar artifacts. Takesjackson_version.build.ymlmain: the Jackson matrix (2.9.10 default, 2.13.5, 2.17.3, 2.22.2) callingjvm-build.yml,format-check,examples, thejvm-buildfan-in,web-build; onmainonly,web-publishandtag-release.release.ymlvX.Y.Ztag:jvm-build.ymlonce, thenpublish-releaseto Maven Central.The JVM build is one reusable workflow rather than two copies, so the release runs exactly the build pull requests were gated on.
Key decisions and trade-offs
pull_requestplus pushes tomain. That covers pull requests from forks (which CircleCI never built) without running every branch twice. A branch with no PR gets no CI, which matches how the repo is worked on (squash merges through PRs).GITHUB_TOKENwithcontents: write. One fewer credential to rotate, and nothing to configure.GITHUB_TOKENdeliberately starts no workflow, sotag-releaserunsgh workflow run release.yml --ref vX.Y.Zafter pushing the tag. A hand-pushed tag still starts the release through its ownpushtrigger.release.ymlguards against aworkflow_dispatchon anything that is not a release tag.skipper-publishcontext becomes four repository secrets of the same names, so the values move over unchanged. GitHub Environments are not available on this repository, so the tag-only restriction they would have given is not possible; forks never see the secrets, and push access is the boundary.jvm-build, so the ruleset's required check changes fromci/circleci: jvm-buildtojvm-build.exampleswaits for all four Jackson builds instead of only 2.9.10. They run in parallel, so the cost is small.0.0.0-CItree before the download and before saving, so a cached copy can never shadow the artifacts the run just built.ubuntu-22.04where the MariaDB4j native libraries (libaio1,libncurses5) are needed, since those package names do not exist on 24.04;ubuntu-latestelsewhere.SKIPPER_ARTIFACTORY_MIRRORvariable, since an internal mirror is unreachable from GitHub-hosted runners. CircleCI's per-test timing and flaky-test detection have no equivalent; the JUnit XML and HTML reports are uploaded as run artifacts instead.mainare never cancelled, so a tag is never pushed without its release started.Cutover steps (repository settings, outside this PR)
ORG_GRADLE_PROJECT_mavenCentralUsername,ORG_GRADLE_PROJECT_mavenCentralPassword,SIGNING_KEY,SIGNING_PASSWORD(Settings > Secrets and variables > Actions), with the values from the CircleCI context.mainruleset's required status check fromci/circleci: jvm-buildtojvm-build. Until this is done the PR cannot merge, since the CircleCI check will never report on it.Testing
actionlint(with shellcheck) passes on all three workflows.bash -n scripts/publish-web.shpasses; only its header comments changed.scripts/next-version.shwas run locally on this branch: exits 3 (nothing releasable) as expected for aci:commit.buildworkflow ran on this PR: run 35020678764 is green across all four Jackson legs,format-check,examples(all five projects including both Docker smoke tests),web-buildand thejvm-buildfan-in. Wall clock about 22 minutes; the JVM legs take about 5 minutes each in parallel,examplesabout 4 minutes after them.SqliteWorkflowIntegTest > testReplaySignal_reusesSameRowAndDoesNotDuplicatewith anOptimisticLockingErrorat thereplaySignalcall; the other three legs passed on identical bytecode and the re-run passed. That is a pre-existing race in the test (it replays before the engine has finished writing the first signal), tracked separately, not a CI change.web-publish,tag-releaseandrelease.ymlonly run onmainor a tag, so they are verified on the first merge and first release. The four release secrets are already set.