TIL: Deploying to GitHub pages
2023-08-15
- github
GitHub pages is a really nice static site option for small projects. It took me some time to get this right, but here’s a little script that can deploy a project easily from my laptop:
#!/usr/bin/env bash
# `x` prints every command the script runs.
set -euox pipefail
if ! git diff; then
printf "Please clean up your git state as this script needs to checkout the gh-pages branch.\n"
exit 1
fi
TEMP_DIR=$(mktemp -d)
# Defer cleanup.
cleanup() {
ls "$TEMP_DIR"
rm -rf "$TEMP_DIR"
}
trap cleanup EXIT
# Clear previous `dist`.
if [ -d dist ]; then
rm -rf dist
fi
# Writes new files to `dist`.
pnpm build
cp -r dist/* "$TEMP_DIR"
# Checkout `gh-pages` if it exists. Might not need this `if` check
if git show-ref --quiet refs/heads/gh-pages; then
git checkout gh-pages
else
git checkout --orphan gh-pages
fi
# Remove all git tracked files.
git rm -rf .
git checkout main -- .gitignore
# Copy over the new assets.
cp -r "$TEMP_DIR"/* .
# Add, commit, push.
git add -A
git commit -m "gh-pages deploy"
git push
# Return to the main branch.
git checkout main
Briefly, it:
- Ensures your
git diff
is clear since it needs to checkout thegh-pages
branch later - Clears out any previous
dist
directory - Runs
pnpm build
and copies all the output to a temporary dir - Checks out the orphan
gh-pages
branch. An orphaned branch has its own separate history from the other branches which is helpful for cases like GH pages. - Deletes all the files normally tracked by git
- Restores the
.gitignore
since that’s still useful here - Copies over the built files from the temporary directory
- Stages all the built files and commits the built files
- Pushes the commit
- Checks out the main branch again to restore the previous state
Using Parcel? Make sure you add this to your package.json
that matches your GH repo name:
"targets": {
"default": {
"publicUrl": "/my-repo-name"
}
},
Using Astro? Be sure to define site
and base
in your astro.config.mjs
:
export default defineConfig({
site: "https://jondlm.github.io/website/",
base: "website",
});