<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/"><channel><title>Reproducibility on Tarragon</title><link>https://tarrragon.github.io/blog/tags/reproducibility/</link><description>Recent content in Reproducibility on Tarragon</description><generator>Hugo -- gohugo.io</generator><language>zh-TW</language><copyright>Tarragon (CC BY 4.0)</copyright><lastBuildDate>Thu, 21 May 2026 00:00:00 +0000</lastBuildDate><atom:link href="https://tarrragon.github.io/blog/tags/reproducibility/index.xml" rel="self" type="application/rss+xml"/><item><title>Artifact 與可重播性</title><link>https://tarrragon.github.io/blog/ci/artifact-reproducibility/</link><pubDate>Thu, 21 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/ci/artifact-reproducibility/</guid><description>&lt;p>Artifact 可重播性的核心責任是讓每次發布都能追到同一份被驗證的產物。CI/CD 不只是在 runner 上跑命令；它要回答「測試通過的是哪份內容」「發布出去的是哪份內容」「事故時如何找回同一份內容」。&lt;/p>
&lt;h2 id="概念定位">概念定位&lt;/h2>
&lt;p>&lt;a href="https://tarrragon.github.io/blog/ci/knowledge-cards/artifact/" data-link-title="Artifact" data-link-desc="說明 CI/CD 中可被驗證、保存與發布的交付產物">Artifact&lt;/a> 是 CI/CD 流程中的交付單位。前端可能是 &lt;code>dist/&lt;/code>，後端可能是 binary 或 image，App 可能是 IPA / AAB，資料任務可能是 DAG 或 query package；不同形式的 artifact 都承擔同一個責任：把 source change 轉成可驗證、可保存、可推進的產物。&lt;/p>
&lt;table>
 &lt;thead>
 &lt;tr>
 &lt;th>能力&lt;/th>
 &lt;th>責任&lt;/th>
 &lt;th>判讀訊號&lt;/th>
 &lt;/tr>
 &lt;/thead>
 &lt;tbody>
 &lt;tr>
 &lt;td>Build once&lt;/td>
 &lt;td>同一次變更只產生一次正式 artifact&lt;/td>
 &lt;td>build job 是否保存產物&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Verify once&lt;/td>
 &lt;td>測試同一份 artifact&lt;/td>
 &lt;td>test job 是否 download artifact&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/ci/knowledge-cards/artifact-handoff/" data-link-title="Artifact Handoff" data-link-desc="說明測試與部署如何共用同一份可追溯產物">Artifact handoff&lt;/a>&lt;/td>
 &lt;td>在 job / workflow 間交接產物&lt;/td>
 &lt;td>checksum、digest、version 是否一致&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Promote same artifact&lt;/td>
 &lt;td>staging / production 推進同一份&lt;/td>
 &lt;td>production 是否重新 build&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Recover artifact&lt;/td>
 &lt;td>事故時找回上一份可用產物&lt;/td>
 &lt;td>retention、release、registry 是否保留&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;p>Build once 的責任是降低環境漂移。若 test job 與 deploy job 各自 build，一個 lockfile、環境變數或 base image 差異就能讓兩份產物不同；此時 CI 綠燈不再能證明 production 內容可信。&lt;/p>
