Thuta Learning
CI/CD with GitHub Actions
IntermediateDevOps & Toolsbeginner

Artifacts နှင့် Job များအကြား Data လွှဲပြောင်းခြင်း

ဒီခန်းပြီးရင် ဘာတတ်သွားမလဲ

  • Artifacts နှင့် Job များအကြား Data လွှဲပြောင်းခြင်း concept ကို နားလည်ရှင်းပြနိုင်ရန်
  • Diagram ကို ဖတ်ပြီး pipeline ထဲမှာ job တွေ ဘယ်လိုစီးဆင်းပြီး ဘာက gate လုပ်သလဲ ခြေရာခံနိုင်ရန်
  • Workflow file ကို ဖတ်ပြီး ဘယ် job တွေ ဘယ်အစဉ်လိုက် run မလဲ ကြိုတင်ပြောနိုင်ရန်

နားလည်ထားရမယ့် အချက်

Workflow ထဲက job တစ်ခုစီသည် ကိုယ်ပိုင် runner ရသည်။ build job ပြီးဆုံးသည်နှင့် အဲဒီ machine သည် ဖျက်သိမ်းခံရသည် — filesystem၊ environment variable၊ node_modules အားလုံး ပါသွားသည်။ needs: build ဖြင့် ကြေညာထားသော deploy job သည် အစီအစဉ်တစ်ခုမှလွဲ၍ ဘာမှ အမွေမဆက်ခံပါ။ ဒါက လူတွေကို အမြဲ ချောက်တွန်းတတ်သည်၊ အကြောင်းက job တစ်ခုအတွင်း step များသည် working directory ကို မျှဝေသုံးနေသဖြင့် workflow တစ်ခုလုံးသည် ဆက်တိုက်တည်ရှိသော machine တစ်လုံးလို ခံစားရသောကြောင့်ဖြစ်သည်။ တကယ်တော့ မဟုတ်ပါ — ကြားထဲတွင် dependency graph တစ်ခု ဆွဲထားသော သီးခြား machine အစုတစ်ခုသာ ဖြစ်သည်။

GitHub သည် အဲဒီ နယ်နိမိတ်ကို ဖြတ်ကူးရန် နည်းလမ်းနှစ်မျိုး ပေးထားပြီး၊ အရွယ်အစား မတူညီသော အရာများအတွက် ဖြစ်သည်။ Artifact များသည် file များဖြစ်သည်။ upload-artifact@v4 သည် path တစ်ခုကို zip လုပ်၍ workflow run နှင့် တွဲသိမ်းပြီး၊ နောက် job တစ်ခုရှိ download-artifact@v4 က runner အသစ်ပေါ်သို့ ပြန်ဆွဲချသည်။ Compile လုပ်ပြီးသား output၊ test report၊ coverage file၊ Playwright screenshot များ ဒီနည်းဖြင့် ခရီးသွားသည်။ Job output များကတော့ string များဖြစ်သည်။ Job တစ်ခုသည် job level တွင် outputs: ကို ကြေညာပြီး၊ $GITHUB_OUTPUT သို့ key=value ရေးထားသော step နှင့် ချိတ်ကာ၊ အောက်ဘက် job က needs.<job>.outputs.<name> ဖြင့် ဖတ်သည်။ Version နံပါတ်၊ image tag၊ တွက်ချက်ထားသော flag များသည် ဒီနေရာတွင် ရှိသင့်သည်။

မှားရွေးမိခြင်းသည် အဖြစ်များဆုံး အမှားဖြစ်သည်။ Version string တစ်ခု ရွှေ့ဖို့ တစ်ကြောင်းတည်းသော file ကို artifact အဖြစ် upload လုပ်တာ အလုပ်ဖြစ်သော်လည်း run တိုင်းသို့ zip round-trip တစ်ခု ထပ်ဖြည့်လိုက်ခြင်းဖြစ်သည်။ Directory တစ်ခုကို job outputs ဖြင့် ရွှေ့ဖို့ ကြိုးစားလျှင်တော့ လုံးဝ အလုပ်မဖြစ်ပါ — output များသည် string များဖြစ်ပြီး၊ အရွယ်အစား ကန့်သတ်ချက်ရှိကာ log ထဲတွင် မြင်နိုင်သည်။

