Skip to content

feat(landing): single-viewport on md+, /resume keeps its own scroll #147

feat(landing): single-viewport on md+, /resume keeps its own scroll

feat(landing): single-viewport on md+, /resume keeps its own scroll #147

name: Build grantfoster.dev image
on:
push:
branches:
- main
- master
tags:
- "v*"
pull_request:
branches:
- main
- master
workflow_dispatch:
jobs:
frontend:
runs-on: ubuntu-latest
permissions:
contents: read
env:
IMAGE_NAME: geeemoney/grantfoster-website
outputs:
version: ${{ steps.version.outputs.version }}
steps:
- name: Checkout
uses: actions/checkout@v6
- name: Compute bare-semver version (tag releases only)
id: version
if: startsWith(github.ref, 'refs/tags/v')
run: |
TAG="${GITHUB_REF_NAME}"
echo "version=${TAG#v}" >> "${GITHUB_OUTPUT}"
# Default docker-container driver: required for cache-from/cache-to type=gha
# (the docker driver cannot export GHA cache). Tradeoff: pulls moby/buildkit
# from Docker Hub during setup.
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v4
- name: Login to Docker Hub
if: startsWith(github.ref, 'refs/tags/')
uses: docker/login-action@v4
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
- name: Extract metadata (tags, labels)
id: meta
uses: docker/metadata-action@v6
with:
images: ${{ env.IMAGE_NAME }}
tags: |
type=semver,pattern={{version}}
type=semver,pattern={{major}}.{{minor}}
type=raw,value=latest,enable=${{ startsWith(github.ref, 'refs/tags/v') }}
type=raw,value=build,enable=${{ !startsWith(github.ref, 'refs/tags/') }}
- name: Validate GA measurement ID for tagged releases
if: startsWith(github.ref, 'refs/tags/')
env:
NEXT_PUBLIC_GA_MEASUREMENT_ID: ${{ vars.NEXT_PUBLIC_GA_MEASUREMENT_ID }}
run: |
if [ -z "${NEXT_PUBLIC_GA_MEASUREMENT_ID}" ]; then
echo "NEXT_PUBLIC_GA_MEASUREMENT_ID repository variable is required for tagged builds."
exit 1
fi
- name: Build and push
uses: docker/build-push-action@v7
with:
context: .
file: deploy/docker/frontend.Dockerfile
target: production
build-args: |
NEXT_PUBLIC_GA_MEASUREMENT_ID=${{ vars.NEXT_PUBLIC_GA_MEASUREMENT_ID }}
push: ${{ startsWith(github.ref, 'refs/tags/') }}
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
platforms: linux/amd64
cache-from: type=gha
cache-to: type=gha,mode=max
- name: Ping IndexNow
if: startsWith(github.ref, 'refs/tags/v')
continue-on-error: true
env:
INDEXNOW_KEY: e15b139d2290690560df79328a1ced26
SITE_HOST: grantfoster.dev
run: |
# Notifies Bing/Copilot/Yandex of URL changes within seconds. Key file
# at https://${SITE_HOST}/${INDEXNOW_KEY}.txt proves ownership.
# Best-effort — never block a release on a push hiccup.
SITEMAP_URLS=$(curl -sS --max-time 10 "https://${SITE_HOST}/sitemap.xml" \
| grep -oE '<loc>[^<]+</loc>' | sed -E 's,</?loc>,,g')
if [ -z "${SITEMAP_URLS}" ]; then
echo "No URLs in sitemap; skipping IndexNow ping."
exit 0
fi
URL_LIST=$(printf '%s\n' ${SITEMAP_URLS} | jq -R . | jq -s .)
PAYLOAD=$(jq -n \
--arg host "${SITE_HOST}" \
--arg key "${INDEXNOW_KEY}" \
--arg keyLocation "https://${SITE_HOST}/${INDEXNOW_KEY}.txt" \
--argjson urlList "${URL_LIST}" \
'{host:$host, key:$key, keyLocation:$keyLocation, urlList:$urlList}')
echo "Pinging IndexNow with $(echo "${URL_LIST}" | jq 'length') URLs."
curl -sS -X POST "https://api.indexnow.org/indexnow" \
--max-time 15 \
-H "Content-Type: application/json" \
-d "${PAYLOAD}" \
-w "\nHTTP %{http_code}\n" || true
# Canary migration: this repo is the first caller of the BimRoss canonical
# gitops-release reusable workflow. See RELEASING.md in BimRoss/.github
# and the discussion in BimRoss/.github#2 for the design.
gitops-release:
if: startsWith(github.ref, 'refs/tags/v')
needs:
- frontend
uses: BimRoss/.github/.github/workflows/gitops-release.yml@91ea84482a8b74acf0f63feebce7187bea0ecc30 # v1
secrets: inherit
with:
app_slug: grantfoster-website
version: ${{ needs.frontend.outputs.version }}
images: |
geeemoney/grantfoster-website
manifest_paths: |
admin/apps/grantfoster-website/deployment.yaml
commit_subject: "release(grantfoster-website): bump image to ${{ needs.frontend.outputs.version }}"