ci: skip build and deploy when no code changes (#335)

## Why

Pushes to `main` that only modify workflows, README, or docs were
triggering production deploys.

## What

- Adds a `changes` job using `dorny/paths-filter@v3` to detect whether
the push touched application code.
- Gates `build-image` and `deploy` on `needs.changes.outputs.code ==
'true'`.

## Code paths considered

`app/`, `bootstrap/`, `config/`, `database/`, `public/`, `resources/`,
`routes/`, `tests/`, `storage/`, `artisan`, `composer.{json,lock}`,
`package*.json`, `bun.lock*`, `vite.config.*`, `tsconfig*.json`,
`eslint.config.*`, `.prettierrc*`, `phpstan.neon*`, `phpunit.xml*`,
`pint.json`, `Dockerfile`, `docker/**`, `.dockerignore`, `.env.example`.

Anything else (e.g. `.github/**`, `*.md`, `docs/**`) is treated as
non-deployable.
This commit is contained in:
Víctor Falcón 2026-04-26 09:15:06 +01:00 committed by GitHub
parent b2d73ef5c3
commit 405e6bfc29
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 44 additions and 5 deletions

View File

@ -223,10 +223,49 @@ jobs:
DB_USERNAME: root
DB_PASSWORD: password
changes:
runs-on: ubuntu-latest
outputs:
code: ${{ steps.filter.outputs.code }}
steps:
- uses: actions/checkout@v4
- uses: dorny/paths-filter@v3
id: filter
with:
filters: |
code:
- 'app/**'
- 'bootstrap/**'
- 'config/**'
- 'database/**'
- 'public/**'
- 'resources/**'
- 'routes/**'
- 'tests/**'
- 'storage/**'
- 'artisan'
- 'composer.json'
- 'composer.lock'
- 'package.json'
- 'package-lock.json'
- 'bun.lock'
- 'bun.lockb'
- 'vite.config.*'
- 'tsconfig*.json'
- 'eslint.config.*'
- '.prettierrc*'
- 'phpstan.neon*'
- 'phpunit.xml*'
- 'pint.json'
- 'Dockerfile'
- 'docker/**'
- '.dockerignore'
- '.env.example'
build-image:
runs-on: ubuntu-latest
needs: [tests, linter, static-analysis, performance-tests]
if: (github.ref == 'refs/heads/main' && github.event_name == 'push') || github.event_name == 'workflow_dispatch'
needs: [tests, linter, static-analysis, performance-tests, changes]
if: ((github.ref == 'refs/heads/main' && github.event_name == 'push') || github.event_name == 'workflow_dispatch') && needs.changes.outputs.code == 'true'
env:
SENTRY_RELEASE: whisper-money@${{ github.sha }}
permissions:
@ -291,8 +330,8 @@ jobs:
deploy:
runs-on: ubuntu-latest
needs: [build-image]
if: github.ref == 'refs/heads/main' && github.event_name == 'push'
needs: [build-image, changes]
if: github.ref == 'refs/heads/main' && github.event_name == 'push' && needs.changes.outputs.code == 'true'
env:
SENTRY_RELEASE: whisper-money@${{ github.sha }}
concurrency:

View File

@ -8,6 +8,6 @@ it('waits for the image build before marking a sentry deploy', function () {
$workflow = file_get_contents(base_path('.github/workflows/ci.yml'));
expect($workflow)
->toContain("deploy:\n runs-on: ubuntu-latest\n needs: [build-image]")
->toContain("deploy:\n runs-on: ubuntu-latest\n needs: [build-image, changes]")
->toContain('run: sentry-cli releases deploys "$SENTRY_RELEASE" new -e production');
});