Artifact များသည် သင့် account ပေါ်တွင် storage ကုန်ကျစေပြီး အရွယ်အစားနှင့် အချိန်အလိုက် ငွေတောင်းခံသည် — ဒါကြောင့် retention-days ရှိသည်။ Default retention သည် ရက်ကြာသည်၊ ညတိုင်း bundle ကြီးတစ်ခု တင်နေသော nightly job တစ်ခုသည် ဘယ်သူမှ မကြည့်သော bill တစ်ခုကို တိတ်တဆိတ် တည်ဆောက်နေမည် ဖြစ်သည်။

text
ARTIFACT HANDOFF BETWEEN JOBS
-----------------------------
  JOB build (runner A)              JOB deploy (runner B)
  +------------------------+        +------------------------+
  | npm ci                 |        | download-artifact      |
  | npm run build -> dist/ |        |   name: dist -> dist/  |
  | upload-artifact        |        | ./deploy.sh dist       |
  |   name: dist           |        +------------------------+
  +------------------------+                    ^
              |                                 |
              v                                 |
  +--------------------------------------------------------+
  | artifact store    name: dist    retention-days: 7       |
  +--------------------------------------------------------+

  job outputs (small strings, no storage cost):
    build.outputs.version ---> needs.build.outputs.version

  runner A is DESTROYED before runner B starts.
  Nothing on disk carries over; only artifacts and outputs do.

လက်တွေ့ scenario နဲ့ ချိတ်ကြည့်မယ်

ပုံမှန် ပုံစံတစ်ခုမှာ compile လုပ်သော build job တစ်ခုနှင့် compile လုပ်ပြီးသားအတိုင်း ပို့ဆောင်သော deploy job တစ်ခု ဖြစ်သည်။ အရေးကြီးသော ဂုဏ်သတ္တိမှာ deploy သည် ဘယ်တော့မှ ပြန် build မလုပ်ခြင်းဖြစ်သည်။ ပြန် build လုပ်လျှင် ဒုတိယမြောက် artifact တစ်ခုကို deploy လုပ်နေခြင်းဖြစ်ပြီး၊ သင့် build ထဲရှိ nondeterminism တစ်ခုခု — timestamp၊ မိနစ်တစ်မိနစ်ကွာပြီး resolve လုပ်ထားသော lockfile၊ runner image ကွဲလွဲမှု — က သင်စမ်းသပ်ခဲ့သည့်အရာနှင့် သင်ပို့ဆောင်လိုက်သည့်အရာကို bundle နှစ်ခု ဖြစ်သွားစေသည်။

ဒါကြောင့် build သည် npm run build ကို run ပြီး dist/ ကို dist ဟူသော အမည်ဖြင့် artifact အဖြစ် upload လုပ်ကာ၊ package version ကို သီးခြားစီ $GITHUB_OUTPUT သို့ တွက်ထည့်သည်။ deploy job သည် needs: build ကြေညာပြီး dist artifact ကို ./dist သို့ ဒေါင်းလုဒ်လုပ်ကာ needs.build.outputs.version ကို deploy script သို့ ပေးပို့သည်။

နှလုံးသွင်းထားသင့်သော အချက်နှစ်ခု ရှိသည်။ Output ရေးသည့်အခါ $GITHUB_OUTPUT file ကို သုံးရမည်ဖြစ်ပြီး၊ security အကြောင်းပြချက်ဖြင့် ပိတ်လိုက်ပြီးဖြစ်သော set-output command ဟောင်းကို မသုံးရပါ။ ထို့အပြင် upload-artifact@v4 သည် v3 လို အမည်တူ artifact သို့ ထပ်ဖြည့်ခြင်း မလုပ်တော့ပါ — run တစ်ခုအတွင်း အမည်တူဖြင့် နှစ်ကြိမ် upload လုပ်လျှင် error ဖြစ်သည်။ ဒါကြောင့် matrix job များကို report-${{ matrix.os }} ကဲ့သို့ သီးခြားအမည်များ ပေးပြီး၊ လိုအပ်လျှင် နောက်မှ ပေါင်းစပ်ပါ။

အတူတူ စမ်းရေးကြည့်မယ်

yaml
name: Build then deploy

on:
  push:
    branches: [main]

