vibecoded-personal-site/.github/workflows/build.yml
badbl0cks e245bcbe96
Some checks failed
Build/Deploy / trigger-dev-build (push) Has been cancelled
Build/Deploy / trigger-staging-build (push) Has been cancelled
Build/Deploy / trigger-main-build (push) Has been cancelled
feat: add in copy of updated shared deployment workflows for now until they are
published
2025-08-14 18:42:59 -07:00

240 lines
10 KiB
YAML

# yaml-language-server: $schema=https://json-schema.org/draft-07/schema#
name: _build
concurrency:
group: build
cancel-in-progress: false
on:
workflow_call:
jobs:
check:
runs-on: ubuntu-latest
permissions:
actions: read
contents: read
outputs:
should-build: ${{ steps.check.outputs.should-build }}
artifact-run-id: ${{ steps.check.outputs.artifact-run-id }}
artifact-id: ${{ steps.check.outputs.artifact-id }}
build-sha: ${{ steps.check.outputs.build-sha }}
repo-name: ${{ steps.meta.outputs.repo-name }}
repo-path: ${{ steps.meta.outputs.repo-path }}
image-tar: ${{ steps.check.outputs.image-tar }}
prod: ${{ steps.meta.outputs.prod }}
tag: ${{ steps.check.outputs.tag }}
should-deploy: ${{ steps.check.outputs.should-deploy }}
steps:
- name: Checkout the repo
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Determine build metadata
id: meta
uses: ./.github/actions/determine-build-metadata
with:
repository: ${{ github.repository }}
github-ref: ${{ github.ref }}
- name: Check if build/deploy needed
id: check
env:
GH_TOKEN: ${{ github.token }}
run: |
set -eu -o pipefail
SHOULD_BUILD=false
SHOULD_DEPLOY=false
SHORT_SHA="${{ github.sha }}"
SHORT_SHA="${SHORT_SHA:0:7}"
IMAGE_TAR="${{ steps.meta.outputs.repo-name }}-${{github.sha}}.tar"
VERSION="$(git tag --points-at ${{ github.sha }})"
IS_VERSION_TAGGED="$([[ "$VERSION" =~ ^v ]] && echo "true" || echo "false")"
BRANCH_NAME="$([[ "${{ github.ref }}" =~ ^refs/tags/v ]] && echo "main" || echo "${{ github.ref }}" | sed 's/refs\/heads\///')"
COMMIT_MESSAGE="$(git log --format=%s -n 1 ${{ github.sha }})"
if [[ "${{ steps.meta.outputs.prod }}" == "true" ]]; then
TAG="${{ steps.meta.outputs.repo-name }}:sha-${SHORT_SHA},${{ steps.meta.outputs.repo-name }}:latest"
else
TAG="${{ steps.meta.outputs.repo-name }}-dev:sha-${SHORT_SHA}"
fi
if [[ "$BRANCH_NAME" == "staging" ]]; then
echo "🔨 Build is on staging - will also deploy to staging"
SHOULD_DEPLOY="true"
elif [[ "$BRANCH_NAME" == "main" ]]; then
if [[ ! "$COMMIT_MESSAGE" =~ ^chore:\ Release ]] || [[ "$IS_VERSION_TAGGED" == "false" ]]; then
echo "❌ Skipping build for main: $COMMIT_MESSAGE. Not a version release. Missing tag or proper commit message for release."
exit 1
fi
echo "🏷️ Version tagged build on main: $VERSION - will also deploy to production"
SHOULD_DEPLOY="true"
fi
echo "🔍 Checking for in progress builds with git SHA ${{github.sha}}"
IN_PROGRESS_BUILDS=""
if ! IN_PROGRESS_BUILDS=$(gh api repos/${{github.repository}}/actions/runs --jq '.workflow_runs[] | select(.head_sha == "${{github.sha}}" and .status == "in_progress" and .name == "Build/Deploy" and .id != ${{ github.run_id }}) | .id' 2>/dev/null); then
echo "❌ Failed to check for in-progress builds via GitHub API"
echo "::error::GitHub API call failed while checking for in-progress builds"
exit 1
fi
IN_PROGRESS_BUILDS=$(echo "$IN_PROGRESS_BUILDS" | head -1)
if [[ -n "$IN_PROGRESS_BUILDS" ]]; then
echo "❌ Found in-progress build for SHA ${{github.sha}}: $IN_PROGRESS_BUILDS - wait for existing build to complete before triggering a new one or rerunning this workflow"
exit 1
fi
echo "🔍 Checking for existing build artifacts with git SHA ${{github.sha}}"
# Check for existing artifacts with this SHA across all workflow runs
ARTIFACT_INFO=""
if ! ARTIFACT_INFO=$(gh api repos/${{github.repository}}/actions/artifacts --jq '.artifacts[] | select(.name | endswith("-${{github.sha}}.tar")) | {id, name, workflow_run} | @json' 2>/dev/null); then
echo "❌ Failed to check for existing artifacts via GitHub API"
echo "::error::GitHub API call failed while checking for existing artifacts"
exit 1
fi
ARTIFACT_INFO=$(echo "$ARTIFACT_INFO" | head -1)
if [[ -n "$ARTIFACT_INFO" ]]; then
ARTIFACT_ID=$(echo "$ARTIFACT_INFO" | jq -r '.id')
ARTIFACT_NAME=$(echo "$ARTIFACT_INFO" | jq -r '.name')
RUN_ID=$(echo "$ARTIFACT_INFO" | jq -r '.workflow_run.id')
echo "✅ Found existing artifact $ARTIFACT_NAME from run: $RUN_ID"
echo "artifact-id=$ARTIFACT_ID" >> $GITHUB_OUTPUT
echo "artifact-id -> $ARTIFACT_ID"
else
RUN_ID="${{ github.run_id }}"
SHOULD_BUILD="true"
echo "🔨 No existing build artifact found; will build..."
fi
echo "should-build=$SHOULD_BUILD" >> $GITHUB_OUTPUT
echo "should-build -> $SHOULD_BUILD"
echo "should-deploy=$SHOULD_DEPLOY" >> $GITHUB_OUTPUT
echo "should-deploy -> $SHOULD_DEPLOY"
echo "artifact-run-id=$RUN_ID" >> $GITHUB_OUTPUT
echo "artifact-run-id -> $RUN_ID"
echo "build-sha=${{github.sha}}" >> $GITHUB_OUTPUT
echo "build-sha -> ${{github.sha}}"
echo "image-tar=$IMAGE_TAR" >> $GITHUB_OUTPUT
echo "image-tar -> $IMAGE_TAR"
echo "tag=$TAG" >> $GITHUB_OUTPUT
echo "tag -> $TAG"
build:
needs: check
if: ${{ needs.check.outputs.should-build == 'true' }}
runs-on: ubuntu-latest
outputs:
artifact-id: ${{ steps.upload-artifact.outputs.artifact-id }}
steps:
- name: Checkout the repo
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Ensure scripts are executable
run: chmod +x deploy/scripts/*.sh
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Generate cache keys
id: cache-keys
run: |
# Generate cache key based on package-lock.json for dependencies
DEPS_HASH=$(sha256sum package-lock.json | cut -d' ' -f1 | cut -c1-8)
echo "deps-hash=${DEPS_HASH}" >> $GITHUB_OUTPUT
echo "deps-hash -> $DEPS_HASH"
# Generate cache key based on source files and paths
SOURCE_PATHS="app/ server/ public/ nuxt.config.ts tsconfig.json tailwind.config.js package.json"
SRC_HASH=$(find $SOURCE_PATHS -type f 2>/dev/null -exec sha256sum {} + | sha256sum | cut -d' ' -f1 | cut -c1-8 || echo "fallback-$(date +%s)")
echo "src-hash=${SRC_HASH}" >> $GITHUB_OUTPUT
echo "src-hash -> $SRC_HASH"
- name: Cache Docker layers
uses: actions/cache@v4
with:
path: /tmp/.buildx-cache
key: ${{ runner.os }}-buildx-deps-${{ steps.cache-keys.outputs.deps-hash }}-src-${{ steps.cache-keys.outputs.src-hash }}-${{ github.sha }}
restore-keys: |
${{ runner.os }}-buildx-deps-${{ steps.cache-keys.outputs.deps-hash }}-src-${{ steps.cache-keys.outputs.src-hash }}-
${{ runner.os }}-buildx-deps-${{ steps.cache-keys.outputs.deps-hash }}-
${{ runner.os }}-buildx-
- name: Extract version for Docker build
id: extract_version
run: |
if [[ "${{ github.ref }}" =~ ^refs/tags/v([0-9]+\.[0-9]+\.[0-9]+)(-.*)?$ ]]; then
VERSION="${BASH_REMATCH[1]}"
if [[ -n "${BASH_REMATCH[2]}" ]]; then
VERSION="${VERSION}${BASH_REMATCH[2]}"
fi
echo "🏷️ Using git tag version: ${VERSION}"
else
VERSION=$(node -p "require('./package.json').version || '0.0.0'")
SHA="${{ github.sha }}"
GIT_SHA_SHORT="${SHA:0:7}"
VERSION="${VERSION}+${GIT_SHA_SHORT}"
echo "📦 Using package.json + SHA version: ${VERSION}"
fi
echo "VERSION=${VERSION}" >> $GITHUB_ENV
- name: Build container
uses: docker/build-push-action@v6
with:
outputs: type=docker,dest=${{ runner.temp }}/${{ needs.check.outputs.image-tar }}
tags: ${{ needs.check.outputs.tag }}
build-args: |
VERSION=${{ env.VERSION }}
context: .
target: runtime
cache-from: type=local,src=/tmp/.buildx-cache
cache-to: type=local,dest=/tmp/.buildx-cache-new,mode=max
platforms: linux/amd64
- name: Rotate cache
run: |
rm -rf /tmp/.buildx-cache
mv /tmp/.buildx-cache-new /tmp/.buildx-cache
- name: Upload container as artifact
id: upload-artifact
uses: actions/upload-artifact@v4
with:
name: ${{ needs.check.outputs.image-tar }}
path: ${{ runner.temp }}/${{ needs.check.outputs.image-tar }}
if-no-files-found: error
retention-days: 30
compression-level: 0
- name: Notify successful build
run: |
echo "🎉 Build completed successfully!"
echo "📋 Summary:"
echo " - Source: ${{ github.ref }}"
echo " - Status: ✅ Build Successful"
echo " - Next: Stage this build manually or wait for the next scheduled staging."
deploy:
needs: [check, build]
if: ${{ always() && needs.check.outputs.should-deploy == 'true' }}
permissions:
actions: read
contents: read
uses: ./.github/workflows/deploy.yml
with:
artifact-run-id: ${{ needs.check.outputs.artifact-run-id }}
artifact-id: ${{ needs.check.outputs.should-build == 'true' && needs.build.outputs.artifact-id || needs.check.outputs.artifact-id }}
build-sha: ${{ needs.check.outputs.build-sha }}
repo-name: ${{ needs.check.outputs.repo-name }}
repo-path: ${{ needs.check.outputs.repo-path }}
image-tar: ${{ needs.check.outputs.image-tar }}
prod: ${{ needs.check.outputs.prod == 'true' }}
tag: ${{ needs.check.outputs.tag }}
secrets: inherit