From 1c64698c181bb7f24b90a1ed0b5e0f5a8a4aff98 Mon Sep 17 00:00:00 2001 From: Sean McGrath Date: Thu, 1 Jan 2026 19:57:17 +1300 Subject: [PATCH 1/2] ci: push to ghcr instead of dockerhub --- .../workflows/post-release-push-images.yml | 60 +++++++++++++------ 1 file changed, 42 insertions(+), 18 deletions(-) diff --git a/.github/workflows/post-release-push-images.yml b/.github/workflows/post-release-push-images.yml index 145ebfdf2..fd2ac366f 100644 --- a/.github/workflows/post-release-push-images.yml +++ b/.github/workflows/post-release-push-images.yml @@ -1,4 +1,4 @@ -name: Publish Docker image +name: Publish Container Image on: release: @@ -7,56 +7,76 @@ on: jobs: push_to_registry: - name: Push Docker images to Docker Hub + name: Push Docker images to GHCR runs-on: ubuntu-latest + permissions: + contents: read + packages: write + steps: - name: Check out the repo - uses: actions/checkout@v4 + uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 with: - token: ${{ secrets.GITHUB_TOKEN }} - persist-credentials: true + fetch-depth: 0 - - name: Log in to Docker Hub - uses: docker/login-action@v2 + - name: Log in to GHCR + uses: docker/login-action@5e57cd118135c172c3672efd75eb46360885c0ef # v3.6.0 with: - username: ${{ secrets.DOCKER_USERNAME }} - password: ${{ secrets.DOCKER_PASSWORD }} + registry: ghcr.io + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} + + - name: Normalise image repository path + run: | + echo "IMAGE_REPO=$(echo "$GITHUB_REPOSITORY" | tr '[:upper:]' '[:lower:]')" >> "$GITHUB_ENV" # All-in-one Image Steps - name: Extract metadata (tags, labels) for All-in-one Docker id: meta_all_in_one - uses: docker/metadata-action@v3 + uses: docker/metadata-action@c299e40c65443455700f0fdfc63efafe5b349051 # v5.10.0 with: - images: daveearley/hi.events-all-in-one + images: ghcr.io/${{ env.IMAGE_REPO }} tags: | type=ref,event=tag type=raw,value=latest,enable=${{ github.event.release.prerelease == false }} + type=semver,pattern=v{{version}} + type=semver,pattern=v{{major}}.{{minor}} + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@e468171a9de216ec08956ac3ada2f0791b6bd435 # v3.11.1 - name: Build and push All-in-one Docker image - uses: docker/build-push-action@v3 + uses: docker/build-push-action@263435318d21b8e681c14492fe198d362a7d2c83 # 6.18.0 with: context: ./ file: ./Dockerfile.all-in-one + cache-from: type=gha + cache-to: type=gha,mode=max push: true tags: ${{ steps.meta_all_in_one.outputs.tags }} labels: ${{ steps.meta_all_in_one.outputs.labels }} + # Backend Image Steps - name: Extract metadata (tags, labels) for Backend Docker id: meta_backend - uses: docker/metadata-action@v3 + uses: docker/metadata-action@c299e40c65443455700f0fdfc63efafe5b349051 # v5.10.0 with: - images: daveearley/hi.events-backend + images: ghcr.io/${{ env.IMAGE_REPO }}-backend tags: | type=ref,event=tag type=raw,value=latest,enable=${{ github.event.release.prerelease == false }} + type=semver,pattern=v{{version}} + type=semver,pattern=v{{major}}.{{minor}} - name: Build and push Backend Docker image - uses: docker/build-push-action@v3 + uses: docker/build-push-action@263435318d21b8e681c14492fe198d362a7d2c83 # 6.18.0 with: context: ./backend file: ./backend/Dockerfile + cache-from: type=gha + cache-to: type=gha,mode=max push: true tags: ${{ steps.meta_backend.outputs.tags }} labels: ${{ steps.meta_backend.outputs.labels }} @@ -64,18 +84,22 @@ jobs: # Frontend Image Steps - name: Extract metadata (tags, labels) for Frontend Docker id: meta_frontend - uses: docker/metadata-action@v3 + uses: docker/metadata-action@c299e40c65443455700f0fdfc63efafe5b349051 # v5.10.0 with: - images: daveearley/hi.events-frontend + images: ghcr.io/${{ env.IMAGE_REPO }}-frontend tags: | type=ref,event=tag type=raw,value=latest,enable=${{ github.event.release.prerelease == false }} + type=semver,pattern=v{{version}} + type=semver,pattern=v{{major}}.{{minor}} - name: Build and push Frontend Docker image - uses: docker/build-push-action@v3 + uses: docker/build-push-action@263435318d21b8e681c14492fe198d362a7d2c83 # 6.18.0 with: context: ./frontend file: ./frontend/Dockerfile.ssr + cache-from: type=gha + cache-to: type=gha,mode=max push: true tags: ${{ steps.meta_frontend.outputs.tags }} labels: ${{ steps.meta_frontend.outputs.labels }} From d43c78fe97d6f760fd9319ce9502416762bdbfb0 Mon Sep 17 00:00:00 2001 From: Sean McGrath Date: Thu, 1 Jan 2026 19:57:26 +1300 Subject: [PATCH 2/2] chore: remove unused workflows --- .github/workflows/cla.yml | 30 ----- .github/workflows/deploy.yml | 206 ----------------------------------- 2 files changed, 236 deletions(-) delete mode 100644 .github/workflows/cla.yml delete mode 100644 .github/workflows/deploy.yml diff --git a/.github/workflows/cla.yml b/.github/workflows/cla.yml deleted file mode 100644 index 6f23c1e21..000000000 --- a/.github/workflows/cla.yml +++ /dev/null @@ -1,30 +0,0 @@ -name: "CLA Assistant" -on: - issue_comment: - types: [created] - pull_request_target: - types: [opened,closed,synchronize] - -permissions: - actions: write - contents: read - pull-requests: write - statuses: write - -jobs: - CLAAssistant: - runs-on: ubuntu-latest - steps: - - name: "CLA Assistant" - if: (github.event.comment.body == 'recheck' || github.event.comment.body == 'I have read the CLA Document and I hereby sign the CLA') || github.event_name == 'pull_request_target' - uses: contributor-assistant/github-action@v2.4.0 - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - PERSONAL_ACCESS_TOKEN: ${{ secrets.PERSONAL_ACCESS_TOKEN }} - with: - path-to-signatures: 'signatures.json' - path-to-document: 'https://github.com/HiEventsDev/hi.events/blob/develop/CLA.md' - branch: 'main' - allowlist: daveearley,bot* - remote-organization-name: HiEventsDev - remote-repository-name: cla-signatures diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml deleted file mode 100644 index 2d19756c0..000000000 --- a/.github/workflows/deploy.yml +++ /dev/null @@ -1,206 +0,0 @@ -name: Deploy to Vapor and Frontend - -on: - push: - branches: - - main - - develop - - feature/vapor-env-updates - workflow_dispatch: - inputs: - environment: - description: 'Environment to deploy to' - required: true - default: 'staging' - type: choice - options: - - staging - - production - test_mode: - description: 'Run in test mode (no actual deployment)' - required: false - default: false - type: boolean - -jobs: - backend: - name: Deploy Backend - runs-on: ubuntu-latest - - steps: - - uses: actions/checkout@v3 - - - name: Setup PHP - uses: shivammathur/setup-php@v2 - with: - php-version: 8.3 - tools: composer:v2 - coverage: none - - - name: Prepare Laravel Environment - working-directory: ./backend - run: | - mkdir -p bootstrap/cache - chmod -R 775 bootstrap/cache - - - name: Prepare HTMLPurifier Cache Directory - working-directory: ./backend - run: | - mkdir -p storage/app/htmlpurifier - chmod -R 775 storage/app/htmlpurifier - - - name: Install Dependencies - working-directory: ./backend - run: composer install --no-dev --no-progress --no-scripts --optimize-autoloader - - - name: Install Vapor CLI - run: composer global require laravel/vapor-cli - - - name: Set Deployment Environment - run: | - if [[ "${{ github.event_name }}" == "workflow_dispatch" ]]; then - echo "VAPOR_ENV=${{ github.event.inputs.environment }}" >> "$GITHUB_ENV" - echo "TEST_MODE=${{ github.event.inputs.test_mode }}" >> "$GITHUB_ENV" - elif [[ "${{ github.ref_name }}" == "main" ]]; then - echo "VAPOR_ENV=production" >> "$GITHUB_ENV" - echo "TEST_MODE=false" >> "$GITHUB_ENV" - elif [[ "${{ github.ref_name }}" == "develop" ]]; then - echo "VAPOR_ENV=staging" >> "$GITHUB_ENV" - echo "TEST_MODE=false" >> "$GITHUB_ENV" - else - echo "VAPOR_ENV=staging" >> "$GITHUB_ENV" - echo "TEST_MODE=false" >> "$GITHUB_ENV" - fi - - - name: Log Branch and Environment - run: | - echo "๐Ÿš€ Deploying to Vapor environment: ${{ env.VAPOR_ENV }}" - echo "๐Ÿงช Test mode: ${{ env.TEST_MODE }}" - - - name: Configure AWS Credentials - if: env.TEST_MODE != 'true' - uses: aws-actions/configure-aws-credentials@v4 - with: - aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }} - aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY_ID }} - aws-region: eu-west-1 - - - name: Download Encrypted Environment File from S3 - if: env.TEST_MODE != 'true' - working-directory: ./backend - run: | - aws s3 cp s3://hi.events-env-secrets/.env.${{ env.VAPOR_ENV }}.encrypted .env.${{ env.VAPOR_ENV }}.encrypted - echo "โœ… Downloaded .env.${{ env.VAPOR_ENV }}.encrypted from S3" - - - name: Validate Deployment Configuration - working-directory: ./backend - run: | - if [[ "${{ env.TEST_MODE }}" == "true" ]]; then - echo "โœ… TEST MODE: Would deploy to ${{ env.VAPOR_ENV }} environment" - echo "vapor deploy ${{ env.VAPOR_ENV }} --dry-run" - exit 0 - fi - - - name: Deploy to Vapor - if: env.TEST_MODE != 'true' - working-directory: ./backend - run: vapor deploy ${{ env.VAPOR_ENV }} - env: - VAPOR_API_TOKEN: ${{ secrets.VAPOR_API_TOKEN }} - - frontend: - name: Deploy Frontend - runs-on: ubuntu-latest - needs: backend - - steps: - - uses: actions/checkout@v3 - - - name: Set Deployment Environment - run: | - if [[ "${{ github.event_name }}" == "workflow_dispatch" ]]; then - if [[ "${{ github.event.inputs.environment }}" == "staging" ]]; then - echo "DO_APP_ID=${{ secrets.DIGITALOCEAN_STAGING_APP_ID }}" >> "$GITHUB_ENV" - else - echo "DO_APP_ID=${{ secrets.DIGITALOCEAN_PRODUCTION_APP_ID }}" >> "$GITHUB_ENV" - fi - echo "TEST_MODE=${{ github.event.inputs.test_mode }}" >> "$GITHUB_ENV" - elif [[ "${{ github.ref_name }}" == "main" ]]; then - echo "DO_APP_ID=${{ secrets.DIGITALOCEAN_PRODUCTION_APP_ID }}" >> "$GITHUB_ENV" - echo "TEST_MODE=false" >> "$GITHUB_ENV" - elif [[ "${{ github.ref_name }}" == "develop" ]]; then - echo "DO_APP_ID=${{ secrets.DIGITALOCEAN_STAGING_APP_ID }}" >> "$GITHUB_ENV" - echo "TEST_MODE=false" >> "$GITHUB_ENV" - else - echo "DO_APP_ID=${{ secrets.DIGITALOCEAN_STAGING_APP_ID }}" >> "$GITHUB_ENV" - echo "TEST_MODE=false" >> "$GITHUB_ENV" - fi - - - name: Log Environment Settings - run: | - echo "๐Ÿš€ Deploying frontend to DigitalOcean App: ${{ env.DO_APP_ID }}" - echo "๐Ÿงช Test mode: ${{ env.TEST_MODE }}" - - - name: Validate Deployment Configuration (Test Mode) - if: env.TEST_MODE == 'true' - run: | - echo "โœ… TEST MODE: Would trigger deployment for DigitalOcean App: ${{ env.DO_APP_ID }}" - echo "curl -X POST 'https://api.digitalocean.com/v2/apps/${{ env.DO_APP_ID }}/deployments'" - exit 0 - - - name: Trigger Deployment on DigitalOcean - if: env.TEST_MODE != 'true' - id: trigger_deployment - run: | - RESPONSE=$(curl -s -o response.json -w "%{http_code}" -X POST "https://api.digitalocean.com/v2/apps/$DO_APP_ID/deployments" \ - -H "Authorization: Bearer ${{ secrets.DIGITALOCEAN_API_TOKEN }}" \ - -H "Content-Type: application/json") - - if [ "$RESPONSE" -ne 201 ] && [ "$RESPONSE" -ne 200 ]; then - ERROR_MSG=$(jq -r '.message // "Unknown error occurred."' response.json) - echo "โŒ Failed to trigger deployment. HTTP Status: $RESPONSE. Error: $ERROR_MSG" - exit 1 - fi - - DEPLOYMENT_ID=$(jq -r '.deployment.id' response.json) - if [ "$DEPLOYMENT_ID" == "null" ]; then - echo "โŒ Failed to extract deployment ID." - exit 1 - fi - - echo "::add-mask::$DEPLOYMENT_ID" - echo "โœ… Deployment triggered successfully." - - echo "deployment_id=$DEPLOYMENT_ID" >> "$GITHUB_ENV" - - - name: Poll Deployment Status - if: env.TEST_MODE != 'true' - run: | - MAX_RETRIES=60 - SLEEP_TIME=10 - COUNTER=0 - - while [ $COUNTER -lt $MAX_RETRIES ]; do - RESPONSE=$(curl -s -X GET "https://api.digitalocean.com/v2/apps/$DO_APP_ID/deployments/${{ env.deployment_id }}" \ - -H "Authorization: Bearer ${{ secrets.DIGITALOCEAN_API_TOKEN }}" \ - -H "Content-Type: application/json") - - STATUS=$(echo "$RESPONSE" | jq -r '.deployment.phase') - - echo "๐Ÿ”„ Deployment Status: $STATUS" - - if [ "$STATUS" == "ACTIVE" ]; then - echo "โœ… Deployment completed successfully." - exit 0 - elif [[ "$STATUS" == "FAILED" || "$STATUS" == "CANCELED" ]]; then - echo "โŒ Deployment failed or was cancelled." - exit 1 - fi - - COUNTER=$((COUNTER + 1)) - echo "โณ Retrying in $SLEEP_TIME seconds... ($COUNTER/$MAX_RETRIES)" - sleep $SLEEP_TIME - done - - echo "โฐ Deployment timed out." - exit 1