blog.itcode.devblog.itcode.dev

[GitHub Actions] Rest in Peace, Manual Deployment — GitHub Actions Has Arrived - 4. Get to Work, GitHub Actions! Jobs

Now that we've covered how to run a workflow, let's cover how to actually get the workflow to do work. This post covers Jobs and Steps, with a brief mention of Runners as well.

[GitHub Actions] Rest in Peace, Manual Deployment — GitHub Actions Has Arrived - 4. Get to Work, GitHub Actions! Jobs

Now that we've covered how to run a workflow, let's cover how to actually get the workflow to do work. This post covers Jobs and Steps, with a brief mention of Runners as well.
RWB0104
@RWBwritten at 2023-11-07 17:34:47
Rest in Peace, Manual Deployment — GitHub Actions Has Arrived

시리즈 모아보기

Rest in Peace, Manual Deployment — GitHub Actions Has Arrived

4 / 5

Now that we've covered how to run a workflow, let's cover how to actually get the workflow to do work.

We'll first cover Jobs, the large unit of the script, and inevitably also briefly touch on Runners, which are declared and run beneath a job.

A job is a collection of Steps. It can be declared using the jobs keyword, and has a unique name.

You can create more than one job, so you can also split up jobs by function and use them separately.

YAML

name: jobs test
on: workflow_dispatch
jobs:
  jobs_test1:
    runs-on: ubuntu-latest
    steps:
      - name: test steps
        run: echo Hello, jobs_test1

  jobs_test2:
    runs-on: ubuntu-latest
    steps:
      - name: test steps
        run: echo Hello, jobs_test2

The workflow in the script above has two jobs, jobs_test1 and jobs_test2. You can name jobs however you want, as shown here.

As mentioned in the previous post, jobs run in parallel by default. That means jobs_test1 and jobs_test2 run at the same time.

If you want them to run sequentially, you need to use the needs keyword. Specifying a job in needs makes that job run only after the specified job finishes.

YAML

name: jobs test
on: workflow_dispatch
jobs:
  jobs_test1:
    runs-on: ubuntu-latest
    steps:
      - name: test steps
        run: echo Hello, jobs_test1

  jobs_test2:
    needs: jobs_test1
    runs-on: ubuntu-latest
    steps:
      - name: test steps
        run: echo Hello, jobs_test2

If you want them to run in the order jobs_test1 -> jobs_test2, just specify jobs_test1 in jobs_test2's needs.

jobs_test2 won't run until jobs_test1 finishes.

A runner is the virtual machine a given job runs on. It's declared under a job, and you can specify the runner with runs-on.

Each job has one runner.

YAML

name: runner test
on: workflow_dispatch
jobs:
  runner_test:
    runs-on: ubuntu-latest
    steps:
      - name: test steps
        run: echo Hello World

The script above runs the workflow on the latest Ubuntu OS. ubuntu-latest is the latest version of Ubuntu, currently version 22.04.

OSCPURAMSSDList
Linux27GB14GBubuntu-latest, ubuntu-22.04, ubuntu-20.04
Windows27GB14GBwindows-latest, windows-2022, windows-2019
macOS314GB14GBmacos-latest, macos-12, macos-11
macOS (Beta)414GB14GBmacos-13

-latest automatically selects the newest version in the version list.

Note that for macOS, since 13 is still in beta, macos-latest currently resolves to macos-12.

In addition to the runners provided by GitHub, you can also register your own server with GitHub Actions Runners and use it as a CI/CD server. This is called a Self-Hosted Runner. Instead of a server provided by GitHub, you host and use your own server.

Since you're using your own server directly, it's not affected by GitHub Actions' billing policy. Also, if your own server is more powerful than what's listed in the table above, you can gain a performance benefit as well.

🖼️ Creating a Self-Hosted Runner

You can register one from the target repository's Settings menu -> Actions in the left sidebar -> the Runners menu in the sub-tree.

You can select the OS that matches your server and connect it. The connection instructions are kindly provided on that page, so just follow them in order.

Afterward, you'll see the added Runner in the list shown in the image above. You can add multiple Runners as well.

Naturally, the connected server must be online, and you can also check the server's status on that page.

YAML

name: runner test
on: workflow_dispatch
jobs:
  runner_test:
    runs-on: self-hosted
    steps:
      - name: test steps
        run: echo Hello World

You can specify it by applying the self-hosted keyword as shown above.

That script then runs on your own server.

YAML

name: runner test
on: workflow_dispatch
jobs:
  runner_test:
    runs-on: [ self-hosted, linux, x64 ]
    steps:
      - name: test steps
        run: echo Hello World

As briefly mentioned earlier, you can have multiple Runners. In that case, you can specify the OS you want using an array.

The script above selects and runs on a Self-Hosted Runner whose OS is Linux and whose architecture is x64.