&lt;p>Verify once 的責任是把測試結果綁到具體產物。測試應輸出 artifact identity，例如 checksum、&lt;a href="https://tarrragon.github.io/blog/ci/knowledge-cards/image-digest/" data-link-title="Image Digest" data-link-desc="說明 container image digest 如何作為不可變產物身分，支撐掃描、推進與 runtime 追溯">Image Digest&lt;/a>、release asset name 或 bundle version，讓 reviewer 能確認紅綠燈對應哪份內容。&lt;/p>
&lt;p>&lt;a href="https://tarrragon.github.io/blog/ci/knowledge-cards/artifact-handoff/" data-link-title="Artifact Handoff" data-link-desc="說明測試與部署如何共用同一份可追溯產物">Artifact handoff&lt;/a> 的責任是在 job 邊界保留身分。Upload / download artifact、registry digest、release asset、package registry 與 object storage 都可以做 handoff；重點是交接時沿用既有產物。&lt;/p>
&lt;p>Promote same artifact 的責任是讓環境差異集中在設定與流量。Staging 驗證過的 image、package 或 static artifact 應被推進到 production；若 production 重新 build，就需要重新驗證 production 那份產物。&lt;/p>
&lt;p>Recover artifact 的責任是讓 rollback 有實體目標。沒有保留 artifact 的 rollback 會變成「從舊 commit 重新 build」，這會受到依賴、base image、registry、toolchain 與時間漂移影響。&lt;/p>
&lt;h2 id="可重播性檢查">可重播性檢查&lt;/h2>
&lt;p>可重播性檢查的責任是確認產物身分與建置條件足夠明確。嚴格 reproducible build 很難在所有專案做到，但 CI/CD 至少要達到「同一次 workflow 的產物可以被查詢、保存、驗證與重新部署」。&lt;/p>
&lt;table>
 &lt;thead>
 &lt;tr>
 &lt;th>檢查項&lt;/th>
 &lt;th>判讀問題&lt;/th>
 &lt;th>常見做法&lt;/th>
 &lt;/tr>
 &lt;/thead>
 &lt;tbody>
 &lt;tr>
 &lt;td>Source&lt;/td>
 &lt;td>artifact 對應哪個 commit&lt;/td>
 &lt;td>embed git SHA / release version&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Dependency&lt;/td>
 &lt;td>dependency 是否固定&lt;/td>
 &lt;td>lockfile、base image digest&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Environment&lt;/td>
 &lt;td>build 環境是否固定&lt;/td>
 &lt;td>runner image、toolchain version&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Identity&lt;/td>
 &lt;td>artifact 是否有不可變身分&lt;/td>
 &lt;td>checksum、digest、signature&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Retention&lt;/td>
 &lt;td>artifact 保留多久&lt;/td>
 &lt;td>release asset、registry retention&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Provenance&lt;/td>
 &lt;td>artifact 如何被產生&lt;/td>
 &lt;td>workflow run、&lt;a href="https://tarrragon.github.io/blog/ci/knowledge-cards/sbom/" data-link-title="SBOM" data-link-desc="說明 Software Bill of Materials 如何揭露 artifact 內含元件，支撐供應鏈掃描與例外治理">SBOM&lt;/a>、attestation&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;p>這張表讓團隊知道自己目前在哪個成熟度。初期可以先做到 source、dependency、identity；高治理場景再補 SBOM、signature 與 provenance。&lt;/p></description><content:encoded><![CDATA[<p>Artifact 可重播性的核心責任是讓每次發布都能追到同一份被驗證的產物。CI/CD 不只是在 runner 上跑命令；它要回答「測試通過的是哪份內容」「發布出去的是哪份內容」「事故時如何找回同一份內容」。</p>
<h2 id="概念定位">概念定位</h2>
<p><a href="/blog/ci/knowledge-cards/artifact/" data-link-title="Artifact" data-link-desc="說明 CI/CD 中可被驗證、保存與發布的交付產物">Artifact</a> 是 CI/CD 流程中的交付單位。前端可能是 <code>dist/</code>，後端可能是 binary 或 image，App 可能是 IPA / AAB，資料任務可能是 DAG 或 query package；不同形式的 artifact 都承擔同一個責任：把 source change 轉成可驗證、可保存、可推進的產物。</p>
<table>
  <thead>
      <tr>
          <th>能力</th>
          <th>責任</th>
          <th>判讀訊號</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>Build once</td>
          <td>同一次變更只產生一次正式 artifact</td>
          <td>build job 是否保存產物</td>
      </tr>
      <tr>
          <td>Verify once</td>
          <td>測試同一份 artifact</td>
          <td>test job 是否 download artifact</td>
      </tr>
      <tr>
          <td><a href="/blog/ci/knowledge-cards/artifact-handoff/" data-link-title="Artifact Handoff" data-link-desc="說明測試與部署如何共用同一份可追溯產物">Artifact handoff</a></td>
          <td>在 job / workflow 間交接產物</td>
          <td>checksum、digest、version 是否一致</td>
      </tr>
      <tr>
          <td>Promote same artifact</td>
          <td>staging / production 推進同一份</td>
          <td>production 是否重新 build</td>
      </tr>
      <tr>
          <td>Recover artifact</td>
          <td>事故時找回上一份可用產物</td>
          <td>retention、release、registry 是否保留</td>
      </tr>
  </tbody>
</table>
<p>Build once 的責任是降低環境漂移。若 test job 與 deploy job 各自 build，一個 lockfile、環境變數或 base image 差異就能讓兩份產物不同；此時 CI 綠燈不再能證明 production 內容可信。</p>
<p>Verify once 的責任是把測試結果綁到具體產物。測試應輸出 artifact identity，例如 checksum、<a href="/blog/ci/knowledge-cards/image-digest/" data-link-title="Image Digest" data-link-desc="說明 container image digest 如何作為不可變產物身分，支撐掃描、推進與 runtime 追溯">Image Digest</a>、release asset name 或 bundle version，讓 reviewer 能確認紅綠燈對應哪份內容。</p>
<p><a href="/blog/ci/knowledge-cards/artifact-handoff/" data-link-title="Artifact Handoff" data-link-desc="說明測試與部署如何共用同一份可追溯產物">Artifact handoff</a> 的責任是在 job 邊界保留身分。Upload / download artifact、registry digest、release asset、package registry 與 object storage 都可以做 handoff；重點是交接時沿用既有產物。</p>
<p>Promote same artifact 的責任是讓環境差異集中在設定與流量。Staging 驗證過的 image、package 或 static artifact 應被推進到 production；若 production 重新 build，就需要重新驗證 production 那份產物。</p>
<p>Recover artifact 的責任是讓 rollback 有實體目標。沒有保留 artifact 的 rollback 會變成「從舊 commit 重新 build」，這會受到依賴、base image、registry、toolchain 與時間漂移影響。</p>
<h2 id="可重播性檢查">可重播性檢查</h2>
<p>可重播性檢查的責任是確認產物身分與建置條件足夠明確。嚴格 reproducible build 很難在所有專案做到，但 CI/CD 至少要達到「同一次 workflow 的產物可以被查詢、保存、驗證與重新部署」。</p>
<table>
  <thead>
      <tr>
          <th>檢查項</th>
          <th>判讀問題</th>
          <th>常見做法</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>Source</td>
          <td>artifact 對應哪個 commit</td>
          <td>embed git SHA / release version</td>
      </tr>
      <tr>
          <td>Dependency</td>
          <td>dependency 是否固定</td>
          <td>lockfile、base image digest</td>
      </tr>
      <tr>
          <td>Environment</td>
          <td>build 環境是否固定</td>
          <td>runner image、toolchain version</td>
      </tr>
      <tr>
          <td>Identity</td>
          <td>artifact 是否有不可變身分</td>
          <td>checksum、digest、signature</td>
      </tr>
      <tr>
          <td>Retention</td>
          <td>artifact 保留多久</td>
          <td>release asset、registry retention</td>
      </tr>
      <tr>
          <td>Provenance</td>
          <td>artifact 如何被產生</td>
          <td>workflow run、<a href="/blog/ci/knowledge-cards/sbom/" data-link-title="SBOM" data-link-desc="說明 Software Bill of Materials 如何揭露 artifact 內含元件，支撐供應鏈掃描與例外治理">SBOM</a>、attestation</td>
      </tr>
  </tbody>
</table>
<p>這張表讓團隊知道自己目前在哪個成熟度。初期可以先做到 source、dependency、identity；高治理場景再補 SBOM、signature 與 provenance。</p>
<h2 id="常見反模式">常見反模式</h2>
<p>反模式的共同問題是讓「綠燈」失去指向性。當綠燈不知道對應哪份產物，CI/CD 只剩下命令執行紀錄。</p>
<table>
  <thead>
      <tr>
          <th>反模式</th>
          <th>風險</th>
          <th>替代做法</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>test 與 deploy 各自 build</td>
          <td>測試與發布內容漂移</td>
          <td>build once，artifact handoff</td>
      </tr>
      <tr>
          <td>rollback 重新 build 舊 commit</td>
          <td>舊 commit 可能產出不同內容</td>
          <td>保留上一份 release artifact</td>
      </tr>
      <tr>
          <td>只用人類可讀 tag</td>
          <td>tag 可被覆寫或語意不精準</td>
          <td>搭配 checksum / digest</td>
      </tr>
      <tr>
          <td>artifact retention 太短</td>
          <td>事故時找不到可回復版本</td>
          <td>對 release artifact 設長期保留</td>
      </tr>
  </tbody>
</table>
<h2 id="下一步路由">下一步路由</h2>
<ul>
<li>Artifact 術語：讀 <a href="/blog/ci/knowledge-cards/artifact/" data-link-title="Artifact" data-link-desc="說明 CI/CD 中可被驗證、保存與發布的交付產物">Artifact</a>。</li>
<li>Artifact handoff：讀 <a href="/blog/ci/knowledge-cards/artifact-handoff/" data-link-title="Artifact Handoff" data-link-desc="說明測試與部署如何共用同一份可追溯產物">Artifact Handoff</a>。</li>
<li>Gate 邊界：讀 <a href="../ci-gate-workflow-boundary/">CI gate 與 workflow 邊界</a>。</li>
</ul>
]]></content:encoded></item></channel></rss>