Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Select an option

  • Save lassebenni/9753a184333d4688fb4c4d6ac5f280aa to your computer and use it in GitHub Desktop.

Select an option

Save lassebenni/9753a184333d4688fb4c4d6ac5f280aa to your computer and use it in GitHub Desktop.
Code Explainer: Week 15 data-ci-cd deploy jobs
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Code Explainer: data-ci-cd deploy jobs</title>
<style>
* { margin: 0; padding: 0; box-sizing: border-box; }
body {
background: #0d1117;
display: flex;
justify-content: center;
align-items: flex-start;
min-height: 100vh;
font-family: 'SF Pro Text', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
padding: 12px;
color: #c9d1d9;
}
.explainer-container {
width: 100%;
max-width: 860px;
background: #161b22;
border-radius: 10px;
overflow: hidden;
box-shadow: 0 16px 36px rgba(0,0,0,0.6);
border: 1px solid #30363d;
display: flex;
flex-direction: column;
}
.titlebar {
background: #0d1117;
padding: 10px 16px;
display: flex;
align-items: center;
gap: 8px;
border-bottom: 1px solid #21262d;
user-select: none;
}
.dot { width: 12px; height: 12px; border-radius: 50%; }
.dot.r { background: #ff5f56; }
.dot.y { background: #ffbd2e; }
.dot.g { background: #27c93f; }
.titlebar .title {
color: #8b949e;
font-size: 13px;
flex: 1;
text-align: center;
font-family: 'SF Mono', 'Fira Code', monospace;
font-weight: 500;
}
.code-body {
padding: 14px 0;
font-family: 'SF Mono', 'Fira Code', 'Menlo', monospace;
font-size: 12px;
line-height: 1.55;
overflow-x: auto;
background: #0d1117;
max-height: 380px;
overflow-y: auto;
}
.code-line {
display: flex;
padding: 2px 16px;
cursor: pointer;
border-left: 3px solid transparent;
transition: background 0.15s ease;
}
.code-line.annotated { border-left-color: #1f6feb; background: rgba(31,111,235,0.06); }
.code-line.annotated:hover { background: rgba(31,111,235,0.22); }
.code-line.annotated.active { background: rgba(56,139,253,0.28); border-left-color: #58a6ff; }
.line-num { width: 40px; color: #484f58; text-align: right; padding-right: 16px; flex-shrink: 0; }
.line-content { white-space: pre; flex: 1; }
.file-sep {
padding: 8px 16px;
color: #8b949e;
font-size: 11px;
text-transform: uppercase;
letter-spacing: 0.04em;
border-top: 1px solid #21262d;
border-bottom: 1px solid #21262d;
background: #161b22;
}
.kwd { color: #ff7b72; font-weight: 600; }
.fn { color: #d2a8ff; }
.str { color: #a5d6ff; }
.cmnt { color: #8b949e; font-style: italic; }
.var { color: #ffa657; }
.jja { color: #79c0ff; font-weight: 600; }
.explanation-dock {
background: #161b22;
border-top: 1px solid #30363d;
padding: 16px 20px;
min-height: 120px;
}
.badge {
font-size: 11px;
text-transform: uppercase;
font-weight: 700;
padding: 2px 8px;
border-radius: 12px;
}
.badge.key { background: rgba(255,166,87,0.15); color: #ffa657; border: 1px solid rgba(255,166,87,0.3); }
.badge.delta { background: rgba(56,139,253,0.15); color: #58a6ff; border: 1px solid rgba(56,139,253,0.3); }
.badge.dbt { background: rgba(46,160,67,0.15); color: #3fb950; border: 1px solid rgba(46,160,67,0.3); }
.dock-header { display: flex; align-items: center; gap: 10px; margin-bottom: 6px; }
.dock-title { font-size: 14px; font-weight: 600; color: #f0f6fc; }
.dock-body { font-size: 13px; line-height: 1.5; color: #c9d1d9; }
.hint-text { font-size: 13px; color: #8b949e; }
</style>
</head>
<body>
<div class="explainer-container">
<div class="titlebar">
<span class="dot r"></span><span class="dot y"></span><span class="dot g"></span>
<span class="title">.github/workflows/data-ci-cd.yaml β€” merge deploy</span>
</div>
<div class="code-body">
<div class="file-sep">top-level env (literals β€” edit once)</div>
<div class="code-line annotated" data-key="literal" onclick="selectLine(this,'literal')" onmouseenter="selectLine(this,'literal')"><span class="line-num">52</span><span class="line-content"> <span class="var">ACA_INGEST_JOB</span>: job-fp-ingest</span></div>
<div class="code-line annotated" data-key="literal" onclick="selectLine(this,'literal')" onmouseenter="selectLine(this,'literal')"><span class="line-num">57</span><span class="line-content"> <span class="var">SOURCE_API_URL</span>: https://www.arbeitnow.com/api/job-board-api</span></div>
<div class="file-sep">deploy-prod (merge to main only)</div>
<div class="code-line annotated" data-key="gate" onclick="selectLine(this,'gate')" onmouseenter="selectLine(this,'gate')"><span class="line-num">268</span><span class="line-content"> <span class="kwd">if</span>: github.ref == <span class="str">'refs/heads/main'</span> &amp;&amp; github.event_name != <span class="str">'pull_request'</span></span></div>
<div class="code-line annotated" data-key="image" onclick="selectLine(this,'image')" onmouseenter="selectLine(this,'image')"><span class="line-num">291</span><span class="line-content"> image=<span class="str">"$REGISTRY/pipeline:${{ github.sha }}"</span></span></div>
<div class="code-line annotated" data-key="prod_env" onclick="selectLine(this,'prod_env')" onmouseenter="selectLine(this,'prod_env')"><span class="line-num">300</span><span class="line-content"> env_vars=<span class="str">"SOURCE_API_URL=${{ env.SOURCE_API_URL }} \</span></span></div>
<div class="code-line annotated" data-key="prod_env" onclick="selectLine(this,'prod_env')" onmouseenter="selectLine(this,'prod_env')"><span class="line-num">302</span><span class="line-content"><span class="str"> LANDING_CONTAINER=prod \</span></span></div>
<div class="code-line annotated" data-key="prod_env" onclick="selectLine(this,'prod_env')" onmouseenter="selectLine(this,'prod_env')"><span class="line-num">303</span><span class="line-content"><span class="str"> LANDING_PREFIX=raw \</span></span></div>
<div class="code-line annotated" data-key="update" onclick="selectLine(this,'update')" onmouseenter="selectLine(this,'update')"><span class="line-num">309</span><span class="line-content"> az containerapp job update -g <span class="str">"$RG"</span> -n <span class="str">"$JOB"</span> \</span></div>
<div class="code-line annotated" data-key="update" onclick="selectLine(this,'update')" onmouseenter="selectLine(this,'update')"><span class="line-num">310</span><span class="line-content"> --image <span class="str">"$image"</span> --set-env-vars $env_vars -o none</span></div>
<div class="file-sep">deploy-dev (same SHA, different landing)</div>
<div class="code-line annotated" data-key="dev_job" onclick="selectLine(this,'dev_job')" onmouseenter="selectLine(this,'dev_job')"><span class="line-num">350</span><span class="line-content"> <span class="var">JOB</span>: job-fp-ingest-dev</span></div>
<div class="code-line annotated" data-key="dev_env" onclick="selectLine(this,'dev_env')" onmouseenter="selectLine(this,'dev_env')"><span class="line-num">361</span><span class="line-content"> env_vars=<span class="str">"SOURCE_API_URL=${{ env.SOURCE_API_URL }} \</span></span></div>
<div class="code-line annotated" data-key="dev_env" onclick="selectLine(this,'dev_env')" onmouseenter="selectLine(this,'dev_env')"><span class="line-num">363</span><span class="line-content"><span class="str"> LANDING_CONTAINER=dev \</span></span></div>
<div class="code-line annotated" data-key="dev_env" onclick="selectLine(this,'dev_env')" onmouseenter="selectLine(this,'dev_env')"><span class="line-num">364</span><span class="line-content"><span class="str"> LANDING_PREFIX=aca-dev \</span></span></div>
</div>
<div class="explanation-dock">
<div class="hint-text" id="hint">πŸ’‘ Hover or tap blue lines. Layer 3 owns the image tag and ACA job env β€” not Airflow Variables.</div>
<div id="dockContent" style="display:none;">
<div class="dock-header">
<span class="badge key" id="dockBadge">key</span>
<span class="dock-title" id="dockTitle"></span>
</div>
<div class="dock-body" id="dockBody"></div>
</div>
</div>
</div>
<script>
const explanations = {
literal: {
type: 'key', badge: 'Literals',
title: 'SOURCE_API_URL lives in the workflow file',
body: 'Team Azure IDs and the feed URL are top-level env literals (not GitHub repository Variables). Change the URL once here; both deploy jobs read ${{ env.SOURCE_API_URL }}. A PR can review the swap in one diff.'
},
gate: {
type: 'delta', badge: 'OIDC gate',
title: 'Deploy only on merge to main',
body: 'Azure trusts tokens minted for refs/heads/main of your repo. A PR cannot update the job β€” the exchange fails before az runs. Merging is the deploy.'
},
image: {
type: 'dbt', badge: 'ACR',
title: 'Point the job at pipeline:sha',
body: 'build already pushed pipeline:<commit-sha> (and latest). Deploy always pins the SHA so a bad number traces to exact code. A job on latest was pointed by hand.'
},
prod_env: {
type: 'key', badge: 'Prod landing',
title: 'job-fp-ingest writes prod/raw',
body: 'Same SOURCE_API_URL as deploy-dev. LANDING_CONTAINER=prod and LANDING_PREFIX=raw are what Mode 4 reads. Edit only these job names β€” do not invent a third ACA job for a new API.'
},
update: {
type: 'delta', badge: 'az update',
title: 'Image + env in one call',
body: 'az containerapp job update sets the image and --set-env-vars together. Until this step is green after your URL PR, Mode 2 and Mode 4 still hit the previous feed.'
},
dev_job: {
type: 'delta', badge: 'Dev job',
title: 'job-fp-ingest-dev is a fixed name',
body: 'Mode 2 and Mode 3 start this job. CI keeps it on the same SHA as prod; only landing differs.'
},
dev_env: {
type: 'key', badge: 'aca-dev',
title: 'Same URL, shared staging landing',
body: 'LANDING_CONTAINER=dev and LANDING_PREFIX=aca-dev. Same SOURCE_API_URL literal as prod. Your laptop .env never overrides this β€” only a successful deploy-dev does.'
}
};
function selectLine(el, key) {
const exp = explanations[key];
if (!exp) return;
document.querySelectorAll('.code-line').forEach(l => l.classList.remove('active'));
document.querySelectorAll(`.code-line[data-key="${key}"]`).forEach(l => l.classList.add('active'));
document.getElementById('hint').style.display = 'none';
document.getElementById('dockContent').style.display = 'block';
document.getElementById('dockBadge').textContent = exp.badge;
document.getElementById('dockBadge').className = 'badge ' + exp.type;
document.getElementById('dockTitle').textContent = exp.title;
document.getElementById('dockBody').textContent = exp.body;
}
</script>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment