Thuta Learning
CI/CD with GitHub Actions
BasicDevOps & Toolsbeginner

Workflow File ရဲ့ ဖွဲ့စည်းပုံ

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

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

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

Workflow file တစ်ခုဟာ repository ရဲ့ .github/workflows/ directory အောက်မှာ .yml (သို့) .yaml extension နဲ့ ရှိရပါမယ်။ ဒီနေရာက ညှိလို့ရတဲ့ setting မဟုတ်ပါဘူး - GitHub က အဲဒီ directory တစ်ခုတည်းကိုပဲ ကြည့်ပါတယ်။ ဒါကြောင့် file ကို workflows/ci.yml ဒါမှမဟုတ် .github/ci.yml မှာ ထားမိရင် error တစ်ခုမှ မမြင်ရဘဲ ဘာမှ မဖြစ်ပါဘူး - ဒါက အသစ်စတဲ့သူတွေ အချိန်အကုန်ဆုံး နာရီပါပဲ။

ဖွဲ့စည်းပုံက အလွှာသုံးလွှာပါ။ အပေါ်ဆုံးမှာ name (Actions tab မှာ ပြမယ့် အမည်၊ မထည့်ရင် file path ကို သုံးပါတယ်)၊ on (ဘယ် event တွေက ဒီ workflow ကို trigger လုပ်မလဲ)၊ နဲ့ jobs (တကယ် အလုပ်လုပ်မယ့် အရာတွေ) ရှိပါတယ်။ YAML မှာ quote မခံထားတဲ့ on: ဟာ Actions အတွက် မှန်ကန်တဲ့ ရေးနည်းဖြစ်ပြီး၊ ဒါဟာ သာမန် key တစ်ခုပါပဲ။

jobs အောက်မှာ ကိုယ်ပေးထားတဲ့ id (ဥပမာ lint, test) တစ်ခုစီရှိပြီး၊ job တစ်ခုစီမှာ runs-on (ဘယ် runner image ပေါ်မှာ run မလဲ) နဲ့ steps (အစဉ်လိုက် လုပ်မယ့် အလုပ်စာရင်း) ရှိရပါမယ်။ step တစ်ခုဟာ uses ဖြစ်နိုင်သလို run လည်း ဖြစ်နိုင်ပါတယ် - uses က တခြားသူရေးထားပြီးသား action တစ်ခုကို ခေါ်သုံးတာ (input တွေကို with နဲ့ ပေးတယ်)၊ run ကတော့ runner ရဲ့ shell ထဲမှာ command တွေ တိုက်ရိုက် run တာပါ။ step တစ်ခုမှာ uses နဲ့ run နှစ်ခုလုံး တစ်ပြိုင်နက် မထားနိုင်ပါဘူး။ name ကတော့ log ထဲမှာ ဖတ်ရလွယ်အောင် ထည့်ပေးတဲ့ label ပါ။

လူအများဆုံး နားလည်မှုလွဲတာက အောက်ပါအချက်ပါ - job တွေဟာ default အားဖြင့် တစ်ပြိုင်နက်တည်း၊ သီးခြား virtual machine အသစ်တစ်လုံးစီပေါ်မှာ run ပါတယ်။ file အထက်အောက် ရေးထားလို့ အစဉ်လိုက် run မယ်လို့ မထင်ပါနဲ့။ job တစ်ခုက ဆွဲထားတဲ့ dependency တွေ၊ ဆောက်ထားတဲ့ file တွေကို နောက် job တစ်ခုက လုံးဝ မမြင်ပါဘူး။ အစဉ်လိုက် လိုချင်ရင် needs နဲ့ တိတိကျကျ ချိတ်ပေးရပါတယ်။

text
WORKFLOW > JOBS > STEPS
-----------------------
file: .github/workflows/ci.yml
+---------------------------------------------------------------+
| name: CI            on: [push, pull_request]                   |
|                                                                |
| jobs:                                                          |
|  +--------------------------+  +--------------------------+    |
|  | lint:                    |  | test:                    |    |
|  |  runs-on: ubuntu-latest  |  |  runs-on: ubuntu-latest  |    |
|  |  steps:                  |  |  steps:                  |    |
|  |   1 uses: checkout@v4    |  |   1 uses: checkout@v4    |    |
|  |   2 uses: setup-node@v4  |  |   2 uses: setup-node@v4  |    |
|  |   3 run:  npm ci         |  |   3 run:  npm ci         |    |
|  |   4 run:  npm run lint   |  |   4 run:  npm test       |    |
|  +--------------------------+  +--------------------------+    |
|        fresh VM #1                   fresh VM #2               |
|                                                                |
|   these two start AT THE SAME TIME and share no files          |
+---------------------------------------------------------------+

  uses: -> run somebody else's reusable action, inputs via with:
  run:  -> run shell commands on this runner

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

အောက်က workflow မှာ job နှစ်ခု - lint နဲ့ test - ရှိပါတယ်။ file ထဲမှာ lint က အပေါ်မှာ ရှိပေမယ့် အရင် run မယ်လို့ မဆိုလိုပါဘူး။ GitHub က နှစ်ခုလုံးကို တစ်ပြိုင်နက် စတင်ပြီး runner နှစ်လုံး သီးခြားစီ ခွဲပေးပါတယ်။ ဒါကြောင့် နှစ်ခုစလုံးမှာ checkout နဲ့ setup-node ကို ထပ်ရေးထားရတာပါ - test job က lint job ရဲ့ file တွေကို လုံးဝ မမြင်လို့ပါ။ ပထမတွေ့တဲ့အခါ ထပ်နေသလို ခံစားရပေမယ့် ဒါက runner သီးသန့်စီ ဖြစ်တဲ့ သဘောသဘာဝကို တိုက်ရိုက် ရောင်ပြန်ဟပ်နေတာပါ။

step တွေကို သေချာကြည့်ပါ။ uses: actions/checkout@v4 က input မလိုတဲ့အတွက် with မပါပါဘူး။ uses: actions/setup-node@v4 ကတော့ with: node-version: '20' လိုအပ်ပါတယ် - '20' ကို quote ခံထားတာက YAML မှာ quote မခံရင် နံပါတ်အဖြစ် ဖတ်လို့ဖြစ်ပြီး၊ '20.10' လိုမျိုးဆိုရင် ပိုဆိုးပါတယ် (float ဖြစ်သွားပြီး နောက်က သုည ပျောက်နိုင်ပါတယ်)။ ဒါကြောင့် version string တွေကို quote အမြဲ ခံပါ။

run: step တွေက runner ရဲ့ shell (Linux မှာ bash) ထဲမှာ တိုက်ရိုက် execute လုပ်ပါတယ်။ step တစ်ခုစီဟာ shell process အသစ်ဖြစ်လို့ step တစ်ခုမှာ cd လုပ်ထားတာ နောက် step ကို မလိုက်ပါဘူး - directory ပြောင်းချင်ရင် working-directory ကို သုံးပါ။ log ထဲမှာ step တစ်ခုစီက ဖွင့်လို့ရတဲ့ ခေါင်းစဉ်တစ်ခုစီ ဖြစ်လာလို့ name ရေးထားရင် ဘယ်နေရာ ကျရှုံးလဲ ချက်ချင်း တွေ့ရပါတယ်။

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

yaml
name: Anatomy Demo

on: [push]

jobs:
  lint:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - name: Set up Node.js
        uses: actions/setup-node@v4
        with:
          node-version: '20'
          cache: npm

      - run: npm ci

      - name: Lint the source
        run: npm run lint

  test:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - name: Set up Node.js
        uses: actions/setup-node@v4
        with:
          node-version: '20'
          cache: npm

      - run: npm ci

      - name: Run unit tests in the api package
        working-directory: packages/api
        run: npm test
You should see
push တိုင်းမှာ ဒီ workflow က run ပြီး job နှစ်ခုဖြစ်တဲ့ lint နဲ့ test ကို တစ်ပြိုင်နက် စတင်ပါတယ်၊ တစ်ခုစီက ubuntu-latest runner အသစ် သီးသန့်စီ ရပါတယ်။ Actions tab မှာ job နှစ်ခု ဘေးချင်းယှဉ်လျက် ပေါ်နေမှာဖြစ်ပြီး တစ်ခုက ကျရှုံးလည်း ကျန်တစ်ခုက ဆက်ပြီး run နေပါလိမ့်မယ်။ job တစ်ခုစီအတွင်းမှာတော့ step တွေက အစဉ်လိုက် run ပြီး၊ step တစ်ခု ကျရှုံးရင် အဲဒီ job ရဲ့ ကျန် step တွေကို ကျော်ပစ်ပါတယ်။ test job ရဲ့ npm test က packages/api directory ထဲမှာ run ပါတယ်။ job နှစ်ခုလုံး အောင်မြင်မှသာ run တစ်ခုလုံး အစိမ်းရောင် ဖြစ်ပါတယ်။

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

