Resources
What & Link | Type |
---|---|
GitHub: GitHub Actions Docs - Workflow Syntax Reference |
Official Docs |
GitHub: Actions Cheat Sheet - Source Code |
Cheatsheet |
github.com/actions - Starter Workflows |
Tools and samples around Actions |
Jason Etcovitch: - What are Workflows |
Jason has some of the best posts around on GitHub actions; incredible level of depth and explains concepts on multiple levels. |
Gabriel Tanner: An Introduction to GitHub Actions | Introduction / Cheatsheet |
sdras/awesome-actions | Collection of resources / links |
G Adventures: Things I learned making my first Github Action | Step-by-step example of making a custom action. Focuses on Bash scripting side. |
GitHub Actions - FAQ
- Where can I find the default environment variables that are injected into actions?
- You can find them under "Learn GitHub Actions -> Environment Variables -> Default Environment Variables"
- How can I tell if my code is running inside an action or not?
- You can check for the presence of one of the default environment variables, such as:
CI
(true
)GITHUB_ACTIONS
(true
)- etc.
- You can check for the presence of one of the default environment variables, such as:
- Workflows vs actions?
- Workflows are at the highest level of Github Actions - a workflow can contain all the sub-components of Github Automation pieces
Workflow
-> [Job
] -> [Step
] -> [Action
(GH, or Docker),Task
, orCommand
(e.g.run
)]- The best diagram I have found (so far) that clearly shows this, is this one, from this article.
- How do I run multiple commands under a single
run
step?- Use a pipe (
|
) right afterrun:
, and then indent each command line below it. Example. - If you want to split into multiple lines, but not execute each line (e.g., all one long command), use
\
at EOL to mark as continuation
- Use a pipe (
- How do I get a nice badge image based on actions?
- Docs: Adding a workflow status badge
- Summary: The URL syntax is one of...:
- Whether or not workflow has
name
:https://github.com/<OWNER>/<REPOSITORY>/actions/workflows/<WORKFLOW_FILENAME>/badge.svg
- If workflow has
name
:https://github.com/<OWNER>/<REPOSITORY>/workflows/<WORKFLOW_NAME>/badge.svg
- Whether or not workflow has
- Remember URL encoding
- How do I use secrets / passwords / .env vars?
- Add them under Repo -> Settings -> Secrets
- Within a workflow
.yml
file, pull in the secret with this syntax:${{ secrets.SECRET_NAME }}
- Security: How do I keep my actions and workflows safe?
- See Zakas: "How to Safely Use Github Actions..."
- Also, Docs: "Security Hardening for GitHub Actions"
- How do I know how many minutes my workflows have used? How many I have left?
- You can find usage under your GitHub Billing Settings
- What is the purpose of things like
echo "::debug::hello world"
- The
::debug::
prefix is used to hide output from the normal log, and have it only show up if debug logging is enabled
- The
- How do I use variables in the
jobs.{ID}.container
? For example, usingGITHUB_WORKSPACE
involumes
to map an absolute path of the host to a docker path?- You have to use the context syntax
${{ github.workspace }}
, not$GITHUB_WORKSPACE
- This holds true in other areas as well
Different Ways of Using Containers
The relationship of GitHub Actions to VMs (Virtual Machines), Docker, and Containers is not always straightforward, and has also evolved over time.
At a basic level:
- Each job runs on a VM (Virtual Machine), specified by the
runs-on
parameter - Each step can run either directly on the VM, or inside a container
- For steps that use an action, via the
uses
parameter, those also run in a container, dictated by the source code of the action being pulled in
🔗 This StackOverflow response does a good job of summarizing this relationship with example YAML.
Pushing Commits in an Action
In addition to producing build artifacts, GitHub Actions can actually make new commits on your behalf, and push them to your repo. Common uses cases for this are:
- Automatically linting / formatting code and committing with fixes applied
- Committing generated build artifacts to the repository
- Auto-updating docs
- Branches used only for deploys (e.g. for GitHub Pages)
GitHub even provides a secure mechanism to streamline this; at the start of each workflow, a short-lived authentication token is provisioned and injected into the environment (the GITHUB_TOKEN
), which can be used throughout the lifetime of the specific workflow.
Furthermore, there is an action that streamlines the process of interacting with git
from within the action even further: the actions/checkout
action. In addition to checking out your code into the action's volume, this action also handles some automatic setup, so that the authentication token is used by the instance of git
on the VM (it is persisted); you only need to manually reference the token if you are using a different remote
. For example, the docs for actions/checkout
provide an example use-case for pushing a new commit, which only takes about 5 lines of actual shell code.
If you are not using actions/checkout
, need to use a nested git repository, or want to manually configure a git push, here is a sample of how you might approach it:
steps:
- name: Push New Branch
run: |
GIT_ORIGIN="https://x-access-token:${{ secrets.GITHUB_TOKEN }}@github.com/$GITHUB_REPOSITORY.git"
git init
git config user.name "${GITHUB_ACTOR}"
git config user.email "${GITHUB_ACTOR}@users.noreply.github.com"
git remote add origin $GIT_ORIGIN
git add .
git commit -m "Auto-Commit, from $GITHUB_SHA"
git checkout -b $NEW_BRANCH_NAME
git push origin HEAD:$NEW_BRANCH_NAME
GitHub Actions - Tips, Tricks, and Pitfalls to Avoid
- Forgetting to use
cd
orworking-directory
to make sure steps execute in the correct directory- For
run
steps, you can use the standardcd
command to traverse directories as part of the step, or pass the starting directory directly, withworking directory
- At the
job
level, you can set a defaultworking-directory
for allrun
steps within that job
- For
- Be careful about infinite loops via triggers
- Use the special
GITHUB_TOKEN
instead of a Personal Access Token (PAT) as an easy way to avoid accidental trigger loops- However, this sometimes causes issues when you want an action to trigger successive events
- Use the special
- A ton of issues around file permissions and use access can be fixed by correctly using
chown
andchmod
between steps- Especially since GitHub uses a special passwordless root user
Passing Data Around Between Steps, Actions, and Environments
There are multiple ways that data can be passed around in GitHub actions, and it really depends on which actions are being used and the specific context. Some common options:
- Storing generated files as artifacts
- Works for both sharing between jobs in the same workflow, as well as for persisting data after a run is complete
- Using explicit inputs and outputs, for pre-built actions that support them
- Using caching to persist and restore selected data based on hashing / fingerprints
To pass variable values between steps in the same job, you don't have to use artifacts, but you still do need a special syntax:
- Setting shared environment variables
echo "{environment_variable_name}={value}" >> "$GITHUB_ENV"
- Using explicit outputs
- In the step that produces the output, give the step a unique
id
, and then inside yourrun
command, use:echo "{name}={value}" >> "$GITHUB_OUTPUT"
- In the step that uses the previous output, you can reference the output value by step ID and name:
${{ steps.YOUR_STEP_ID.outputs.YOUR_OUTPUT_NAME }}
- In the step that produces the output, give the step a unique
act for Local GitHub Action Running
act
(nektos/act) is a tool for running GitHub actions locally, with minimal setup required. It is not a perfect 1:1 mirror of how GitHub actions execute through the hosted runner, but is still very useful.
GitHub Actions - ACT - How Do I...
- How to watch what ENV variables each step runs with
- Enable verbose logging, with
--verbose
, optionally in dry-mode, with--dry-run
- Enable verbose logging, with
- Inspect the local bin of a 3rd party action that is being used?
- You could either inspect the overall ACT Docker container, or if the action was built as a separate container, that one instead
- Inspecting is a little complicated; you might have to mount the image or dump it to a tarball in order to inspect the contents.
GitHub Actions - ACT - Issues
- Cannot copy files to local system
- This will not work:
cp -r ./docker-dir ${GITHUB_WORKSPACE}
; you are still in the docker container - Have to use volumes to share data
- This will not work:
- Any action that uses the cache fails, usually with getCacheEntry failed: Cache Service URL not found, unable to restore cache, or any action that uses artifacts fails
- This has been a known issue for a while, but has seen recent activity that could address it - asset server implementation code (PR #677)
- Main tracking issues: #329, #169
- Until this is officially addressed, here are two workarounds
- Use GitHub YML conditionals to skip a step if executed locally with ACT and all it does is cache (suggested here)
- Conditional:
if: ${{ !env.ACT }}
- You can use ACT's
--reuse
flag to reuse the container, if you are after a faster run (suggested in #285)
- Conditional:
- Use the artifact server developed separately (anthonykawa/artifact-server), run it alongside ACT, and point ACT to it (like this)
- Use GitHub YML conditionals to skip a step if executed locally with ACT and all it does is cache (suggested here)