GitHub/Workflow: Difference between revisions
Line 139: | Line 139: | ||
with open(os.environ['GITHUB_OUTPUT'], 'a') as fh: | with open(os.environ['GITHUB_OUTPUT'], 'a') as fh: | ||
print(f'{SOME}={THING}', file=fh) | print(f'{SOME}={THING}', file=fh) | ||
</pre> | |||
Function version: | |||
<pre> | |||
def set_output(name, value): | |||
with open(os.environ['GITHUB_OUTPUT'], 'a') as fh: | |||
print(f'{name}={value}', file=fh) | |||
</pre> | </pre> | ||
Revision as of 05:37, 25 June 2024
Starter Workflows
Quickstart for GitHub Actions - GitHub Docs https://docs.github.com/en/actions/quickstart
actions/starter-workflows: Accelerating new GitHub Actions workflows https://github.com/actions/starter-workflows
GitHub Marketplace - Actions https://github.com/marketplace?category=&query=&type=actions&verification=
Manual Run
manual.yaml:
name: Manual Run run-name: Test on: workflow_dispatch: inputs: LABEL: required: true type: string description: label jobs: run: runs-on: ${{ inputs.LABEL }} steps: - run: hostname
On Pull Request
name: On Pull Request on: pull_request: types: [opened, reopened] jobs: test: runs-on: [ubuntu-latest] steps: - name: do something shell: bash run: | echo "hi"
On Label Change
Note: Must have event in
name: On Label on: pull_request: types: - labeled jobs: label-job: if: "github.event.label.name == 'run-mylabel'" uses: myorg/myrepo/.github/workflows/dolabel.yaml@v2 with: VAR1: VAR1 secrets: inherit
Basic Workflow
name: GitHub Actions Demo run-name: ${{ github.actor }} is testing out GitHub Actions 🚀 on: [push] jobs: Explore-GitHub-Actions: runs-on: ubuntu-latest steps: - run: echo "🎉 The job was automatically triggered by a ${{ github.event_name }} event." - run: echo "🐧 This job is now running on a ${{ runner.os }} server hosted by GitHub!" - run: echo "🔎 The name of your branch is ${{ github.ref }} and your repository is ${{ github.repository }}." - name: Check out repository code uses: actions/checkout@v3 - run: echo "💡 The ${{ github.repository }} repository has been cloned to the runner." - run: echo "🖥️ The workflow is now ready to test your code on the runner." - name: List files in the repository run: | ls ${{ github.workspace }} - run: echo "🍏 This job's status is ${{ job.status }}."
ref: https://docs.github.com/en/actions/quickstart
Using Job Output
if you want to export the job output from the workflow:
name: CI Precommit Automation Pipeline - Get Builds on: workflow_call: inputs: ... outputs: output1: ${{ jobs.job1.outputs.output1 }}
job outputs:
jobs: job1: runs-on: ubuntu-latest # Map a step output to a job output outputs: output1: ${{ steps.step1.outputs.test }} output2: ${{ steps.step2.outputs.test }} steps: - id: step1 run: echo "test=hello" >> "$GITHUB_OUTPUT" - id: step2 run: echo "test=world" >> "$GITHUB_OUTPUT" - id: step3 run: echo "I see step1: ${{ steps.step1.outputs.test }} job2: runs-on: ubuntu-latest needs: job1 steps: - env: OUTPUT1: ${{needs.job1.outputs.output1}} OUTPUT2: ${{needs.job1.outputs.output2}} run: echo "$OUTPUT1 $OUTPUT2"
ref: Defining outputs for jobs - GitHub Enterprise Cloud Docs - https://docs.github.com/en/enterprise-cloud@latest/actions/using-jobs/defining-outputs-for-jobs
Python version job output
Python version: [1]
with open(os.environ['GITHUB_OUTPUT'], 'a') as fh: print(f'{SOME}={THING}', file=fh)
Function version:
def set_output(name, value): with open(os.environ['GITHUB_OUTPUT'], 'a') as fh: print(f'{name}={value}', file=fh)
Multi lined version:
import uuid def set_multiline_output(name, value): with open(os.environ['GITHUB_OUTPUT'], 'a') as fh: delimiter = uuid.uuid1() print(f'{name}<<{delimiter}', file=fh) print(value, file=fh) print(delimiter, file=fh) # call example: set_multiline_output("value", my_multiline_string)
Dynamic Runs-on
Dynamic from Input:
name: Dynamic Labels run-name: Dynamic Labels on: workflow_dispatch: inputs: LABELS: required: false type: string jobs: run: # runs-on: ${{ fromJSON( '["CI"]' ) }} # This works # runs-on: ${{ fromJSON( '["CI", "MORE"]' ) }} # This works runs-on: ${{ fromJSON( inputs.LABELS ) }} # This works if formatted like: ["CI", "MORE"] # runs-on: ${{ inputs.LABELS }} # this works for single label # runs-on: [ CI, MORE ] # this works steps: - run: hostname
Dynamic from script:
name: Dynamic Script run-name: Test on: workflow_dispatch: inputs: Go: required: false type: string jobs: job1: runs-on: ubuntu-latest outputs: RUNS: ${{ steps.set-RUNS.outputs.RUNS }} steps: - id: set-RUNS run: echo "RUNS=[\"CI\",\"MORE\"]" >> $GITHUB_OUTPUT job2: needs: job1 runs-on: ${{fromJSON(needs.job1.outputs.RUNS)}} steps: - run: hostname
ref:
- How to Dynamically assign the runs-on value in the github actions - Stack Overflow - https://stackoverflow.com/questions/73241812/how-to-dynamically-assign-the-runs-on-value-in-the-github-actions
- Github Actions: How use strategy/matrix with script - Stack Overflow - https://stackoverflow.com/questions/59977364/github-actions-how-use-strategy-matrix-with-script
Dynamic Jobs
{ "include": [ {"runson": ["CI", "MORE"], "task": "joe"}, {"runson": ["CI", "LESS"], "task": "bob"} ] }
name: Dynamic Jobs run-name: Test on: workflow_dispatch: inputs: Go: required: false type: string jobs: generate: runs-on: ubuntu-latest outputs: MATRIX: ${{ steps.set-MATRIX.outputs.MATRIX }} steps: - id: set-MATRIX run: echo "MATRIX={\"include\":[{\"runson\":[\"CI\",\"MORE\"],\"task\":\"joe\"},{\"runson\":[\"CI\",\"LESS\"],\"task\":\"bob\"}]}" >> $GITHUB_OUTPUT jober: needs: generate runs-on: ${{ matrix.runson }} strategy: matrix: ${{fromJson(needs.generate.outputs.matrix)}} steps: - run: hostname - run: echo ${{ matrix.runson }} - run: echo ${{ matrix.task }}
Remotely Trigger Workflow - repository_dispatch
on: repository_dispatch:
---
on: repository_dispatch: types: [some_event_type]
curl -X POST https://api.github.com/repos/OWNER/REPO/dispatches -H "Authorization: Bearer ${GH_TOKEN}" -d '{"event_type":"some_event_type"}'
---
curl -X POST https://api.github.com/repos/ORG/REPO/dispatches -d '{"event_type":"some_event_type"}' # -d or --data, -X or --request # -H "Accept: application/vnd.github.v3+json" # -H "Accept: application/vnd.github+json" # You will most likely need to also pass along auth: (unless you are silly and on a publicly executable workflow?) # -H "Authorization: Bearer $GITHUB_TOKEN"
curl -L \ -X POST \ -H "Accept: application/vnd.github+json" \ -H "Authorization: Bearer <YOUR-TOKEN>" \ -H "X-GitHub-Api-Version: 2022-11-28" \ https://api.github.com/repos/OWNER/REPO/dispatches \ -d '{"event_type":"on-demand-test","client_payload":{"unit":false,"integration":true}}'
---
if you want to trigger from some other branch: {...,'ref':'other_branch_or_ref'},...}
---
repository_dispatch - Events that trigger workflows - GitHub Docs https://docs.github.com/en/actions/using-workflows/events-that-trigger-workflows#repository_dispatch
repository_dispatch - Repositories - GitHub Docs https://docs.github.com/rest/repos/repos#create-a-repository-dispatch-event
---
If you pass this payload through, you can limit the workflow, and access it in the workflow:
{ "event_type": "test_result", "client_payload": { "passed": false, "message": "Error: timeout" } }
workflow:
on: repository_dispatch: types: [test_result] jobs: run_if_failure: if: ${{ !github.event.client_payload.passed }} runs-on: ubuntu-latest steps: - env: MESSAGE: ${{ github.event.client_payload.message }} run: echo $MESSAGE
Job Timeout
Workflow syntax - jobs - timeout-minutes https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idtimeout-minutes
my-job: runs-on: ubuntu-latest timeout-minutes: 30
jobs.<job_id>.timeout-minutes The maximum number of minutes to let a job run before GitHub automatically cancels it. Default: 360
If the timeout exceeds the job execution time limit for the runner, the job will be canceled when the execution time limit is met instead. For more information about job execution time limits, see "Usage limits, billing, and administration" for GitHub-hosted runners and "About self-hosted runners" for self-hosted runner usage limits.
Usage Limits:
There are some limits on GitHub Actions usage when using GitHub-hosted runners. These limits are subject to change. [2]
- Job execution time - Each job in a workflow can run for up to 6 hours of execution time. If a job reaches this limit, the job is terminated and fails to complete.
There are some limits on GitHub Actions usage when using self-hosted runners. These limits are subject to change. [3]
- Job execution time - Each job in a workflow can run for up to 5 days of execution time. If a job reaches this limit, the job is terminated and fails to complete.
Step Timeout
jobs.<job_id>.steps[*].timeout-minutes The maximum number of minutes to run the step before killing the process.
Status Check Functions
Expressions - GitHub Docs https://docs.github.com/en/actions/learn-github-actions/expressions#status-check-functions
success
steps: ... - name: The job has succeeded if: ${{ success() }}
failure
Returns true when any previous step of a job fails.
steps: ... - name: The job has failed if: ${{ failure() }}
with step conclusion check:
steps: ... - name: Failing step id: demo run: exit 1 - name: The demo step has failed if: ${{ failure() && steps.demo.conclusion == 'failure' }}
always
Causes the step to always execute, and returns true, even when canceled. The always expression is best used at the step level or on tasks that you expect to run even when a job is canceled.
if: ${{ always() }}
cancelled
Returns true if the workflow was canceled.
if: ${{ cancelled() }}
Pass Status to Step
Use:
steps.<id>.outcome != 'success'
- name: Check status step id: check-step if: success() shell: bash run: | echo "Workflow successful" - name: The step to call the action if: always() uses: ./path/to/action with: some-token: ${{ inputs.some-token }} some-value: ${{ inputs.some-value }} workflow-status: ${{ steps.check-step.outcome }}