အထက်ပါ workflow ကို ကူးယူပြီး lint job ရဲ့ ပထမ step ဖြစ်တဲ့ actions/checkout@v4 ကို ဖျက်လိုက်ပါ။ push လုပ်ပြီး Actions tab မှာ ဘယ်လို ကျရှုံးလဲ ကြည့်ပါ - error message က ဘာလို့ "file not found" မျိုး ဖြစ်နေလဲ ဆိုတာ စဉ်းစားပါ။ ပြီးရင် test job ထဲမှာ echo လုပ်တဲ့ step တစ်ခု ထည့်ပြီး၊ lint job က ဖန်တီးထားတဲ့ file တစ်ခုကို ဖတ်ကြည့်ပါ။ ဘာဖြစ်လဲ ခန့်မှန်းပြီးမှ run ကြည့်ပါ။

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

file ကို .github/workflows/ အောက်မှာ မထားတာ၊ ဒါမှမဟုတ် .github/workflow/ (s မပါ) လို့ စာလုံးပေါင်းမှားတာ - GitHub က တိတ်တဆိတ် လျစ်လျူရှုပါတယ်။

job တွေ file ထဲက အစဉ်လိုက် run မယ်လို့ ထင်ပြီး job တစ်ခုက ဆောက်ထားတဲ့ file ကို နောက် job တစ်ခုမှာ ရှိမယ်လို့ မှတ်ယူတာ - needs နဲ့ artifact မပါဘဲ ဘယ်တော့မှ မရပါဘူး။

GitHub Docs - Workflow syntax for GitHub ActionsCI/CD with GitHub Actions

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

  • file ကို .github/workflows/ အောက်မှာ မထားတာ၊ ဒါမှမဟုတ် .github/workflow/ (s မပါ) လို့ စာလုံးပေါင်းမှားတာ - GitHub က တိတ်တဆိတ် လျစ်လျူရှုပါတယ်။
  • job တွေ file ထဲက အစဉ်လိုက် run မယ်လို့ ထင်ပြီး job တစ်ခုက ဆောက်ထားတဲ့ file ကို နောက် job တစ်ခုမှာ ရှိမယ်လို့ မှတ်ယူတာ - needs နဲ့ artifact မပါဘဲ ဘယ်တော့မှ မရပါဘူး။
  • Workflow ကို production branch ပေါ် တိုက်ရိုက်မစမ်းဘဲ branch (သို့) test repository တွင် အရင်အတည်ပြုပါ။

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

အထက်ပါ workflow ကို ကူးယူပြီး lint job ရဲ့ ပထမ step ဖြစ်တဲ့ actions/checkout@v4 ကို ဖျက်လိုက်ပါ။ push လုပ်ပြီး Actions tab မှာ ဘယ်လို ကျရှုံးလဲ ကြည့်ပါ - error message က ဘာလို့ "file not found" မျိုး ဖြစ်နေလဲ ဆိုတာ စဉ်းစားပါ။ ပြီးရင် test job ထဲမှာ echo လုပ်တဲ့ step တစ်ခု ထည့်ပြီး၊ lint job က ဖန်တီးထားတဲ့ file တစ်ခုကို ဖတ်ကြည့်ပါ။ ဘာဖြစ်လဲ ခန့်မှန်းပြီးမှ run ကြည့်ပါ။

You'll know it worked when: push တိုင်းမှာ ဒီ workflow က run ပြီး job နှစ်ခုဖြစ်တဲ့ lint နဲ့ test ကို တစ်ပြိုင်နက် စတင်ပါတယ်၊ တစ်ခုစီက ubuntu-latest runner အသစ် သီးသန့်စီ ရပါတယ်။ Actions tab မှာ job နှစ်ခု ဘေးချင်းယှဉ်လျက် ပေါ်နေမှာဖြစ်ပြီး တစ်ခုက ကျရှုံးလည်း ကျန်တစ်ခုက ဆက်ပြီး run နေပါလိမ့်မယ်။ job တစ်ခုစီအတွင်းမှာတော့ step တွေက အစဉ်လိုက် run ပြီး၊ step တစ်ခု ကျရှုံးရင် အဲဒီ job ရဲ့ ကျန် step တွေကို ကျော်ပစ်ပါတယ်။ test job ရဲ့ npm test က packages/api directory ထဲမှာ run ပါတယ်။ job နှစ်ခုလုံး အောင်မြင်မှသာ run တစ်ခုလုံး အစိမ်းရောင် ဖြစ်ပါတယ်။

Workflow File ရဲ့ ဖွဲ့စည်းပုံ | Thuta Learning