ci(pact): record production deployments + shadow can-i-deploy
Adds the missing record-deployment half of the Pact can-i-deploy loop and stops can-i-deploy from failing every merge while the broker's production environment is still empty. - New pact-record-deployment.yml: on tag push, records a production deployment of nextcloud-mcp-server keyed by the tagged commit SHA, which matches the SHA pact.yml publishes consumer pacts / verification results with. Recording the tag string would not link to the verified pacts. - pact.yml can-i-deploy: wrapped in shadow mode (runs for signal, emits a warning annotation on failure, always exits 0). can-i-deploy cannot pass until both nextcloud-mcp-server and astrolabe have recorded a production deployment, so gating now would block merges on a bootstrap gap. Tracked on Deck card #325. Promotion to a hard gate is a follow-up. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.8
parent
4cf31b1472
commit
5a91b45f2a
@@ -0,0 +1,67 @@
|
|||||||
|
name: Pact record deployment
|
||||||
|
|
||||||
|
# Records a production deployment of nextcloud-mcp-server in the Pact Broker
|
||||||
|
# (ADR-029). This is the missing half of the can-i-deploy loop: can-i-deploy
|
||||||
|
# checks the candidate against whatever is currently in `production`, and this
|
||||||
|
# workflow tells the broker what `production` now contains.
|
||||||
|
#
|
||||||
|
# Trigger: tag push (v*). The release pipeline (bump-version -> tag -> docker /
|
||||||
|
# app-store publish) cuts a tag for every shipped version, so a tag push is the
|
||||||
|
# repo-controlled signal that this version is going to production.
|
||||||
|
#
|
||||||
|
# Version identity: on a tag-push event GITHUB_SHA is the commit the tag points
|
||||||
|
# to (the "bump: version ..." commit). pact.yml publishes consumer pacts and
|
||||||
|
# provider verification results keyed by that same SHA when the bump commit
|
||||||
|
# lands on master, so recording the deployment with ${{ github.sha }} links the
|
||||||
|
# deployed version to its already-verified pacts. Recording the tag string
|
||||||
|
# instead would NOT match and can-i-deploy would stay red.
|
||||||
|
#
|
||||||
|
# The broker is only reachable over Tailscale; the step no-ops when the broker
|
||||||
|
# secrets are absent (e.g. forks).
|
||||||
|
#
|
||||||
|
# Required repo/org secrets:
|
||||||
|
# TS_OAUTH_CLIENT_ID / TS_OAUTH_SECRET - Tailscale github-runner OAuth client
|
||||||
|
# PACT_BROKER / PACT_USERNAME / PACT_PASSWORD - broker URL + basic auth
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
tags:
|
||||||
|
- "v*"
|
||||||
|
|
||||||
|
permissions:
|
||||||
|
contents: read
|
||||||
|
|
||||||
|
env:
|
||||||
|
PACT_BROKER: ${{ secrets.PACT_BROKER }}
|
||||||
|
PACT_USERNAME: ${{ secrets.PACT_USERNAME }}
|
||||||
|
PACT_PASSWORD: ${{ secrets.PACT_PASSWORD }}
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
record-deployment:
|
||||||
|
name: Record production deployment
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- name: Join tailnet
|
||||||
|
if: ${{ env.PACT_BROKER != '' }}
|
||||||
|
uses: tailscale/github-action@306e68a486fd2350f2bfc3b19fcd143891a4a2d8 # v4
|
||||||
|
with:
|
||||||
|
oauth-client-id: ${{ secrets.TS_OAUTH_CLIENT_ID }}
|
||||||
|
oauth-secret: ${{ secrets.TS_OAUTH_SECRET }}
|
||||||
|
tags: tag:github-runner
|
||||||
|
|
||||||
|
- name: Install Pact CLI
|
||||||
|
if: ${{ env.PACT_BROKER != '' }}
|
||||||
|
run: |
|
||||||
|
curl -fsSL https://raw.githubusercontent.com/pact-foundation/pact-ruby-standalone/f03e620e7552239b6ca59438c9beed9d1038c949/install.sh | bash # v2.6.1
|
||||||
|
echo "$PWD/pact/bin" >> "$GITHUB_PATH"
|
||||||
|
|
||||||
|
- name: Record deployment to production
|
||||||
|
if: ${{ env.PACT_BROKER != '' }}
|
||||||
|
run: |
|
||||||
|
pact-broker record-deployment \
|
||||||
|
--broker-base-url "$PACT_BROKER" \
|
||||||
|
--broker-username "$PACT_USERNAME" \
|
||||||
|
--broker-password "$PACT_PASSWORD" \
|
||||||
|
--pacticipant nextcloud-mcp-server \
|
||||||
|
--version "${{ github.sha }}" \
|
||||||
|
--environment production
|
||||||
@@ -149,9 +149,18 @@ jobs:
|
|||||||
curl -fsSL https://raw.githubusercontent.com/pact-foundation/pact-ruby-standalone/f03e620e7552239b6ca59438c9beed9d1038c949/install.sh | bash # v2.6.1
|
curl -fsSL https://raw.githubusercontent.com/pact-foundation/pact-ruby-standalone/f03e620e7552239b6ca59438c9beed9d1038c949/install.sh | bash # v2.6.1
|
||||||
echo "$PWD/pact/bin" >> "$GITHUB_PATH"
|
echo "$PWD/pact/bin" >> "$GITHUB_PATH"
|
||||||
|
|
||||||
- name: Can I deploy nextcloud-mcp-server?
|
# SHADOW MODE: run can-i-deploy for signal but never fail the workflow.
|
||||||
|
# The broker's `production` environment is populated by the
|
||||||
|
# pact-record-deployment workflow on each repo's next release; until both
|
||||||
|
# nextcloud-mcp-server AND astrolabe have recorded a prod deployment this
|
||||||
|
# check cannot pass, so gating now would block every merge on a bootstrap
|
||||||
|
# gap rather than a real incompatibility. Once it reports ✅ in both repos,
|
||||||
|
# promote to a hard gate by removing the `set +e`/`exit 0` wrapper and
|
||||||
|
# relocating it ahead of the deploy step (see card #325 follow-up).
|
||||||
|
- name: Can I deploy nextcloud-mcp-server? (shadow — non-blocking)
|
||||||
if: ${{ env.PACT_BROKER != '' }}
|
if: ${{ env.PACT_BROKER != '' }}
|
||||||
run: |
|
run: |
|
||||||
|
set +e
|
||||||
pact-broker can-i-deploy \
|
pact-broker can-i-deploy \
|
||||||
--broker-base-url "$PACT_BROKER" \
|
--broker-base-url "$PACT_BROKER" \
|
||||||
--broker-username "$PACT_USERNAME" \
|
--broker-username "$PACT_USERNAME" \
|
||||||
@@ -159,3 +168,10 @@ jobs:
|
|||||||
--pacticipant nextcloud-mcp-server \
|
--pacticipant nextcloud-mcp-server \
|
||||||
--version "${{ github.sha }}" \
|
--version "${{ github.sha }}" \
|
||||||
--to-environment production
|
--to-environment production
|
||||||
|
rc=$?
|
||||||
|
if [ "$rc" -ne 0 ]; then
|
||||||
|
echo "::warning title=can-i-deploy (shadow)::can-i-deploy exited $rc — NOT gating (shadow mode). Expected until both repos record a production deployment; see Deck card #325."
|
||||||
|
else
|
||||||
|
echo "can-i-deploy passed ✅ (shadow mode — not yet gating)"
|
||||||
|
fi
|
||||||
|
exit 0
|
||||||
|
|||||||
Reference in New Issue
Block a user