[AZ-400] Implement CI with Azure Pipelines and GitHub Actions (Part2)

สำหรับตอนแรกดูได้จาก [AZ-400] Implement CI with Azure Pipelines and GitHub Actions (Part1) ส่วน Part 2 มีหัวข้อดังนี้

Implement a pipeline strategy

  • Configure agent demands - กำหนด Spec ของ Agents (รูปแบบ Key/Value) ที่ใช้งาน
    ปล ใน YAML กำหนด Lock Build Agent ได้นะ
    • System capabilities - ระบบ Auto ให้
    • User-defined capabilities - เติมเอง
  • Implement multi-agent builds
    • Multiple jobs in a pipeline เพื่อ
      • แยก Pipeline ตาม host
      • Publish หลัง Build แลัวมีอีกหลาย Job รอ Output
      • Build faster จาก parallel build
      • Enable conditional execution of tasks.
  • Explore source control types supported by Azure Pipelines

Integrate with Azure Pipelines

  • Describe the anatomy of a pipeline
    • ตัว Azure Pipeline จะเป็นคนคุยกับ Agent //Agent always initiates the communication with Azure Pipelines
    • pipeline จะคล้ายๆ Jenkinsfile ที่บอกการบิ้ว โดยมี Structure คร่าวๆ ดังนี้
name: string  # build numbering format
resources:
  pipelines: [ pipelineResource ]
  containers: [ containerResource ]
  repositories: [ repositoryResource ]  #ใช่กรณีที่เอาข้อมูลมาจากหลาย Code หลาย Repo
variables: # several syntaxes
 name: pingkunga
# simplified trigger (implied branch)
trigger:
- main

# equivalents trigger
# trigger:
#  branches:
#    include:
#    - main

