v5.4.5 -- Astro v5.9.2 #1051
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: CI/CD Pipeline for Revista-4 | |
| on: | |
| push: | |
| branches: [main] | |
| pull_request: | |
| branches: [main] | |
| release: | |
| types: [published] | |
| env: | |
| REGISTRY_IMAGE: erfianugrah/revista-4 | |
| jobs: | |
| build-revista: | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: Checkout repository | |
| uses: actions/checkout@v4 | |
| - name: Setup Bun environment | |
| uses: oven-sh/setup-bun@v1 | |
| - name: Cache dependencies and build artifacts | |
| uses: actions/cache@v4 | |
| with: | |
| path: | | |
| ~/.bun/install/cache | |
| node_modules | |
| .astro | |
| dist | |
| key: ${{ runner.os }}-bun-${{ hashFiles('**/bun.lockb') }}-${{ hashFiles('**/package.json') }}-${{ hashFiles('src/**') }} | |
| restore-keys: | | |
| ${{ runner.os }}-bun-${{ hashFiles('**/bun.lockb') }}-${{ hashFiles('**/package.json') }}- | |
| ${{ runner.os }}-bun-${{ hashFiles('**/bun.lockb') }}- | |
| ${{ runner.os }}-bun- | |
| - name: Install project dependencies | |
| run: bun install | |
| - name: Build project with retry | |
| env: | |
| MAX_ATTEMPTS: 3 | |
| RETRY_INTERVAL: 30 | |
| run: | | |
| attempt=1 | |
| until bun run build || [ $attempt -eq $MAX_ATTEMPTS ]; do | |
| echo "Build attempt $attempt failed. Retrying in $RETRY_INTERVAL seconds..." | |
| sleep $RETRY_INTERVAL | |
| attempt=$((attempt + 1)) | |
| done | |
| if [ $attempt -eq $MAX_ATTEMPTS ] && ! bun run build; then | |
| echo "Build failed after $MAX_ATTEMPTS attempts." | |
| exit 1 | |
| fi | |
| - name: Upload build artifacts | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: dist | |
| path: dist | |
| retention-days: 7 | |
| deploy-to-deno: | |
| needs: build-revista | |
| runs-on: ubuntu-latest | |
| permissions: | |
| id-token: write | |
| contents: read | |
| steps: | |
| - name: Download build artifacts | |
| uses: actions/download-artifact@v4 | |
| with: | |
| name: dist | |
| path: dist | |
| - name: Setup Deno | |
| uses: denoland/setup-deno@v1 | |
| with: | |
| deno-version: v1.x | |
| - name: Deploy to Deno | |
| uses: denoland/deployctl@v1 | |
| with: | |
| project: "revista-3" | |
| entrypoint: "https://deno.land/std@0.188.0/http/file_server.ts" | |
| root: "dist" | |
| deploy-to-cloudflare: | |
| needs: build-revista | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@v4 | |
| with: | |
| fetch-depth: 2 | |
| - name: Download built artifacts | |
| uses: actions/download-artifact@v4 | |
| with: | |
| name: dist | |
| path: dist | |
| - name: Setup Bun | |
| uses: oven-sh/setup-bun@v1 | |
| - name: Get git information | |
| id: git-info | |
| run: | | |
| echo "COMMIT_HASH=$(git rev-parse HEAD)" >> $GITHUB_OUTPUT | |
| echo "COMMIT_MESSAGE=$(git log -1 --pretty=%B)" >> $GITHUB_OUTPUT | |
| echo "BRANCH_NAME=$(git rev-parse --abbrev-ref HEAD)" >> $GITHUB_OUTPUT | |
| echo "COMMIT_DIRTY=$(if [[ -n $(git status -s) ]]; then echo true; else echo false; fi)" >> $GITHUB_OUTPUT | |
| - name: Deploy to Cloudflare Pages | |
| uses: cloudflare/wrangler-action@v3 | |
| with: | |
| apiToken: ${{ secrets.CLOUDFLARE_WRANGLER_TOKEN }} | |
| accountId: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }} | |
| command: pages deploy dist --project-name=revista-4 --commit-hash "${{ steps.git-info.outputs.COMMIT_HASH }}" --commit-message "${{ steps.git-info.outputs.COMMIT_MESSAGE }}" --branch "${{ steps.git-info.outputs.BRANCH_NAME }}" --commit-dirty ${{ steps.git-info.outputs.COMMIT_DIRTY }} | |
| wranglerVersion: '3.70.0' | |
| packageManager: bun | |
| prepare-docker: | |
| needs: build-revista | |
| runs-on: ubuntu-latest | |
| outputs: | |
| new_tag: ${{ steps.get_tag.outputs.NEW_TAG }} | |
| steps: | |
| - name: Checkout repository | |
| uses: actions/checkout@v4 | |
| with: | |
| fetch-depth: 2 | |
| - name: Determine version increment type | |
| id: check_commit_message | |
| run: | | |
| COMMIT_MSG=$(git log -1 --pretty=%B) | |
| if echo "$COMMIT_MSG" | grep -qE "^\[major\]"; then | |
| echo "VERSION_INCREMENT=major" >> $GITHUB_OUTPUT | |
| elif echo "$COMMIT_MSG" | grep -qE "^\[minor\]"; then | |
| echo "VERSION_INCREMENT=minor" >> $GITHUB_OUTPUT | |
| else | |
| echo "VERSION_INCREMENT=patch" >> $GITHUB_OUTPUT | |
| fi | |
| - name: Generate new version tag | |
| id: get_tag | |
| run: | | |
| # Fetch all tags and sort them | |
| echo "Fetching tags for ${REGISTRY_IMAGE}..." | |
| TAGS_JSON=$(curl -s "https://hub.docker.com/v2/repositories/${REGISTRY_IMAGE}/tags/?page_size=100") | |
| echo "Fetched tags JSON:" | |
| echo "$TAGS_JSON" | jq '.' | |
| ALL_TAGS=$(echo "$TAGS_JSON" | jq -r '.results[].name' | grep -E '^v?[0-9]+\.[0-9]+\.[0-9]+$' | sort -V) | |
| echo "Sorted semantic version tags:" | |
| echo "$ALL_TAGS" | |
| if [ -z "$ALL_TAGS" ]; then | |
| echo "No existing semantic version tags found." | |
| NEW_TAG="0.0.1" | |
| else | |
| LATEST_TAG=$(echo "$ALL_TAGS" | tail -n 1) | |
| echo "Latest tag: $LATEST_TAG" | |
| # Remove 'v' prefix if present | |
| LATEST_TAG=${LATEST_TAG#v} | |
| IFS='.' read -r MAJOR MINOR PATCH <<< "$LATEST_TAG" | |
| # Increment version based on commit message or default to patch | |
| case "${{ steps.check_commit_message.outputs.VERSION_INCREMENT }}" in | |
| major) | |
| MAJOR=$((MAJOR+1)) | |
| MINOR=0 | |
| PATCH=0 | |
| ;; | |
| minor) | |
| MINOR=$((MINOR+1)) | |
| PATCH=0 | |
| ;; | |
| patch|*) | |
| PATCH=$((PATCH+1)) | |
| ;; | |
| esac | |
| NEW_TAG="${MAJOR}.${MINOR}.${PATCH}" | |
| # Check if the new tag already exists | |
| while echo "$ALL_TAGS" | grep -q "^v?${NEW_TAG}$"; do | |
| case "${{ steps.check_commit_message.outputs.VERSION_INCREMENT }}" in | |
| major) | |
| MAJOR=$((MAJOR+1)) | |
| ;; | |
| minor) | |
| MINOR=$((MINOR+1)) | |
| ;; | |
| patch|*) | |
| PATCH=$((PATCH+1)) | |
| ;; | |
| esac | |
| NEW_TAG="${MAJOR}.${MINOR}.${PATCH}" | |
| done | |
| fi | |
| echo "NEW_TAG=$NEW_TAG" >> $GITHUB_OUTPUT | |
| echo "New tag: $NEW_TAG" | |
| build-and-push-docker: | |
| needs: [build-revista, prepare-docker] | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: Checkout repository | |
| uses: actions/checkout@v4 | |
| - name: Download build artifacts | |
| uses: actions/download-artifact@v4 | |
| with: | |
| name: dist | |
| path: dist | |
| - name: Set up QEMU | |
| uses: docker/setup-qemu-action@v3 | |
| - name: Set up Docker Buildx | |
| uses: docker/setup-buildx-action@v3 | |
| - name: Login to Docker Hub | |
| uses: docker/login-action@v3 | |
| with: | |
| username: ${{ secrets.DOCKER_USERNAME }} | |
| password: ${{ secrets.DOCKER_REGISTRY_TOKEN }} | |
| - name: Build and push Docker image | |
| uses: docker/build-push-action@v6 | |
| with: | |
| context: . | |
| file: ./Dockerfile | |
| platforms: linux/amd64,linux/arm64,linux/arm/v6,linux/arm/v7 | |
| push: true | |
| tags: | | |
| ${{ env.REGISTRY_IMAGE }}:${{ needs.prepare-docker.outputs.new_tag }} | |
| ${{ env.REGISTRY_IMAGE }}:latest | |
| cache-from: type=gha | |
| cache-to: type=gha,mode=max | |
| provenance: true | |
| sbom: true | |
| inspect-docker-image: | |
| needs: [prepare-docker, build-and-push-docker] | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: Inspect Docker image | |
| run: | | |
| docker buildx imagetools inspect ${{ env.REGISTRY_IMAGE }}:${{ needs.prepare-docker.outputs.new_tag }} | |
| sign-docker-image: | |
| needs: [prepare-docker, build-and-push-docker, inspect-docker-image] | |
| runs-on: ubuntu-latest | |
| permissions: | |
| contents: read | |
| packages: write | |
| id-token: write # Needed for keyless signing | |
| steps: | |
| - name: Install Cosign | |
| uses: sigstore/cosign-installer@v3.6.0 | |
| with: | |
| cosign-release: 'v2.4.0' | |
| - name: Login to Docker Hub | |
| uses: docker/login-action@v3 | |
| with: | |
| username: ${{ secrets.DOCKER_USERNAME }} | |
| password: ${{ secrets.DOCKER_REGISTRY_TOKEN }} | |
| - name: Install jq | |
| run: sudo apt-get update && sudo apt-get install -y jq | |
| - name: Get image digest | |
| id: get_digest | |
| run: | | |
| DIGEST=$(docker buildx imagetools inspect ${REGISTRY_IMAGE}:${{ needs.prepare-docker.outputs.new_tag }} --format '{{json .}}' | jq -r 'if .manifest then .manifest.digest elif .Descriptor then .Descriptor.digest else .digest end') | |
| echo "IMAGE_DIGEST=${DIGEST}" >> $GITHUB_OUTPUT | |
| echo "Image digest: ${DIGEST}" | |
| - name: Sign the Docker image | |
| env: | |
| COSIGN_EXPERIMENTAL: 1 | |
| run: | | |
| cosign sign --yes ${REGISTRY_IMAGE}@${{ steps.get_digest.outputs.IMAGE_DIGEST }} | |
| - name: Verify Docker image signature | |
| env: | |
| COSIGN_EXPERIMENTAL: 1 | |
| run: | | |
| cosign verify ${REGISTRY_IMAGE}@${{ steps.get_digest.outputs.IMAGE_DIGEST }} \ | |
| --certificate-identity-regexp="https://github.com/${GITHUB_REPOSITORY}/.*" \ | |
| --certificate-oidc-issuer=https://token.actions.githubusercontent.com | |
| purge-cloudflare-cache: | |
| needs: [deploy-to-deno, deploy-to-cloudflare, sign-docker-image] | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: Purge Cloudflare Cache | |
| run: | | |
| curl -X POST "https://api.cloudflare.com/client/v4/zones/${{ secrets.CLOUDFLARE_ZONE_ID }}/purge_cache" \ | |
| -H "Authorization: Bearer ${{ secrets.CLOUDFLARE_CACHE_PURGE_TOKEN }}" \ | |
| -H "Content-Type: application/json" \ | |
| --data '{"hosts":["${{ secrets.CLOUDFLARE_ZONE_NAME }}", "${{ secrets.CLOUDFLARE_WWW}}" ]}' |