This way, you can connect and use your own server with GitHub Actions.

You can apply a conditional to a job so that it only runs under the condition you want.

Naturally, this uses the if keyword, as shown below.

YAML

name: if test
on: workflow_dispatch
jobs:
  if_test:
    runs-on: ubuntu-latest
    if: github.repository == 'RWB0104/github-acitons-test'
    steps:
      - name: test steps
        run: echo Hello World

As shown above, the job only runs when the if keyword evaluates to true.

Here's the first time we encounter the concept of a matrix. GitHub Actions lets you build a kind of matrix called matrix, which lets you easily implement repetitive behavior across multiple environments.

For example, you can build a script that runs code tests separately on Windows, Mac, and Linux environments.

YAML

name: matrix test
on: workflow_dispatch
jobs:
  matrix_test:
    strategy:
      matrix:
        os: [ ubuntu-latest, windows-latest, macos-latest ]
    runs-on: ${{ matrix.os }}
    steps:
      - name: test steps
        run: echo Hello World in ${{ matrix.os }}

The script above is a simple example. Declare the strategy keyword under a job, and under that, enter the desired values as an array using the matrix keyword.

In the example above, a set of Runners is entered with the key os. You can use any key you want here, not necessarily os.

So, depending on the number of items in matrix's os field, the matrix_test job runs 3 times. You can use it like a variable within the script in the form ${{ matrix.os }}.

By assigning the variable to the runs-on keyword, you can see that the script is configured to run on each OS.

So the result of test steps looks like this.

BASH

Hello World in ubuntu-latest
Hello World in windows-latest
Hello World in macos-latest

matrix can also have multiple keys added under it.

YAML

name: matrix test
on: workflow_dispatch
jobs:
  matrix_test:
    strategy:
      matrix:
        os: [ ubuntu-latest, windows-latest, macos-latest ]
        version: [ 16, 18 ]
    runs-on: ${{ matrix.os }}
    steps:
      - name: test steps
        run: echo Hello World in ${{ matrix.os }} ${{ matrix.version }}

In this case, it runs once for every combination of os and version, for a total of 6 runs.

BASH

Hello World in ubuntu-latest 16
Hello World in ubuntu-latest 18
Hello World in windows-latest 16
Hello World in windows-latest 18
Hello World in macos-latest 16
Hello World in macos-latest 18

That's the general idea.

Based on what we've seen so far, it seems like a GitHub Actions job just performs its work and can't affect other jobs — kind of like a void method.

But by having a job return an output value, you can give a job's action a result and configure it so other jobs can use it.

YAML

name: output test
on: workflow_dispatch
jobs:
  output_test:
    runs-on: ubuntu-latest
    outputs:
      result: output1
      call: output2
    steps:
      - name: test steps
        run: echo Hello World

  output_test2:
    needs: output_test
    runs-on: ubuntu-latest
    steps:
      - name: test steps
        run: |
          echo ${{ needs.output_test.outputs.result }}
          echo ${{ needs.output_test.outputs.call }}

You can define the desired output values using the outputs keyword under a declared job.

The output values of a job defined this way can be used in other jobs. To call the result output of the output_test job, you can call it like needs.output_test.outputs.result.

BASH

output1
output2

The result of output_test2 is shown above. You can see that output_test's output values result and call are printed correctly.

Making good use of this, you can use the if keyword to have other effects depending on the result of a previous job, such as running additional jobs conditionally.

In the example above, the output values were hardcoded, but you can also set a job's outputs dynamically via a command in Steps. This is covered later in the next post.

Sometimes you need to use values common across jobs. In that case, using environment variables lets you assign a value common to multiple jobs.

YAML

name: env test
on: workflow_dispatch

env:
  KEY: Hello World

jobs:
  env-job1:
    runs-on: ubuntu-latest

    steps:
      - name: Print env
        run: echo "${{ env.KEY }}"
        
  env-job2:
    runs-on: ubuntu-latest

    steps:
      - name: Print env
        run: echo "${{ env.KEY }}"

As shown above, you can specify a workflow's environment variables with the env keyword. You can call the environment variable using the form ${{ env.[KEY] }}.

Environment variables declared in a workflow can be used anywhere within that workflow. This lets you manage the same value in a common way.

BASH

Hello World
Hello World

Both jobs print the same result.

This post covered jobs, the main building block of GitHub Actions.

The next post covers Steps, which describe a job's detailed behavior.

For more detail on this topic, refer to GitHub Actions Docs - Using Jobs.




  • [2024-06-09 03:37:00] Added content about env
# GitHub# GitHub Actions# Workflows# Events# Jobs# Runners# Steps# YAML
ship
blog.itcode.dev

Notes from the π-th Alpaca

7.0.1
Developed by RWB since 2021.057th upgraded at 2026.08