# ตัว Trigger กำหนด Rule และ
trigger:
    branches:
        include:
            - master
            - releases/*
        exclude:
            - releases/old*

pool: #บอกว่า Run ใช้ Pool ไหน + Agent อะไร
  vmImage: ubuntu-latest
pr: pr
stages: [ stage | templateReference ]
- stage: Build
  jobs: #set of steps executed by an agent in a queue (or pool). Jobs are atomic
  - job: BuildNET
    steps: #actual "things" that execute ตามลำดับใน Job ปกติจะมี out-of-the-box (OOB) task ที่เตรียมไว้อยู่แล้ว
    - script: echo "Hello, $(name)!"
    - script: echo Building!
  - job: PackConfig
    dependsOn: BuildNET       #dependsOn บอกว่าต้องรอ Job BuildNET ทำก่อนนะ
    steps:
    - script: echo Building!
- stage: Test
  jobs:
  - job: TestOnWindows
    steps:
    - script: echo Testing on Windows!
  - job: TestOnLinux
    steps:
    - script: echo Testing on Linux!
- stage: Deploy
  jobs:
  - job: Deploy
    steps:
    - script: echo Deploying the code!
  • Deployment strategies
    • RunOnce
    • Rolling - replaces instances of the previous version of an application with instances of the new version.
    • Canary - ลองก่อน และแบ่ง Traffic มาทดสอบ ถ้ามั่นใจขยับเพิ่ม
  • Lifecycle hooks ส่วนนี้น่าจะใหม่สำหรับผม ปกติทำ CI ได้ image และไปลงด้วยมือที่ Site ลูกค้า โดย Azure DevOps มีประมาณนี้
    • preDeploy
    • deploy
    • routeTraffic
    • postRouteTraffic
    • on: failure or on: success
  • Detail templates - เอาส่วนที่ reuse แยกออกมาจากไฟล์หลัก โดยที่ทำ Template ได้ Stage / Job / Step / Variable
  • Explore YAML resources
    • Pipeline resource
    • Container resource - ดูผ่านๆ เหมือนแทน Docker ไฟล์เลย แต่ต้องลองดูลึกๆอีกที
    • Repository resource
  • Use multiple repositories in your pipeline
    • ถ้าย้ายจริง น่าจะได้ใช้นะ ดูคล้ายกับ ๋Jenkins ปกติ checkout ตัวมันเอง แต่ jenkins version หลังๆ เหมือนจะให้ใส่ checkout อีกรอบ ฮ่าๆ
    • GitHub - Auth 3 แบบ GitHub App / OAuth / PAT
steps:
- checkout: git://MyProject/MyRepo@features/tools # checks out the features/tools branch
- checkout: git://MyProject/MyRepo@refs/heads/features/tools # also checks out the features/tools branch.
- checkout: git://MyProject/MyRepo@refs/tags/MyTag # checks out the commit referenced by MyTag.

Introduction to GitHub Actions

  • Manage Level
    • Organizational-level (multiple repositories in an organization),
    • Enterprise-level (multiple organizations across an enterprise),
    • Repository-level (single repository)
  • What are Actions? -
    • Action - เหมือน Steps ใน Azure Pipeline / JenkinsFile ว่าจะทำอะไรจริงๆ
    • format - YAML
    • Actions are executed on "runners," hosted มี 2 แบบ GitHub / self-hosted (Public Repo ไม่แนะนำนะ)
    • Flow [Events] --Trigger--> [Workflows] --ประกอบด้วย--> [Jobs] --Use--> [Actions]
# .github/workflows/build.yml
name: Node Build.

# on = Event ที่ทำให้เกิด มี 4 กลุ่ม //Ref https://learn.microsoft.com/en-us/training/modules/introduction-to-github-actions/6-explore-events
# - Scheduled events - ใช้ Cron 
# - Code events [push, pull_request]
# - Manual events
# - WEB HOOKs
# - External events - Other System

on: [push]

jobs:
    mainbuild:
 
        runs-on: ${{ matrix.os }}   #บอก Agent (Runner) ที่ใช้
     
    strategy:
        matrix:
            node-version: [12.x]
            os: [windows-latest]
         
    steps:

    - uses: actions/checkout@v1     #predefined action needs to be retrieved ที่เตรียมไว้
    - name: Run node.js on latest Windows.
      uses: actions/setup-node@v1
      with:
        node-version: ${{ matrix.node-version }}

    - name: Install NPM and build.  #คำสั่ง run บอกให้ Command ที่ Agent (Runner) เช่น Build Code
      run: |
        npm ci
        npm run build
  • strategy + matrix
    • ชุดของตัวแปรที่เป็นไปได้ทั้งหมด เพื่อให้ Pipeline มัน Execute ตาม Combination ลดการเขียน Pipeline หลายไฟล์
    • เช่น node-version x os จะกลายเป็นว่ามันจะ Run ตาม Node 12.0 + [windows-latest] ไปจนถึง 12.n + [windows-latest]
  • Job - ปกติจะ Default Parallel ถ้าจะให้มันรอ แต่ละ Job ต้องใส่ key need <ชื่อjob>
jobs:
  startup:
    runs-on: ubuntu-latest
    steps:

      - run: ./setup_server_configuration.sh
  build:
    needs: startup
    steps:

      - run: ./build_new_server.sh

Learn continuous integration with GitHub Actions

  • Examine environment variables - Jenkins มีแล้ว ตัว GitHub ก็มีเหมือนกัน จุดสังเกตุจะเป็นตัวพิมพ์ใหญ่หมด
    • ระบบมีให้ GITHUB_WORKFLOW / GITHUB_ACTION / GITHUB_REPOSITORY (ชื่อ Repo + User) /
    • Custom ใน YAML ในนี้ PROJECT_SERVER / PROJECT_DATABASE
      ส่วน DB_USER / DB_PASS ถูกกำหนดค่าจาก Secret อย่า HARDCODE
jobs:
    verify-connection:
        steps:
            - name: Verify Connection to SQL Server
            - run: node testconnection.js
        env:
            PROJECT_SERVER: PH202323V
            PROJECT_DATABASE: HAMaster
            DB_USER: ${{ secrets.DBUsname }}
            DB_PASS: ${{ secrets.DBPassword }}
  • Workflow badges - เอาไว้บอกสถานะของ CI/CD รูปแบบ URL
https://github.com/[ACOUNT_NAME]/[REPO_NAME]/workflows/[WORKFLOW_NAME]/badge.svg
  • Best practices for creating actions
    • actions - เล็กๆ หลายๆอัน ดีกว่า action เดียว แล้วยัดทุกอย่าง มันหา Error ง่าย เหมือน Jenkinsfile
    • กำหนด version ของ actions ด้วย และพวก dependency ใช้ latest ก็ได้ แต่เอาจริง ตอนทำ Jenkins / DockerFile ฉิบหายมา นัดต่อนัดและ 5555
    • ถ้าใน Action มี Secret อย่าง Password ใช้ GitHub-Secret: Create encrypted secrets อย่า Hard Code และเอามาใช้ตัวแปรใน Workflow แทน
    • documentation + comment
    • Add details action.yml metadata - ถ้ามันน่าจะมีคนใช้เยอะ เอาไปไว้ใน marketplace ก็ได้นะ จะได้มีคนมาช่วยกัน Improve
  • Mark releases with Git tags
  • Lab7 : Implement GitHub Actions by using DevOps Starter (ไม่แน่ใจว่าเสียเงินไหม แต่เรียบใช้ Azure DevOps Starter และ)
  • Knowledge check: Learn continuous integration with GitHub Actions

Design a container build strategy

  • container provides operating-system-level virtualization by abstracting the "userspace." ซึ่งเจ้า userspace ซึ่งให้ Run Container หลายตัวบน Host OS ได้ ถ้าจะสร้าง Container ฝั่ง docker มีตัว dockerfile ให้ลอง
FROM ubuntu
LABEL maintainer="johndoe@contoso.com"
ADD appsetup /
#run แก้ไข Container หลัง Create แล้ว
RUN /bin/bash -c 'source $HOME/.bashrc; \
echo $HOME'
CMD ["echo", "Hello World from within the container"]
  • หลังจากเตรียม dockerfile พร้อม Run คำสั่ง docker build สร้าง image ได้เลย
  • Multi-stage build - ช่วยลดขนาดของ image จาก docker file ด้านล่าง มี 2 ส่วน
    1. base สร้างรอไว้
    2. build > publish ทดไว้
    3. จากนั้นค่อยเอา 2 มาใส่ใน 1
FROM mcr.microsoft.com/dotnet/core/aspnetcore:3.1 AS base
WORKDIR /app
EXPOSE 80
EXPOSE 443

FROM mcr.microsoft.com/dotnet/core/sdk:3.1 AS build
WORKDIR /src
COPY ["WebApplication1.csproj", ""]
RUN dotnet restore "./WebApplication1.csproj"
COPY . .
WORKDIR "/src/."
RUN dotnet build "WebApplication1.csproj" -c Release -o /app/build

FROM build AS publish
RUN dotnet publish "WebApplication1.csproj" -c Release -o /app/publish

FROM base AS final
WORKDIR /app
COPY --from=publish /app/publish .
ENTRYPOINT ["dotnet", "WebApplication1.dll"]

Reference


Discover more from naiwaen@DebuggingSoft

Subscribe to get the latest posts sent to your email.