From 0c4f667026738a1fc02123cefc7055d3bd281814 Mon Sep 17 00:00:00 2001 From: Nicholas Avenell Date: Thu, 4 Jun 2026 00:24:22 +0100 Subject: [PATCH 1/3] =?UTF-8?q?=E2=9A=99=EF=B8=8F=20Standardise=20CI/CD=20?= =?UTF-8?q?to=20match=20docket/wereabouts=20pattern?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - ci.yml: replace docker.yml + create-release-tag.yml with standard pattern (test → build-and-push with host pre-build of deps/assets → staging deploy on PRs → production deploy on release tag) - release.yml: standard pattern with set -euo pipefail, env: blocks, tag-exists recovery message - Add dependabot-make-release.yml for automated weekly releases - Add .github/dependabot.yml targeting dependabot-updates branch - Remove docker.yml, create-release-tag.yml, auto-merge-dependabot.yml - docker/production/entrypoint.sh: add APP_KEY check, storage dir creation, error wrappers for artisan commands - .dockerignore: add docs exclusion and preserve README.md Co-Authored-By: Claude Sonnet 4.6 --- .dockerignore | 2 + .github/dependabot.yml | 19 ++ .github/workflows/auto-merge-dependabot.yml | 16 -- .github/workflows/ci.yml | 252 ++++++++++++++++++ .github/workflows/create-release-tag.yml | 125 --------- .github/workflows/dependabot-make-release.yml | 108 ++++++++ .github/workflows/docker.yml | 73 ----- .github/workflows/release.yml | 136 ++++++++++ docker/production/entrypoint.sh | 23 +- 9 files changed, 537 insertions(+), 217 deletions(-) create mode 100644 .github/dependabot.yml delete mode 100644 .github/workflows/auto-merge-dependabot.yml create mode 100644 .github/workflows/ci.yml delete mode 100644 .github/workflows/create-release-tag.yml create mode 100644 .github/workflows/dependabot-make-release.yml delete mode 100644 .github/workflows/docker.yml create mode 100644 .github/workflows/release.yml diff --git a/.dockerignore b/.dockerignore index 0c7c6c1..d5a07d5 100644 --- a/.dockerignore +++ b/.dockerignore @@ -10,5 +10,7 @@ storage/framework/views storage/logs bootstrap/cache tests +docs docker-compose*.yml *.md +!README.md diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 0000000..9e9683b --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,19 @@ +version: 2 +updates: + - package-ecosystem: "composer" + directory: "/" + target-branch: "dependabot-updates" + schedule: + interval: "daily" + + - package-ecosystem: "npm" + directory: "/" + target-branch: "dependabot-updates" + schedule: + interval: "daily" + + - package-ecosystem: "github-actions" + directory: "/" + target-branch: "dependabot-updates" + schedule: + interval: "daily" diff --git a/.github/workflows/auto-merge-dependabot.yml b/.github/workflows/auto-merge-dependabot.yml deleted file mode 100644 index 32b855f..0000000 --- a/.github/workflows/auto-merge-dependabot.yml +++ /dev/null @@ -1,16 +0,0 @@ -name: "[Auto] Merge Dependabot Updates" - -on: - workflow_run: - workflows: ["[Tests] Acceptance Testing"] - types: - - completed - branches-ignore: - - 'main' - -jobs: - automerge: - uses: istic/shared-workflows/.github/workflows/auto-merge-dependabot.yml@main - permissions: - pull-requests: write - contents: write diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..2e1a7d1 --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,252 @@ +name: CI + +on: + push: + branches: [dependabot-updates, 'release/*'] + pull_request: + branches: ['**'] + types: [opened, synchronize, reopened] + workflow_dispatch: + workflow_call: + inputs: + tag: + description: 'Release tag to build and deploy' + type: string + required: true + +env: + REGISTRY: ghcr.io + IMAGE_NAME: ${{ github.repository }} + +jobs: + test: + runs-on: ubuntu-latest + permissions: + contents: read + + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Setup PHP + uses: shivammathur/setup-php@v2 + with: + php-version: '8.4' + tools: composer:v2 + + - name: Setup Node + uses: actions/setup-node@v4 + with: + node-version: '22' + cache: 'npm' + + - name: Cache Composer dependencies + uses: actions/cache@v4 + with: + path: ~/.composer/cache + key: ${{ runner.os }}-composer-${{ hashFiles('composer.lock') }} + restore-keys: ${{ runner.os }}-composer- + + - name: Install PHP dependencies + run: composer install --no-interaction --prefer-dist --optimize-autoloader + + - name: Install Node dependencies + run: npm ci + + - name: Copy environment file + run: cp .env.example .env + + - name: Generate application key + run: php artisan key:generate + + - name: Create SQLite database file + run: touch database/database.sqlite + + - name: Smoke-test migrations + run: php artisan migrate --force + env: + DB_CONNECTION: sqlite + DB_DATABASE: database/database.sqlite + + - name: Build assets + run: npm run build + + - name: Run tests + run: vendor/bin/pest + + build-and-push: + needs: [test] + runs-on: ubuntu-latest + if: | + github.ref != 'refs/heads/dependabot-updates' && + (github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name == github.repository) + permissions: + contents: read + packages: write + + steps: + - name: Checkout + uses: actions/checkout@v4 + with: + ref: ${{ inputs.tag || github.ref }} + + - name: Setup PHP + uses: shivammathur/setup-php@v2 + with: + php-version: '8.4' + tools: composer:v2 + + - name: Install PHP dependencies + run: composer install --no-dev --no-interaction --prefer-dist --optimize-autoloader --no-scripts + + - name: Setup Node + uses: actions/setup-node@v4 + with: + node-version: '22' + + - name: Install Node dependencies + run: npm ci + + - name: Build assets + run: npm run build + + - name: Log in to GitHub Container Registry + uses: docker/login-action@v3 + with: + registry: ${{ env.REGISTRY }} + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} + + - name: Extract metadata + id: meta + uses: docker/metadata-action@v5 + with: + images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }} + tags: | + type=semver,pattern={{version}},value=${{ inputs.tag || github.ref_name }},enable=${{ inputs.tag != '' || startsWith(github.ref, 'refs/tags/v') }} + type=semver,pattern={{major}}.{{minor}},value=${{ inputs.tag || github.ref_name }},enable=${{ inputs.tag != '' || startsWith(github.ref, 'refs/tags/v') }} + type=sha + type=raw,value=latest,enable=${{ inputs.tag != '' || startsWith(github.ref, 'refs/tags/v') }} + type=raw,value=staging,enable=${{ github.event_name == 'pull_request' }} + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v3 + + - name: Build and push + uses: docker/build-push-action@v5 + with: + context: . + file: docker/production/Dockerfile + push: true + tags: ${{ steps.meta.outputs.tags }} + labels: ${{ steps.meta.outputs.labels }} + cache-from: type=gha + cache-to: type=gha,mode=max + build-args: | + APP_VERSION=${{ inputs.tag || github.ref_name }} + APP_PR_NUMBER=${{ github.event.pull_request.number }} + APP_BRANCH=${{ github.head_ref }} + + deploy-staging: + needs: build-and-push + if: github.event_name == 'pull_request' + runs-on: ubuntu-latest + concurrency: + group: deploy-staging + cancel-in-progress: true + permissions: + contents: read + + steps: + - name: Deploy staging + uses: appleboy/ssh-action@v1 + with: + host: firth.water.gkhs.net + username: alchemistic + key: ${{ secrets.FIRTH_SSH_KEY }} + script: | + set -euo pipefail + cd /home/docker/alchemistic-staging + timeout 300 docker compose pull || { + echo "ERROR: docker compose pull failed or timed out after 300s" + exit 1 + } + docker compose up -d || { + echo "ERROR: docker compose up -d failed" + docker compose ps + docker compose logs --tail=50 + exit 1 + } + for i in $(seq 1 30); do + if docker compose exec -T app php artisan --version > /dev/null 2>&1; then + echo "Container ready after ${i} attempt(s)" + break + fi + if [ "$i" -eq 30 ]; then + echo "ERROR: Container failed to become ready after 30 attempts" + echo "--- Final health check output ---" + docker compose exec -T app php artisan --version || true + docker compose logs --tail=50 app + exit 1 + fi + echo "Attempt ${i}/30: container not ready, waiting..." + sleep 2 + done + docker compose exec -T app test -d /var/www/html/public/build || { + echo "ERROR: /var/www/html/public/build not found in container, aborting asset copy" + exit 1 + } + rm -rf public/build && mkdir -p public/build + docker compose cp app:/var/www/html/public/build/. public/build/ + + deploy-production: + needs: build-and-push + if: inputs.tag != '' + runs-on: ubuntu-latest + concurrency: + group: deploy-production + cancel-in-progress: false + permissions: + contents: read + + steps: + - name: Deploy production + uses: appleboy/ssh-action@v1 + with: + host: firth.water.gkhs.net + username: alchemistic + key: ${{ secrets.FIRTH_SSH_KEY }} + script: | + set -euo pipefail + cd /home/docker/alchemistic + timeout 300 docker compose pull || { + echo "ERROR: docker compose pull failed or timed out after 300s" + exit 1 + } + docker compose up -d || { + echo "ERROR: docker compose up -d failed" + docker compose ps + docker compose logs --tail=50 + exit 1 + } + for i in $(seq 1 30); do + if docker compose exec -T app php artisan --version > /dev/null 2>&1; then + echo "Container ready after ${i} attempt(s)" + break + fi + if [ "$i" -eq 30 ]; then + echo "ERROR: Container failed to become ready after 30 attempts" + echo "--- Final health check output ---" + docker compose exec -T app php artisan --version || true + docker compose logs --tail=50 app + exit 1 + fi + echo "Attempt ${i}/30: container not ready, waiting..." + sleep 2 + done + docker compose exec -T app test -d /var/www/html/public/build || { + echo "ERROR: /var/www/html/public/build not found in container, aborting asset copy" + exit 1 + } + rm -rf public/build && mkdir -p public/build + docker compose cp app:/var/www/html/public/build/. public/build/ diff --git a/.github/workflows/create-release-tag.yml b/.github/workflows/create-release-tag.yml deleted file mode 100644 index aa30ae9..0000000 --- a/.github/workflows/create-release-tag.yml +++ /dev/null @@ -1,125 +0,0 @@ -name: Create Release Tag - -on: - workflow_dispatch: - inputs: - version_bump: - description: "Version bump type" - required: true - default: "patch" - type: choice - options: - - patch - - minor - - major - -jobs: - test: - uses: ./.github/workflows/tests.yml - secrets: inherit - - tag: - needs: test - runs-on: ubuntu-latest - permissions: - contents: write - - steps: - - name: Checkout repository - uses: actions/checkout@v4 - with: - fetch-depth: 0 - ref: main - - - name: Get latest tag - id: get_tag - run: | - # Get the latest semver tag, or use v0.0.0 if none exist - LATEST_TAG=$(git tag -l "v*.*.*" | sort -V | tail -n 1) - if [ -z "$LATEST_TAG" ]; then - LATEST_TAG="v0.0.0" - echo "No existing tags found, starting from $LATEST_TAG" - else - echo "Latest tag: $LATEST_TAG" - fi - echo "latest_tag=$LATEST_TAG" >> $GITHUB_OUTPUT - - - name: Calculate next version - id: next_version - run: | - LATEST_TAG="${{ steps.get_tag.outputs.latest_tag }}" - VERSION=${LATEST_TAG#v} - - IFS='.' read -r MAJOR MINOR PATCH <<< "$VERSION" - - case "${{ github.event.inputs.version_bump }}" in - major) - MAJOR=$((MAJOR + 1)) - MINOR=0 - PATCH=0 - ;; - minor) - MINOR=$((MINOR + 1)) - PATCH=0 - ;; - patch) - PATCH=$((PATCH + 1)) - ;; - esac - - NEXT_VERSION="v${MAJOR}.${MINOR}.${PATCH}" - echo "Next version: $NEXT_VERSION" - echo "next_version=$NEXT_VERSION" >> $GITHUB_OUTPUT - - - name: Create and push tag - run: | - git config user.name "github-actions[bot]" - git config user.email "github-actions[bot]@users.noreply.github.com" - - NEXT_VERSION="${{ steps.next_version.outputs.next_version }}" - - git tag -a "$NEXT_VERSION" -m "Release $NEXT_VERSION" - git push origin "$NEXT_VERSION" - - echo "✅ Created and pushed tag: $NEXT_VERSION" - - - name: Generate release notes - id: release_notes - run: | - LATEST_TAG="${{ steps.get_tag.outputs.latest_tag }}" - NEXT_VERSION="${{ steps.next_version.outputs.next_version }}" - - # Generate commit log since last tag - if [ "$LATEST_TAG" == "v0.0.0" ]; then - COMMITS=$(git log --pretty=format:"- %s (%h)" --no-merges) - else - COMMITS=$(git log ${LATEST_TAG}..HEAD --pretty=format:"- %s (%h)" --no-merges) - fi - - # Create release notes - cat > release_notes.md << EOF - ## What's Changed - - ${COMMITS} - - ## Docker Image - - \`\`\`bash - docker pull ghcr.io/${{ github.repository }}:${NEXT_VERSION#v} - docker pull ghcr.io/${{ github.repository }}:latest - \`\`\` - - **Full Changelog**: https://github.com/${{ github.repository }}/compare/${LATEST_TAG}...${NEXT_VERSION} - EOF - - echo "Release notes generated" - - - name: Create GitHub Release - uses: softprops/action-gh-release@v1 - with: - tag_name: ${{ steps.next_version.outputs.next_version }} - name: Release ${{ steps.next_version.outputs.next_version }} - body_path: release_notes.md - draft: false - prerelease: false - generate_release_notes: true diff --git a/.github/workflows/dependabot-make-release.yml b/.github/workflows/dependabot-make-release.yml new file mode 100644 index 0000000..2b5598c --- /dev/null +++ b/.github/workflows/dependabot-make-release.yml @@ -0,0 +1,108 @@ +name: "[Dependabot] Make Release" + +on: + schedule: + - cron: "0 3 * * 1" # Monday 3am UTC + workflow_dispatch: + inputs: + merge_dependabot: + description: "Merge dependabot-updates into main first" + required: false + default: true + type: boolean + version_bump: + description: "Version bump type" + required: true + default: "patch" + type: choice + options: + - patch + - minor + - major + +permissions: {} + +jobs: + check-for-updates: + runs-on: ubuntu-latest + permissions: + contents: read + outputs: + has_updates: ${{ steps.check.outputs.has_updates }} + version_bump: ${{ steps.params.outputs.version_bump }} + + steps: + - uses: actions/checkout@v4 + with: + fetch-depth: 0 + + - name: Resolve parameters + id: params + env: + EVENT_NAME: ${{ github.event_name }} + INPUT_VERSION_BUMP: ${{ inputs.version_bump }} + run: | + if [ "$EVENT_NAME" = "schedule" ]; then + echo "version_bump=patch" >> "$GITHUB_OUTPUT" + else + echo "version_bump=$INPUT_VERSION_BUMP" >> "$GITHUB_OUTPUT" + fi + + - name: Check if dependabot-updates is ahead of main + id: check + run: | + git fetch origin + if ! git ls-remote --exit-code origin dependabot-updates > /dev/null 2>&1; then + echo "dependabot-updates branch does not exist, skipping release" + echo "has_updates=false" >> "$GITHUB_OUTPUT" + exit 0 + fi + AHEAD=$(git rev-list --count origin/main..origin/dependabot-updates) + echo "dependabot-updates is $AHEAD commits ahead of main" + if [ "$AHEAD" -gt 0 ]; then + echo "has_updates=true" >> "$GITHUB_OUTPUT" + else + echo "No new commits in dependabot-updates, skipping release" + echo "has_updates=false" >> "$GITHUB_OUTPUT" + fi + + merge-dependabot: + needs: check-for-updates + if: | + needs.check-for-updates.outputs.has_updates == 'true' && + (github.event_name == 'schedule' || inputs.merge_dependabot == true) + runs-on: ubuntu-latest + permissions: + contents: write + pull-requests: write + checks: read + + steps: + - name: Merge dependabot-updates PR into main + env: + GH_TOKEN: ${{ github.token }} + GH_REPO: ${{ github.repository }} + run: | + PR_STATE=$(gh pr view dependabot-updates --json state --jq '.state' 2>/dev/null || echo "NOT_FOUND") + if [ "$PR_STATE" != "OPEN" ]; then + echo "No open PR for dependabot-updates (state: $PR_STATE), creating one..." + gh pr create --base main --head dependabot-updates \ + --title "chore: bump dependencies" \ + --body "Automated dependency updates" + fi + gh pr ready dependabot-updates + gh pr checks dependabot-updates --watch --fail-fast + gh pr merge dependabot-updates --merge + + create-release: + needs: [check-for-updates, merge-dependabot] + if: | + !failure() && !cancelled() && + (github.event_name == 'workflow_dispatch' || needs.check-for-updates.outputs.has_updates == 'true') + permissions: + contents: write + packages: write + uses: istic/Alchemistic/.github/workflows/release.yml@main + with: + version_bump: ${{ needs.check-for-updates.outputs.version_bump }} + secrets: inherit # pragma: allowlist secret diff --git a/.github/workflows/docker.yml b/.github/workflows/docker.yml deleted file mode 100644 index 076baf3..0000000 --- a/.github/workflows/docker.yml +++ /dev/null @@ -1,73 +0,0 @@ -name: Build and publish Docker image - -on: - push: - tags: - - "v*" - workflow_dispatch: - -env: - REGISTRY: ghcr.io - IMAGE_NAME: ${{ github.repository }} - -jobs: - build: - runs-on: ubuntu-latest - permissions: - contents: read - packages: write - - steps: - - name: Checkout - uses: actions/checkout@v4 - - - name: Setup PHP - uses: shivammathur/setup-php@v2 - with: - php-version: ${{ vars.PHP_VERSION }} - tools: composer:v2 - - - name: Install PHP dependencies - run: composer install --no-dev --no-interaction --prefer-dist --optimize-autoloader --no-scripts - - - name: Setup Node - uses: actions/setup-node@v4 - with: - node-version: ${{ vars.NODE_VERSION }} - - - name: Install Node dependencies - run: npm ci - - - name: Build assets - run: npm run build - - - name: Log in to GitHub Container Registry - uses: docker/login-action@v3 - with: - registry: ${{ env.REGISTRY }} - username: ${{ github.actor }} - password: ${{ secrets.GITHUB_TOKEN }} - - - name: Extract metadata - id: meta - uses: docker/metadata-action@v5 - with: - images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }} - tags: | - type=semver,pattern={{version}} - type=semver,pattern={{major}}.{{minor}} - type=sha - - - name: Set up Docker Buildx - uses: docker/setup-buildx-action@v3 - - - name: Build and push - uses: docker/build-push-action@v6 - with: - context: . - file: docker/production/Dockerfile - push: true - tags: ${{ steps.meta.outputs.tags }} - labels: ${{ steps.meta.outputs.labels }} - cache-from: type=gha - cache-to: type=gha,mode=max diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 0000000..4ecefe4 --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,136 @@ +name: Release + +on: + workflow_dispatch: + inputs: + version_bump: + description: 'Version bump type' + required: true + type: choice + options: + - patch + - minor + - major + workflow_call: + inputs: + version_bump: + type: string + description: 'Version bump type' + required: true + +jobs: + tag: + runs-on: ubuntu-latest + permissions: + contents: write + outputs: + next_version: ${{ steps.next_version.outputs.next_version }} + + steps: + - name: Checkout repository + uses: actions/checkout@v4 + with: + fetch-depth: 0 + ref: main + + - name: Get latest tag + id: get_tag + run: | + set -euo pipefail + LATEST_TAG=$(git tag -l "v*.*.*" | sort -V | tail -n 1) + if [ -z "$LATEST_TAG" ]; then + LATEST_TAG="v0.0.0" + echo "No existing tags found, starting from $LATEST_TAG" + else + echo "Latest tag: $LATEST_TAG" + fi + echo "latest_tag=$LATEST_TAG" >> "$GITHUB_OUTPUT" + + - name: Calculate next version + id: next_version + env: + LATEST_TAG: ${{ steps.get_tag.outputs.latest_tag }} + VERSION_BUMP: ${{ inputs.version_bump }} + run: | + set -euo pipefail + VERSION=${LATEST_TAG#v} + IFS='.' read -r MAJOR MINOR PATCH <<< "$VERSION" + case "$VERSION_BUMP" in + major) MAJOR=$((MAJOR + 1)); MINOR=0; PATCH=0 ;; + minor) MINOR=$((MINOR + 1)); PATCH=0 ;; + patch) PATCH=$((PATCH + 1)) ;; + *) echo "Invalid version_bump: $VERSION_BUMP"; exit 1 ;; + esac + NEXT_VERSION="v${MAJOR}.${MINOR}.${PATCH}" + echo "Next version: $NEXT_VERSION" + echo "next_version=$NEXT_VERSION" >> "$GITHUB_OUTPUT" + + - name: Create and push tag + env: + NEXT_VERSION: ${{ steps.next_version.outputs.next_version }} + run: | + set -euo pipefail + git config user.name "github-actions[bot]" + git config user.email "github-actions[bot]@users.noreply.github.com" + LS_REMOTE_OUTPUT=$(git ls-remote --tags origin "$NEXT_VERSION") + if echo "$LS_REMOTE_OUTPUT" | grep -qF "refs/tags/$NEXT_VERSION"; then + echo "ERROR: Tag $NEXT_VERSION already exists on remote." + echo "A previous run may have pushed the tag but failed before creating the GitHub Release." + echo "Recovery options:" + echo " 1. If the GitHub Release is missing: create it manually at https://github.com/${GITHUB_REPOSITORY}/releases/new?tag=${NEXT_VERSION}" + echo " 2. If you want to re-run: delete the remote tag with: git push origin :refs/tags/${NEXT_VERSION}" + exit 1 + fi + git tag -a "$NEXT_VERSION" -m "Release $NEXT_VERSION" + git push origin "$NEXT_VERSION" + echo "Created and pushed tag: $NEXT_VERSION" + + - name: Generate release notes + id: release_notes + env: + LATEST_TAG: ${{ steps.get_tag.outputs.latest_tag }} + NEXT_VERSION: ${{ steps.next_version.outputs.next_version }} + REPOSITORY: ${{ github.repository }} + run: | + set -euo pipefail + if [ "$LATEST_TAG" == "v0.0.0" ]; then + COMMITS=$(git log --pretty=format:"- %s (%h)" --no-merges) + else + if ! git rev-parse --verify "$LATEST_TAG" > /dev/null 2>&1; then + echo "ERROR: Tag $LATEST_TAG not found in local history" + exit 1 + fi + COMMITS=$(git log "${LATEST_TAG}..HEAD" --pretty=format:"- %s (%h)" --no-merges) + fi + [ -z "$COMMITS" ] && COMMITS="No notable changes." + TAG_SUFFIX="${NEXT_VERSION#v}" + { + printf '## What'\''s Changed\n\n' + printf '%s\n' "${COMMITS}" + printf '\n## Docker Image\n\n' + printf '```bash\n' + printf 'docker pull ghcr.io/%s:%s\n' "${REPOSITORY}" "${TAG_SUFFIX}" + printf 'docker pull ghcr.io/%s:latest\n' "${REPOSITORY}" + printf '```\n\n' + printf '**Full Changelog**: https://github.com/%s/compare/%s...%s\n' \ + "${REPOSITORY}" "${LATEST_TAG}" "${NEXT_VERSION}" + } > release_notes.md + + - name: Create GitHub Release + uses: softprops/action-gh-release@v3 + with: + tag_name: ${{ steps.next_version.outputs.next_version }} + name: Release ${{ steps.next_version.outputs.next_version }} + body_path: release_notes.md + draft: false + prerelease: false + + ci: + needs: tag + uses: ./.github/workflows/ci.yml + permissions: + contents: read + packages: write + with: + tag: ${{ needs.tag.outputs.next_version }} + secrets: inherit # pragma: allowlist secret diff --git a/docker/production/entrypoint.sh b/docker/production/entrypoint.sh index d3e982e..d8bce6d 100644 --- a/docker/production/entrypoint.sh +++ b/docker/production/entrypoint.sh @@ -1,8 +1,25 @@ #!/bin/sh set -e -php artisan config:cache -php artisan route:cache -php artisan view:cache +if [ -z "${APP_KEY}" ]; then + echo "[entrypoint] ERROR: APP_KEY is not set. Set it in your environment." >&2 + exit 1 +fi + +echo "[entrypoint] Creating storage directories..." +mkdir -p storage/framework/cache storage/framework/sessions storage/framework/views storage/logs storage/app/public + +php artisan config:cache || { + echo "[entrypoint] ERROR: php artisan config:cache failed" >&2 + exit 1 +} +php artisan route:cache || { + echo "[entrypoint] ERROR: php artisan route:cache failed" >&2 + exit 1 +} +php artisan view:cache || { + echo "[entrypoint] ERROR: php artisan view:cache failed" >&2 + exit 1 +} exec "$@" From f82094359f4037794747f1143aa374187a2ecea4 Mon Sep 17 00:00:00 2001 From: Nicholas Avenell Date: Thu, 4 Jun 2026 00:33:04 +0100 Subject: [PATCH 2/3] =?UTF-8?q?=E2=9A=99=EF=B8=8F=20Pass=20secrets=20to=20?= =?UTF-8?q?shared=20rebase=20workflow?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Claude Sonnet 4.6 --- .github/workflows/auto-rebase-dependabot.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/auto-rebase-dependabot.yml b/.github/workflows/auto-rebase-dependabot.yml index 32b5b7a..8fb4ecc 100644 --- a/.github/workflows/auto-rebase-dependabot.yml +++ b/.github/workflows/auto-rebase-dependabot.yml @@ -11,3 +11,4 @@ jobs: permissions: contents: write pull-requests: write + secrets: inherit From d00dfaed8b7a578fcba36d1427a845dd4fa4be1b Mon Sep 17 00:00:00 2001 From: Nicholas Avenell Date: Thu, 4 Jun 2026 07:48:41 +0100 Subject: [PATCH 3/3] =?UTF-8?q?=F0=9F=AA=B3=20Skip=20staging=20deploy=20fo?= =?UTF-8?q?r=20Dependabot=20PRs?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Claude Sonnet 4.6 --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 2e1a7d1..5c6bfcf 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -149,7 +149,7 @@ jobs: deploy-staging: needs: build-and-push - if: github.event_name == 'pull_request' + if: github.event_name == 'pull_request' && github.actor != 'dependabot[bot]' runs-on: ubuntu-latest concurrency: group: deploy-staging