jobs:
  build:
    runs-on: ubuntu-latest
    outputs:
      version: ${{ steps.meta.outputs.version }}
    steps:
      - uses: actions/checkout@v4

      - uses: actions/setup-node@v4
        with:
          node-version: '20'
          cache: npm

      - name: Install dependencies
        run: npm ci

      - name: Build
        run: npm run build

      - name: Record the package version as a job output
        id: meta
        run: |
          VERSION=$(node -p "require('./package.json').version")
          echo "version=$VERSION" >> "$GITHUB_OUTPUT"

      - name: Upload the build output
        uses: actions/upload-artifact@v4
        with:
          name: dist
          path: dist/
          retention-days: 7

  deploy:
    needs: build
    runs-on: ubuntu-latest
    steps:
      - name: Download the build output
        uses: actions/download-artifact@v4
        with:
          name: dist
          path: dist

      - name: Deploy exactly what was built
        run: ./scripts/deploy.sh dist "${{ needs.build.outputs.version }}"
You should see
Job နှစ်ခုသည် ပြိုင်တူမဟုတ်ဘဲ အစဉ်လိုက် run သည် — deploy သည် needs: build ကြေညာထားသဖြင့် build အောင်မြင်စွာ ပြီးဆုံးမှသာ စတင်သည်။ build သည် code ကို checkout လုပ်၊ install လုပ်၊ dist/ သို့ compile လုပ်၊ package version ကို job output အဖြစ် မှတ်တမ်းတင်ပြီး dist/ ကို run ရဲ့ artifact store သို့ ခုနစ်ရက် retention ဖြင့် upload လုပ်သည်။ build ကျရှုံးလျှင် deploy ကို လုံးဝ skip လုပ်ပြီး deployment မဖြစ်ပေါ်ပါ။ build အောင်မြင်လျှင် deploy သည် filesystem အလွတ်ရှိသော runner အသစ်လုံးဝပေါ်တွင် စတင်သည် — repository ကို လုံးဝ checkout မလုပ်ပါ — ထို့ကြောင့် အဲဒီနေရာတွင် dist/ ရှိနေရခြင်း၏ တစ်ခုတည်းသော အကြောင်းရင်းမှာ download-artifact step ဖြစ်သည်။ Version string သည် file တစ်ခုမှတစ်ဆင့်မဟုတ်ဘဲ needs.build.outputs.version မှတစ်ဆင့် deploy script သို့ ရောက်သည်။ Upload လုပ်ထားသော artifact ကို run ရဲ့ summary စာမျက်နှာမှ ခုနစ်ရက်အတွင်း ဒေါင်းလုဒ်လုပ်နိုင်ပြီး၊ ဒါကပင် ဒီ pattern ကို deployment အပြင် test report အတွက်ပါ အသုံးဝင်စေခြင်း ဖြစ်သည်။

၅ မိနစ် စမ်းကြည့်

ရှိပြီးသား job တစ်ခုတည်း workflow ကို build နှင့် deploy ဟူ၍ ခွဲပါ။ ပထမဦးစွာ download step မပါဘဲ deploy ကို run ပြီး၊ ဒုတိယ runner ပေါ်တွင် dist/ တကယ် မရှိကြောင်း အတည်ပြုပါ။ ထို့နောက် artifact upload/download ကို ထည့်ပြီး အလုပ်ဖြစ်အောင် လုပ်ပါ။ နောက်ဆုံးတွင် လက်ရှိ file ထဲသို့ ရေးနေသော တန်ဖိုးတစ်ခု — version သို့မဟုတ် commit short SHA — ကို job output သို့ ရွှေ့ပြီး၊ retention-days ကို သင့်အဖွဲ့ တကယ်လိုအပ်သော အတိုဆုံး ကိန်းသို့ သတ်မှတ်ပါ။

သတိလေးတစ်ချက်

နောက် job တစ်ခုသည် ရှေ့ job ရေးထားသော file များကို ဖတ်နိုင်သည်ဟု ယူဆခြင်း — job တစ်ခုစီသည် runner အသစ်ဖြစ်သဖြင့် upload-artifact/download-artifact မပါလျှင် အဲဒီ directory ကို ရှိပင် မရှိပါ။

