13-June-25

In CI/CD world, environment variables and secret is key to storing value without writing directly to yaml files. It's possible to manage credentials, versioning, and configure build according to the needs

13-June-25
Photo by nbtrisna Humble craft, bringing possibilities to light.

Daily Quest #2: Secrets & Environment Variables

In CI/CD world, environment variables and secret is key to storing value without writing directly to yaml files. It's possible to manage credentials, versioning, and configure build according to the needs

Skenario : Understand how to use env and secret in github actions for flexible and secure workflow.

  1. In existing repository, reconfigure first-workflows.yaml.
name: Hello CI
on: 
    - push
jobs:
  build:
    runs-on: ubuntu-latest
    steps:
        - name: Checkout code
          uses: actions/checkout@v2
        - name: say hello
          run: echo "Hello from CI/CD!"
        - name: Greeting from variable
          run: echo "Hello from ${{ env.GREETING }}"
        - name: Echo secret
          run: echo "Secret is ${{ secrets.SECRET_MSG }}"
  1. Create secrets on github. Navigate to Settings > Secrets and variables > Actions
Pasted image 20250615135106

2. Create secrets & variable, makesure name of variable/secret correct

  1. Result
Pasted image 20250615135035

Answer :

  1. Penggunaan secrets digunakan untuk store data penting seperti password. Ketika digunakan dalam workflows, akan di samarkan dengan **. Untuk variable, biasanya digunakan untuk menyimpan config, dll. Yang sifatnya general
  2. Github workflow memask secret agar isi dari secret tidak terlihat. Karena biasanya data yang tersimpan dalam secrets adalah data rahasia.

Daily Quest #3: Matrix Mastery

In github workflows, we can use matrix strategies for create multiple job runs using a single jobs variable definition like job running pararalel simultaneously. For example like you can configure your ci to run build in 3 different os/arch

Referensi : https://docs.github.com/en/actions/writing-workflows/choosing-what-your-workflow-does/running-variations-of-jobs-in-a-workflow

To define matrix_strategy simply put in jobs.<job_id>.strategy.matrix with value array.

jobs:
	example_matrix:
		strategy:
			matrix:
				os: [ubuntu-latest, selfhosted]
				version: [10, 11, 12]

By default, GitHub will maximize the number of jobs run in parallel depending on runner availability. The order of the variables in the matrix determines the order in which the jobs are created. The first variable you define will be the first job that is created in your workflow run. For example, the above matrix will create the jobs in the following order:

{version: 10, os: ubuntu-latest}
{version: 10, os: windows-latest}
{version: 12, os: ubuntu-latest}
{version: 12, os: windows-latest}
{version: 14, os: ubuntu-latest}
{version: 14, os: windows-latest}

Single-dimension matrix

jobs:
  example_matrix:
    strategy:
      matrix:
        version: [10, 12, 14]
    steps:
      - uses: actions/setup-node@v4
        with:
          node-version: ${{ matrix.version }}

Explanation : For example, the following workflow defines the variable version with the values [10, 12, 14]. The workflow will run three jobs, one for each value in the variable. Each job will access the version value through the matrix.version context and pass the value as node-version to the actions/setup-node action.

Multi-dimension matrix

jobs:
  example_matrix:
    strategy:
      matrix:
        os: [ubuntu-22.04, ubuntu-20.04]
        version: [10, 12, 14]
    runs-on: ${{ matrix.os }}
    steps:
      - uses: actions/setup-node@v4
        with:
          node-version: ${{ matrix.version }}

Quest

  1. Create new job called matrix-workflow.yaml. Using matrix-strategy to run jobs in different os
name: Hello CI
on: 
    - push
jobs:
  build:
    strategy:
      matrix: 
        os: [ubuntu-latest, windows-latest, macos-latest]
    runs-on: ${{ matrix.os }}
    steps:
        - name: Checkout code
          uses: actions/checkout@v2
        - name: say hello
          run: echo "Hello from CI/CD!"
        - name: Greeting from variable
          run: echo "Hello from ${{ env.GREETING }}"
        - name: Echo secret
          run: echo "Secret is ${{ secrets.SECRET_MSG }}"
        - name: Display OS
          run: echo "Running on ${{ matrix.os }}"
  1. Push, and see result
