Checkpoint Lab — GitHub Actions Importer, CI Migration, Compatibility, and Modernization
Migrate a synthetic CI pipeline with one unsupported construct, prove behavioral parity, document deltas, and produce a guarded cutover and rollback plan.
Learning objectives
- Migrate a synthetic pipeline with one unsupported feature.
- Fail closed until unsupported behavior is mapped.
- Prove same-revision artifact and quality-gate parity.
- Write guarded cutover and rollback criteria.
- Bridge migration evidence into the Chapter 36 capstone.
1. Checkpoint: migrate, compare, cut over safely
You own a synthetic legacy pipeline with build, test and manual
deploy stages. One source
feature—legacy-quality-gate-plugin—is intentionally
unsupported. Your task is to produce a candidate Actions workflow,
preserve the unsupported item, implement a documented replacement,
run parity checks on the same revision, and write a cutover/rollback
record. The mandatory path is local and free.
2. Preflight, assumptions and predictions
- Python 3.11+ and Git installed.
- No production repository or source CI server is required.
- All deployment state is a local JSON file under the lab directory.
- No credential value appears in source or target files.
- If live Importer is used optionally, run audit or dry-run first and record actual version output.
Predict before execution: (1) source and target build artifacts should have the same digest for the same commit; (2) the first target candidate should be denied cutover because the unsupported quality gate is unresolved; (3) after the replacement check is added, target CI can become eligible while legacy deployment remains disabled during proof.
3. Create the migration inventory and source pipeline
{
"source_platform": "SyntheticCI 2.4",
"pipeline": "release-main",
"trigger": "push main",
"agent": {"os":"linux","tools":["python3"],"private_network":false},
"secrets": ["DEPLOY_TOKEN"],
"artifact": "dist/app.txt",
"deployment": {"manual_approval":true,"target":"local:target-state.json"},
"unsupported": ["legacy-quality-gate-plugin"]
}
Hash the inventory and source configuration. Their digests identify the migration input set. Any later edit creates a new migration revision and must not be silently mixed with earlier parity evidence.
4. Candidate Actions workflow with the unsupported item preserved
name: migration-checkpoint
on:
workflow_dispatch:
permissions: {}
jobs:
build-test:
runs-on: ubuntu-24.04
permissions:
contents: read
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
- run: python3 scripts/build_and_test.py
- uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: migration-${{ github.sha }}
path: dist/app.txt
quality-gate:
needs: build-test
runs-on: ubuntu-24.04
steps:
# TODO(actions-importer): replace legacy-quality-gate-plugin.
- run: exit 1
deploy:
needs: quality-gate
environment: migration-lab
if: github.ref == 'refs/heads/main'
runs-on: ubuntu-24.04
permissions: {}
steps:
- run: echo "synthetic deploy only after mapped gate"
The intentionally failing quality-gate job is safer than silently dropping the unsupported source behavior. It makes the missing contract fail closed until engineering resolves it.
5. Replace the unsupported gate with observable local behavior
from pathlib import Path
artifact=Path('dist/app.txt')
assert artifact.exists(), 'artifact missing'
text=artifact.read_text()
assert 'BLOCKED' not in text, 'quality policy violation'
print('quality gate: PASS')
Document this as an intentional implementation delta: the legacy plugin is not “converted”; its required outcome is reimplemented as a deterministic local policy check. In a real migration, acceptance criteria would be agreed with the source-system owner.
6. Execute parity test and preserve one failing comparison
import hashlib, json, pathlib
s=pathlib.Path('source-out/app.txt'); t=pathlib.Path('target-out/app.txt')
def h(p): return hashlib.sha256(p.read_bytes()).hexdigest()
report={'source_sha':h(s),'target_sha':h(t),'artifact_equal':h(s)==h(t),'quality_gate':'mapped','cutover_eligible':h(s)==h(t)}
pathlib.Path('evidence/parity.json').write_text(json.dumps(report,indent=2))
print(json.dumps(report,indent=2))
Before the replacement check exists, record
cutover_eligible=false. Do not overwrite that
first-failure evidence after repair. The second report should cite
the same source revision and explicitly name the repaired semantic
gap.
7. Write the guarded cutover and rollback plan
| Phase | Legacy CI | Actions | Deployment authority | Exit criterion |
|---|---|---|---|---|
| Inventory | active | candidate only | legacy only | source contract hashed |
| Dual-run validation | build/test active | build/test active | legacy only | same-SHA parity sample passes |
| Cutover | build may remain read-only | authoritative | Actions only | old deploy credential/trigger disabled and denial verified |
| Rollback window | read-only standby | authoritative unless rollback trigger | exactly one system | rollback criteria and artifact target known |
| Retirement | disabled/archived | authoritative | Actions only | evidence retained; legacy credential revoked |
Rollback means restoring the previous known deploy authority and artifact, not enabling both systems. State the exact rollback trigger, responsible operator and verification steps.
8. Required evidence packet
- Source platform/version and pipeline/config digest.
- Source revision SHA used by both implementations.
- Generated workflow and preserved Importer TODO/unsupported inventory.
- Runner/tool assumptions and explicit permissions.
- Source and target run IDs or local simulation identifiers.
- Artifact SHA-256 comparison and quality-gate result.
- Secret mapping document containing names/scopes only, never values.
- Cutover record proving one deploy authority and legacy disablement.
- Rollback target and acceptance criteria.
- Assumptions/limitations note, including whether live Importer was used.
9. Verification and cleanup
test -f evidence/parity.json
python3 - <<'PY'
import json
r=json.load(open('evidence/parity.json'))
assert r['artifact_equal'] is True
assert r['quality_gate']=='mapped'
assert r['cutover_eligible'] is True
print('checkpoint parity verified')
PY
If you used only the local path, no cloud or enterprise cleanup is necessary. If you used live source/GitHub credentials, remove temporary tokens, close or delete the disposable migration PR/repository if authorized, and verify that no source deployment permission was broadened.
10. What Chapter 35 adds—and the bridge to Chapter 36
This chapter adds migration discipline to the production operating model: syntax conversion is subordinate to invariant preservation, same-revision evidence, explicit runner/secret/artifact mappings, one deployment authority and reversible cutover. Chapter 36 combines these controls into the capstone: a secure reusable enterprise CI/CD platform with versioned contracts, governed runners, provenance, deployment controls, observability and recovery.
Knowledge check
Why should an unsupported migration feature fail closed in the checkpoint?
Because silently omitting it can create a false-green target pipeline. A visible blocking TODO/failure preserves the missing contract until mapped.
Which two items must match before artifact parity is meaningful?
At minimum the immutable source revision/input set and the artifact content digest or equivalent semantic output.
What belongs in a secret-mapping evidence file?
Secret names, intended scopes, consumers and replacement mechanism, not secret values.
During dual-run validation, which system should deploy?
Exactly one authorized system; the other should remain read-only for the target.
What makes rollback safe?
A known previous authority/path and exact rollback target, explicit trigger/owner, and verification that only one deployer is active.
Official references and version notes
- Automating migration with GitHub Actions Importer — Current Importer commands, prerequisites, supported platforms and review warning.
- GitHub Actions Importer reference — Supplemental settings and migration-reference material.
- Custom transformers — Current custom transformer model for unsupported tasks, runners and variables.
- Migrating to GitHub Actions — Automated and manual migration guidance.
- Secure use reference — Trust-boundary and least-privilege guidance applicable during cutover.
Keep the academy open
Support free, practical DevOps education.
Every lesson is designed to remain readable in a browser, downloadable from GitHub, and usable without a paid learning platform. Contributions help expand and maintain the curriculum.
0x716c4Ab160C4B66F31a28AE2448BfF68fc3a2ef0Send only Ethereum/ERC-20 compatible assets to this
address.