[GitHub Actions] Rest in Peace, Manual Deployment — GitHub Actions Has Arrived - 4. Get to Work, GitHub Actions! Jobs
[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.
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.
| OS | CPU | RAM | SSD | List |
|---|---|---|---|---|
| Linux | 2 | 7GB | 14GB | ubuntu-latest, ubuntu-22.04, ubuntu-20.04 |
| Windows | 2 | 7GB | 14GB | windows-latest, windows-2022, windows-2019 |
| macOS | 3 | 14GB | 14GB | macos-latest, macos-12, macos-11 |
| macOS (Beta) | 4 | 14GB | 14GB | macos-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