Pasted image 20250615135116

Answer :

  1. Kelebihan utama menggunakan matrix yaitu dapat mempersingkat dan membuat efiisien dari file workflow. Ketika ada perubahan besar di yaml workflow, devops hanya mengubah satu job. Tanpa mengulangi edit yang lain
  2. Matrix dapat menjadi overkill karena dapat menjalankan secara paralel setiap jobs sesuai dengan variable yang di definisikan dalam array. Untuk membatasinya, kita dapat membatasi sesuai dengan kebutuhan(? coba koreksi)

Daily Quest #4: Dependency Caching

Refrensi : https://docs.github.com/actions/using-workflows/caching-dependencies-to-speed-up-workflows To make workflows faster and efficient, you can cache for depedencies and other commonly reused file. Job in github-hosted runners start a clean runner image, and must download depedencies each time. Causing incerased network utilizaiton, longiger runtime, and incerase cost. To cache depedencies for a job, you can use cache-action. The action create and restores a cache identified by a unique key.

Artifacts vs caching

  • Use caching when you want to reuse files that don't change often between jobs/workflows runs. Such a depedencies from package management system (npm, dll)
  • Using artifacts when you want to save files produce by a job to view after a workflow run has ended. Such a built binaries/logs.

Using a cache actions

  • First search for excat match to your provided key
  • if no excact match, it will search for partial matches of the key
  • if there is still no match found, and you've provided restore-keys, these keys wil be checked sequenial for partial matches. Input parameters for the cache action
  • key : Using to search for a cache. It can any combination of variables, context values, static strings, and function.
  • path : The path of the runner to cache/restore
  • restore-keys : Alternative restore keys.

Is quite hard to understand to using key and restore-key. So first if key not match -> search to restore-keys to list what to restore on path.

       +-------------------------+
       |  Start cache step      |
       +-------------------------+
                 |
                 v
      +---------------------------+
      |  Key match with cache?   |
      +---------------------------+
           |              |
          Yes            No
           |              |
           v              v
  Restore full         Try restore with
    cache              restore-keys prefix
           |              |
         (Hit)         (Partial hit / miss)
           |              |
           v              v
    Run job (npm install, dll)
           |
           v
  +------------------------------+
  |  Save cache at end?         |
  +------------------------------+
           |
  Only if ❌ cache miss

Cache : only run if cache miss.

Skenario : add cache before installing deedencies

  1. Edit cache-workflow.yml
name: Cache Workflows
on: 
  push:
    branches:
      - main
jobs:
  build:
    runs-on: ubuntu-latest
    steps:
        - name: Checkout code
          uses: actions/checkout@v2
        - name: say hello
          run: echo "Hello from CI/CD!"
        - name: Greeting from variable
          run: echo "Hello from ${{ env.GREETING }}"
        - name: Echo secret
          run: echo "Secret is ${{ secrets.SECRET_MSG }}"
        - name: Cache node modules 
          uses: actions/cache@v4
          with:
            path: ~/.npm
            key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }}
            restore-keys: |
              ${{ runner.os }}-node-
        - name: Install dependencies
          run: npm install
        - if: ${{ steps.cache-npm.outputs.cache-hit != 'true' }}
          name: List the state of node modules
          continue-on-error: true
          run: npm list
  1. Push, and result
Pasted image 20250615135122

Answer

  1. Key and restore-keys akan melakukan pengecekan, jika key match maka akan di restore seluruh yang ada di path. Jika tidak, maka akan melakukan general check dengan restore-keys. Jika match maka restore, jika tidak maka hanya akan di cache dan tidak restore
  2. Tidak menggunakan caching ketika workflow/job yang dijalankan tidak memerlukan depedencies berulang.