A collection of useful GitHub tricks
yq
(similar to jq
) is preinstalled on GitHub Actions runners, which means you can edit a .json
, .yml
or .csv
file very easily without installing any software.
For example, the following workflow file would use yq
to copy all "resolutions"
to "overrides"
in a package.json
file (and then commit the result using stefanzweifel/git-auto-commit-action
.
.github/workflows/copy-resolutions-to-overrides.yml
name: Copy Yarn Resolutions to npm Overrides
on:
push:
branches:
# Match every branch except for main
- '**'
- '!main'
jobs:
build:
name: Copy Yarn Resolutions to npm Overrides
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
# To trigger further `on: [push]` workflow runs
# Ref: https://github.com/peter-evans/create-pull-request/blob/main/docs/concepts-guidelines.md#triggering-further-workflow-runs
# Ref: https://github.com/peter-evans/create-pull-request/blob/main/docs/concepts-guidelines.md#push-using-ssh-deploy-keys
with:
ssh-key: ${{ secrets.SSH_PRIVATE_KEY }}
- name: Use Node.js
uses: actions/setup-node@v3
with:
node-version: '16'
- name: Copy "resolutions" object to "overrides" in package.json
run: yq --inplace --output-format=json '.overrides = .resolutions' package.json
- name: Install any updated dependencies
run: npm install
- uses: stefanzweifel/git-auto-commit-action@v4
with:
commit_message: Update Overrides from Resolutions
Or, to copy all @types/*
and typescript
packages from devDependencies
to dependencies
(eg. for a production build):
yq --inplace --output-format=json '.dependencies = .dependencies * (.devDependencies | to_entries | map(select(.key | test("^(typescript|@types/*)"))) | from_entries)' package.json
It can be useful to commit and push to a pull request in a GitHub Actions workflow, eg. an automated script that fixes something like upgrading pnpm patch versions on automatic Renovate dependency upgrades.
Once your script makes the commit and pushes to the PR, it can also be useful to re-run the workflows on that commit, eg. linting the new commit, so that GitHub auto-merge can run also on protected branches with required status checks.
-
First, create a GitHub fine-grained personal access token:
- Visit https://github.com/settings/personal-access-tokens/new
- Fill out Token name (repository name + a short reminder), Expiration (longest available, 1 year), Description (a reminder of the purpose)
- Under Repository access, choose Only select repositories and then choose the repository where the workflow will run
- Under Permissions, expand Repository permissions, locate Contents and choose Access: Read and write
This will also by default set Metadata to Access: Read-only
- Review your settings under Overview - it should be set to "2 permissions for 1 of your repositories" and "0 Account permissions"
- If you are satisfied with this, click on Generate token.
- This will show you the token on your screen only once, so be careful to copy the token.
-
Add a repository secret
- In the repository where the workflow will run, visit Settings -> Secrets and variables -> Actions and click on New repository secret
- For Name, enter a
SCREAMING_SNAKE_CASE
name that makes it clear that it's a GitHub token (eg.PNPM_PATCH_UPDATE_GITHUB_TOKEN
) and for Secret paste in the token that you copied at the end of step 1 above. Click Add secret.
- In the repository where the workflow will run, visit Settings -> Secrets and variables -> Actions and click on New repository secret
-
Adjust your workflow for the token
-
Under
uses: actions/checkout
, add awith:
block includingpersist-credentials: false
- uses: actions/checkout@v4 with: # Disable configuring $GITHUB_TOKEN in local git config persist-credentials: false
-
‼️ IMPORTANT: As mentioned above, make sure that you don't create a loop! Make sure that your script which alters files includes some kind of way to exit early, for example checkinggit status --porcelain
and runningexit 0
to exit the script early without errors or by skipping steps based on the last commits- name: Fix `pnpm patch` not upgrading patch versions automatically run: | # <your script makes changes here> git add package.json pnpm-lock.yaml patches if [ -z "$(git status --porcelain)" ]; then echo "No changes to commit, exiting" exit 0 fi # <your script sets Git credentials and commits here> # <your script pushes here>
-
Set your Git
user.email
anduser.name
credentials to the GitHub Actions bot and commit:- name: Fix `pnpm patch` not upgrading patch versions automatically run: | # <your script makes changes here> # <your script exits early here> git config user.email github-actions[bot]@users.noreply.github.com git config user.name github-actions[bot] git commit -m "Upgrade versions for \`pnpm patch\`" # <your script pushes here>
-
Use the token via
secrets.<name>
in your Git origin in your workflow (credit:ad-m/github-push-action
)- name: Fix `pnpm patch` not upgrading patch versions automatically run: | # <your script makes changes here> # <your script exits early here> # <your script sets Git credentials and commits here> # Credit for oauth2 syntax is the ad-m/github-push-action GitHub Action: # https://github.com/ad-m/github-push-action/blob/d91a481090679876dfc4178fef17f286781251df/start.sh#L43-L5 git push https://oauth2:${{ secrets.PNPM_PATCH_UPDATE_GITHUB_TOKEN }}@github.com/${{ github.repository }}.git HEAD:${{ github.ref }}
-
.github/workflows/lint-check-types-and-build.yml
name: Lint, Check Types, Build
on: push
jobs:
lint-check-types-and-build:
name: Lint, Check Types, Build
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
# Disable configuring $GITHUB_TOKEN in local git config
persist-credentials: false
- uses: pnpm/action-setup@v2
with:
version: 'latest'
- uses: actions/setup-node@v4
with:
node-version: 'lts/*'
cache: 'pnpm'
# Fix `pnpm patch` not upgrading patch versions automatically
# https://github.com/pnpm/pnpm/issues/5686#issuecomment-1527221879
- name: Fix `pnpm patch` not upgrading patch versions automatically
run: |
./scripts/fix-pnpm-patches.sh
git add package.json pnpm-lock.yaml patches
if [ -z "$(git status --porcelain)" ]; then
echo "No changes to commit, exiting"
exit 0
fi
git config user.email github-actions[bot]@users.noreply.github.com
git config user.name github-actions[bot]
git commit -m "Upgrade versions for \`pnpm patch\`"
# Credit for oauth2 syntax is the ad-m/github-push-action GitHub Action:
# https://github.com/ad-m/github-push-action/blob/d91a481090679876dfc4178fef17f286781251df/start.sh#L43-L55
git push https://oauth2:${{ secrets.PNPM_PATCH_UPDATE_GITHUB_TOKEN }}@github.com/${{ github.repository }}.git HEAD:${{ github.ref }}
- name: Install dependencies
run: pnpm install
- run: pnpm eslint . --max-warnings 0
- run: pnpm tsc
- name: Build extension
run: pnpm build
Pull request with automatic PR commit including workflow checks: karlhorky/archive-webpage-browser-extension#47
Screenshot of a GitHub PR showing two commits, the first by Renovate bot upgrading dependencies and the second by the automated script shown above. Both commits have status icons to the right of them (one red X and one green checkmark), indicating that the workflows have run on both of them. At the bottom, the PR auto-merge added by the Renovate bot is carried out because the last commit has a green checkmark.Use
entities to give a table column a width:
| property | description |
| -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------- |
| `border-bottom-right-radius` | Defines the shape of the bottom-right |
Demo:
property | description |
---|---|
border-bottom-right-radius |
Defines the shape of the bottom-right |
Linking to an anchor in a relative Markdown file path in the same repo (eg. ./windows.md#user-content-xxx
) doesn't currently work on GitHub (Mar 2023). Probably another bug in GitHub's client-side router, maybe fixed sometime.
A workaround is to link to the full GitHub URL with a www.
subdomain - this will cause a redirect to the non-www.
version, and scroll to the anchor:
-[Expo + React Native](./windows.md#user-content-expo-react-native)
+[Expo + React Native](https://www.github.com/upleveled/system-setup/blob/main/windows.md#user-content-expo-react-native)
When in a particular folder (such as the root directory), GitHub displays content from README files underneath the files in that folder:
However, these README files need to be named README.md
, readme.md
, README.mdx
or readme.mdx
in order to be recognized. GitHub doesn't display the content of certain common Markdown index filenames such as index.md
or index.mdx
(❓MDX file extension) (as of 18 June 2019).
GitHub does however follow symlinks named README.md
, readme.md
, README.mdx
and readme.mdx
. See example here: mdx-deck root folder, mdx-deck symlink README.md
So if you want to use another file (also in a subdirectory) as the contents displayed within a directory, create a symlink pointing at it:
ln -s index.md README.md
If you have many directories with index.mdx
files that you want to display as the readme content when you enter those directories on the web version of GitHub, you can run this script in the containing directory.
# Create symlinks for all directories within the current directory that
# do not yet have README.mdx files.
find . -mindepth 1 -maxdepth 1 -type d '!' -exec test -e "{}/README.mdx" ';' -print0 | while IFS= read -r -d $'\0' line; do
cd $line && ln -s index.mdx README.mdx && cd ..
done