Matrix job များစွာမှ artifact name တူတူဖြင့် upload လုပ်ခြင်း — upload-artifact@v4 သည် v3 လို အမည်တူများကို မပေါင်းစပ်တော့သဖြင့် run ကျရှုံးပြီး၊ အမည်ထဲတွင် matrix တန်ဖိုးများ ပါဝင်ရန် လိုအပ်သည်။

GitHub Docs - Storing and sharing data from a workflowCI/CD with GitHub Actions

ဒီနေရာမှာ လူအများမှားတတ်တယ်

  • နောက် job တစ်ခုသည် ရှေ့ job ရေးထားသော file များကို ဖတ်နိုင်သည်ဟု ယူဆခြင်း — job တစ်ခုစီသည် runner အသစ်ဖြစ်သဖြင့် upload-artifact/download-artifact မပါလျှင် အဲဒီ directory ကို ရှိပင် မရှိပါ။
  • Matrix job များစွာမှ artifact name တူတူဖြင့် upload လုပ်ခြင်း — upload-artifact@v4 သည် v3 လို အမည်တူများကို မပေါင်းစပ်တော့သဖြင့် run ကျရှုံးပြီး၊ အမည်ထဲတွင် matrix တန်ဖိုးများ ပါဝင်ရန် လိုအပ်သည်။
  • Workflow ကို production branch ပေါ် တိုက်ရိုက်မစမ်းဘဲ branch (သို့) test repository တွင် အရင်အတည်ပြုပါ။

လေ့ကျင့်ခန်း

ရှိပြီးသား job တစ်ခုတည်း workflow ကို build နှင့် deploy ဟူ၍ ခွဲပါ။ ပထမဦးစွာ download step မပါဘဲ deploy ကို run ပြီး၊ ဒုတိယ runner ပေါ်တွင် dist/ တကယ် မရှိကြောင်း အတည်ပြုပါ။ ထို့နောက် artifact upload/download ကို ထည့်ပြီး အလုပ်ဖြစ်အောင် လုပ်ပါ။ နောက်ဆုံးတွင် လက်ရှိ file ထဲသို့ ရေးနေသော တန်ဖိုးတစ်ခု — version သို့မဟုတ် commit short SHA — ကို job output သို့ ရွှေ့ပြီး၊ retention-days ကို သင့်အဖွဲ့ တကယ်လိုအပ်သော အတိုဆုံး ကိန်းသို့ သတ်မှတ်ပါ။

You'll know it worked when: Job နှစ်ခုသည် ပြိုင်တူမဟုတ်ဘဲ အစဉ်လိုက် run သည် — deploy သည် needs: build ကြေညာထားသဖြင့် build အောင်မြင်စွာ ပြီးဆုံးမှသာ စတင်သည်။ build သည် code ကို checkout လုပ်၊ install လုပ်၊ dist/ သို့ compile လုပ်၊ package version ကို job output အဖြစ် မှတ်တမ်းတင်ပြီး dist/ ကို run ရဲ့ artifact store သို့ ခုနစ်ရက် retention ဖြင့် upload လုပ်သည်။ build ကျရှုံးလျှင် deploy ကို လုံးဝ skip လုပ်ပြီး deployment မဖြစ်ပေါ်ပါ။ build အောင်မြင်လျှင် deploy သည် filesystem အလွတ်ရှိသော runner အသစ်လုံးဝပေါ်တွင် စတင်သည် — repository ကို လုံးဝ checkout မလုပ်ပါ — ထို့ကြောင့် အဲဒီနေရာတွင် dist/ ရှိနေရခြင်း၏ တစ်ခုတည်းသော အကြောင်းရင်းမှာ download-artifact step ဖြစ်သည်။ Version string သည် file တစ်ခုမှတစ်ဆင့်မဟုတ်ဘဲ needs.build.outputs.version မှတစ်ဆင့် deploy script သို့ ရောက်သည်။ Upload လုပ်ထားသော artifact ကို run ရဲ့ summary စာမျက်နှာမှ ခုနစ်ရက်အတွင်း ဒေါင်းလုဒ်လုပ်နိုင်ပြီး၊ ဒါကပင် ဒီ pattern ကို deployment အပြင် test report အတွက်ပါ အသုံးဝင်စေခြင်း ဖြစ်သည်။

Artifacts နှင့် Job များအကြား Data လွှဲပြောင်းခြင်း | Thuta Learning