GitHub actions
Artifacts
Artifacts are data generated by workflows that can be passed to subsequent jobs.
Official actions
Merge multiple artifacts
Set merge-multiple: true
- name: Download notebooks
uses: actions/download-artifact@v4
with:
path: path/of/artifacts
pattern: notebook-*
merge-multiple: true
- name: Display structure of downloaded files
run: ls -R path/of/artifactsAutomatic Dependency Update
Updating package and GitHub actions dependencies automatically as a part of continuous integration (CI).
Dependabot
Dependabot creates a pull request once there is an update for the dependencies. The pull requests are usually tested by continuous integration (CI).
However, dependabot does not support automerging on its own due to security concerns. The good news is that we could use Kodiak to do the job. See it’s quickstart if you are interested.
For example, the dependabot file .github/dependabot.yml to track GitHub actions.
version: 2
updates:
- package-ecosystem: "github-actions"
directory: "/"
schedule:
interval: "daily"
labels:
- "automerge"
groups:
gha-dependencies:
applies-to: "version-updates"
patterns:
- "*"Kodiak bot configuration file: .github/.kodiak.toml
version = 1
[merge]
method = "squash"Renovate
Renovate bot can manage both dependency update checking and automated pull request merging. Renovate supports a variety of platforms and a variety of programming languages.
Enable the Renovate GitHub APP for GitHub repositories. Renovate bot will open an pull request for reachable repos to begin an interactive setup.
The settings file renovate.json example
{
"extends": [
"config:recommended",
],
"git-submodules": {
"enabled": true
}Caching
The https://github.com/actions/cache action caches data across workflow runs.
- name: Cache multiple paths
uses: actions/cache@v6
with:
path: |
~/cache
!~/cache/exclude
key: ${{ runner.os }}-${{ hashFiles('**/Lockfile') }}
restore-keys: |
${{ runner.os }}-- The
keyis the identifier for writing into the cache. If thekeystays the same before and after the workflow, the cache will not be updated. - The
restore-keysare the identifiers for reading the cache besides thekey.If there is no matchingkeybut a part of it (restore-keys) matches, the GitHub action will still read the cache and update it after the job. (since thekeyis different)
You can split caching into restore and save steps, leading to a fine-grained behavior.
- name: Restore cached Primes
id: cache-primes-restore
uses: actions/cache/restore@v6
with:
path: |
path/to/dependencies
some/other/dependencies
key: ${{ runner.os }}-primes
#
# //intermediate workflow steps
#
- name: Save Primes
id: cache-primes-save
uses: actions/cache/save@v6
with:
path: |
path/to/dependencies
some/other/dependenciesCleanup PR caches
Clean up PR caches after it is closed.
name: Cleanup PR caches
on:
pull_request:
types:
- closed
jobs:
cleanup:
permissions:
actions: write
runs-on: ubuntu-latest
steps:
- name: Cleanup
run: |
gh extension install actions/gh-actions-cache
echo "Fetching list of cache key"
cacheKeysForPR=$(gh actions-cache list -R $REPO -B $BRANCH -L 100 | cut -f 1 )
## Setting this to not fail the workflow while deleting cache keys.
set +e
echo "Deleting caches..."
for cacheKey in $cacheKeysForPR
do
gh actions-cache delete $cacheKey -R $REPO -B $BRANCH --confirm
done
echo "Done"
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
REPO: ${{ github.repository }}
BRANCH: refs/pull/${{ github.event.pull_request.number }}/mergeDynamic parallel matrix
We can create a job matrix dynamically by returning a JSON array.
Here we use json and glob modules in Python as an example.
name: Show text files with dynamic parallel matrix
on:
push:
branches:
- main
jobs:
setup:
runs-on: ubuntu-latest
outputs:
matrix: ${{ steps.set-matrix.outputs.matrix }}
steps:
- name: Checkout repository
uses: actions/checkout@v3
- name: List text files as a JSON array
id: set-matrix
run: echo "matrix=$(python -c 'import glob, json; print(json.dumps(glob.glob("*.txt")))')" >> $GITHUB_OUTPUT
execute:
needs: setup
strategy:
fail-fast: false
matrix:
textfile: ${{ fromJSON(needs.setup.outputs.matrix) }}
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v3
- name: Print text file
run: cat ${{ matrix.textfile }}Git Operations
Git commands, such as checkout, add, create a branch, make a pull request in Github actions.
Checkout/Clone
The official https://github.com/actions/checkout action clones the repository to $GITHUB_WORKSPACE. By default it uses the built-in GITHUB_TOKEN for authentication.
In most cases, this is what you need:
- uses: actions/checkout@v7The checkout action also supports pushing a commit to the same repo.
Warning
This may not work on protected branches that need status checks.
on: push
jobs:
git-push:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v7
- run: |
date > generated.txt
git config user.name github-actions
git config user.email github-actions@github.com
git add .
git commit -m "generated"
git pushHowever, the following actions are more convenient for commit and push changes back to your GitHub repo.
- https://github.com/EndBug/add-and-commit
- https://github.com/stefanzweifel/git-auto-commit-action
- https://github.com/ad-m/github-push-action
However, no further workflows will be triggered with the GITHUB_TOKEN. You will need the following steps to trigger workflows.
How to trigger further CI runs
You will need either a Personal access token (PAT) with repo scope access as an action secret.
- uses: actions/checkout@v7
with:
token: ${{ secrets.PAT }}Or a pair of SSH keys; the public key is the deploy key with write access, while the private key is an action secret variable SSH_PRIVATE_KEY.
- uses: actions/checkout@v7
with:
ssh-key: ${{ secrets.SSH_PRIVATE_KEY }}Create a pull request
The https://github.com/peter-evans/create-pull-request action will commit all files into a new branch and make a pull request to the target (default main) branch.
- name: Create Pull Request
uses: peter-evans/create-pull-request@v6
with:
# token: ${{ secrets.PAT }} # A PAT is required for triggering pull request workflows
token: ${{ secrets.GITHUB_TOKEN }} # This will not trigger further workflowsMerge pull requests
- Kodiak Bot : automatic merge PRs based on the issue label. (by default
automerge). - Run
gh pr merge --merge --auto $PR_NUMBERin the workflow. - https://github.com/peter-evans/enable-pull-request-automerge : A GitHub action to enable auto-merge on a pull request.
Issues to a markdown file
The Python package https://github.com/mattduck/gh2md exports Github repository issues and pull requests to a single, readable markdown file.
name: Issues2Markdown
on:
# issues:
# issue_comment:
workflow_dispatch: # manually run this workflow
schedule:
- cron: "0 0 * * *" # On 00:00 every day
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
with:
token: ${{ secrets.PERSONAL_ACCESS_TOKEN }}
fetch-depth: 0 # otherwise, you will failed to push refs to dest repo.
- uses: actions/setup-python@v2
with:
python-version: '3.x'
- name: Install GitHub Issue to Markdown
run: pip install gh2md
- name: Backup github issues into separate markdown files
env:
GITHUB_ACCESS_TOKEN: ${{ secrets.PERSONAL_ACCESS_TOKEN }}
run: |
rm -rf issues/ || true
gh2md --multiple-files -I --no-prs --no-closed-prs $GITHUB_REPOSITORY issues/
- name: Install mmv
run: sudo apt update && sudo apt install -y mmv
- name: Modify markdown file names
working-directory: issues
run: mmv '*.*.issue.*.md' '#2.md'
- name: Commit files
uses: stefanzweifel/git-auto-commit-action@v5
with:
commit_message: Backup IssuesGitHub Pages
Publish your website to GitHub pages with GitHub actions (CI/CD).
Official workflow
The benefit of using the official workflow is that you do not need an orphan branch to hold the webpages.
jobs:
build:
runs-on: ubuntu-latest
steps:
# After the website is built
- name: Upload artifact
uses: actions/upload-pages-artifact@v3
if: ${{ github.ref == 'refs/heads/main' }}
with:
path: ./site
# Deployment job
deploy:
needs: build
if: ${{ github.ref == 'refs/heads/main' }}
# Grant GITHUB_TOKEN the permissions required to make a Pages deployment
permissions:
pages: write # to deploy to Pages
id-token: write # to verify the deployment originates from an appropriate source
actions: read # to download an artifact uploaded by `actions/upload-pages-artifact@v3`
environment:
name: github-pages
url: ${{ steps.deployment.outputs.page_url }}
runs-on: ubuntu-latest
steps:
- name: Deploy to GitHub Pages
id: deployment
uses: actions/deploy-pages@v4In the repository settings => Pages => Build and deployment => Select GitHub actions as the page source.
Publish to another branch
You need to give write permission to GITHUB_TOKEN in the workflow file for the following actions to work
permissions:
contents: writeUse https://github.com/peaceiris/actions-gh-pages
# After the website was built
- name: Deploy
uses: peaceiris/actions-gh-pages@v3
with:
github_token: ${{ secrets.GITHUB_TOKEN }} # You need an SSH deploy key if deploying to another repo
publish_dir: ./public
force_orphan: true
commit_message: ${{ github.event.head_commit.message }}Or https://github.com/JamesIves/github-pages-deploy-action
# After the website was built
- name: Deploy 🚀
uses: JamesIves/github-pages-deploy-action@v4
with:
folder: ./public # The folder the action should deploy.In the repository settings => Pages => Build and deployment => Select Deploy from a branch as the page source.
Release
- https://github.com/softprops/action-gh-release : A GitHub Action for creating GitHub Releases on Linux, Windows, and macOS virtual environments.
- https://github.com/release-drafter/release-drafter : Drafts your next release notes as pull requests are merged into master.
- https://github.com/robinraju/release-downloader : Github action to download release assets from private or public repositories.
- https://github.com/actions/delete-package-versions : This action deletes versions of a package from GitHub Packages. This action will only delete a maximum of 100 versions in one run.