Retire Jenkins for vmt: build & deploy both mt-test tiers from GitHub Actions - #1362
Merged
Conversation
Replaces Jenkinsfile-dev: builds Dockerfile-dev, pushes dev-build-N and dev-latest to Docker Hub, then redeploys mt-test_vmt over SSH using the stack file already provisioned in /mtdocker.
Ci/GitHub actions dev deploy
The full `docker stack deploy` re-resolved the moving *-staging-latest tags and churned the staging tier on every dev push, and the convergence poll could never succeed: `--filter name=mt-test_vmt` prefix-matched mt-test_vmt-staging, and it compared against a hardcoded 1/1 while vmt runs 2 replicas. Now a targeted `docker service update --image` on the immutable dev-build-<run#> tag, with a stack deploy fallback only when the service is missing. The wait loop reads the replica count from the service spec and heartbeats each iteration. Adds ssh keepalives, a runner-side timeout, and --detach on the monitoring_prom force-update, all of which could hang the step into an exit-255 broken pipe.
Deploy only the vmt service instead of the whole mt-test stack
Pinning the digest is enough to make the service update a real spec change, so the live spec stays consistent with the dev-latest tag the stack file declares and a manual stack deploy no longer reverts vmt. dev-build-<run#> is still pushed as a rollback target.
Ci/GitHub actions dev deploy
Mirrors the development workflow for the main branch: Dockerfile-prod, staging-latest + staging-build-<run#> tags, and a targeted digest-pinned `docker service update` on mt-test_vmt-staging. Shares the vmt-test-deploy concurrency group with the development workflow so the two never touch the mt-test stack at the same time. Removes Jenkinsfile-staging.
Build & deploy the staging tier from GitHub Actions
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
Replaces both vmt Jenkins pipelines with GitHub Actions workflows. The diff is CI only — no application code changes.
Both deploy to the same mt-test host and the same mt-test stack, and both share the vmt-test-deploy concurrency group so they can never touch the stack at once.
What changed versus the Jenkins pipelines
Deploys one service instead of the whole stack. Jenkins ran docker service rm followed by a full docker stack deploy. That reconciles every service in the stack file, and with the default --resolve-image=always it re-resolved the moving *-staging-latest tags, so a development push restarted the staging tier. Now it is a targeted docker service update --image, with a stack deploy fallback only when the service does not exist.
Deploys by digest, not by moving tag. The image is dev-latest@ / staging-latest@, the digest coming from the build step in the same run. The digest makes it a genuine spec change, so swarm does a rolling restart without the service rm hack, and the live service spec still matches the tag the stack file declares — a manual docker stack deploy on mt-test resolves to the same digest and leaves vmt alone. The *-build-<run#> tags are still pushed as named rollback targets.
Waits for real convergence instead of sleep 10. The loop reads the desired replica count from the service spec, counts running tasks, prints a timestamped heartbeat every 10s, and dumps docker service ps --no-trunc before failing at 300s.
Survives a slow deploy. ssh keepalives, BatchMode, ConnectTimeout, a runner-side timeout 900, and --detach=true on the monitoring_prom force-update, which otherwise blocks on a service in a different stack.
Other differences from Jenkins: buildx with GHA layer caching; Slack via an Incoming Webhook rather than the Jenkins Slack plugin (notify steps are continue-on-error and skip themselves when the webhook secret is unset); no workspace cleanup step, which GHA does not need.
Deliberate scope change
The Jenkins jobs checked out the devops repo and scp'd the stack file, traefik.yml and the .env-* files to /mtdocker on every deploy. These workflows do not — /mtdocker is assumed already provisioned, which keeps every secret out of GitHub. The tradeoff is that changes to docker-compose-mt-apps-test.yml and the env files need their own delivery path once Jenkins stops running. Tracked separately; it does not block this merge.
Testing
The development workflow has been running against the real development branch and deploying mt-test_vmt successfully, including with the digest pin.
The staging workflow is unrun — it cannot fire until it is on main, which this merge does.
Note on merging
Merging this will immediately trigger the staging workflow, because the push to main that lands the file is itself a push: main event. That build deploys mt-test_vmt-staging. Worth confirming beforehand that mt-test_vmt-staging exists on the host — the old Jenkinsfile-staging ran docker service rm with no || true, so if a past run died mid-deploy the service may be missing, in which case the first run takes the stack deploy bootstrap path and reconciles the whole stack file once.