Reusable GitHub Actions workflows and org-level configuration for all VTS Studio repositories.
Defaults follow the VTS stack β the PHP version vts-product-template targets, the current Node LTS, the MySQL version Sail runs. A repository follows a default change unless it sets the input: pin php-version to the PHP of your Sail image (projects created from the template already do).
Usage β add this to your repo's .github/workflows/ci.yml:
jobs:
laravel:
uses: vts-studio/.github/.github/workflows/laravel.yml@main
with:
php-version: "8.5"
working-directory: "backend"
test-runner: "vendor/bin/pest"Jobs: Pint (code style), Tests (PHPUnit/Pest with MySQL + Redis), PHPStan (static analysis, opt-in)
| Input | Default | Description |
|---|---|---|
php-version |
8.5 |
PHP version β pin it to your Sail image |
mysql-version |
8.4 |
MySQL image tag of the test database |
node-version |
24 |
Node.js version (frontend assets, if needed) |
working-directory |
backend |
Path to Laravel project |
test-runner |
vendor/bin/pest |
Test command (vendor/bin/pest or vendor/bin/phpunit) |
run-pint |
true |
Run Laravel Pint check |
run-tests |
true |
Run test suite |
run-phpstan |
false |
Run PHPStan static analysis |
phpstan-level |
5 |
PHPStan analysis level (0-9) |
Usage:
jobs:
react:
uses: vts-studio/.github/.github/workflows/react.yml@main
with:
node-version: "24"
working-directory: "frontend"Jobs: ESLint, TypeScript check, Vitest, Production build
| Input | Default | Description |
|---|---|---|
node-version |
24 |
Node.js version |
working-directory |
frontend |
Path to React project |
run-lint |
true |
Run ESLint |
run-typecheck |
true |
Run TypeScript check |
run-tests |
true |
Run Vitest |
run-build |
true |
Run production build |
package-manager |
npm |
Package manager (npm or yarn) |
Usage:
jobs:
mobile:
uses: vts-studio/.github/.github/workflows/react-native.yml@main
with:
node-version: "24"
working-directory: "mobile"Jobs: ESLint, TypeScript check, Jest tests
| Input | Default | Description |
|---|---|---|
node-version |
24 |
Node.js version |
working-directory |
mobile |
Path to React Native project |
run-lint |
true |
Run ESLint |
run-typecheck |
true |
Run TypeScript check |
run-tests |
true |
Run Jest tests |
package-manager |
npm |
Package manager (npm or yarn) |
name: CI
on:
pull_request:
branches: [main]
push:
branches: [main]
jobs:
laravel:
uses: vts-studio/.github/.github/workflows/laravel.yml@main
with:
php-version: "8.5"
test-runner: "vendor/bin/pest"
react:
uses: vts-studio/.github/.github/workflows/react.yml@main
mobile:
uses: vts-studio/.github/.github/workflows/react-native.yml@mainBuilds a static front β single-page app (Vite) or generated site (Nuxt generate) β and ships it to a private S3 bucket served by CloudFront. Files under the hashed-assets directory are cached for a year; every other file is revalidated on each visit, then CloudFront is invalidated.
Usage β .github/workflows/deploy-frontend.yml in the project:
name: Deploy frontend
on:
push:
branches: [deploy-staging, deploy-production]
workflow_dispatch:
concurrency:
group: deploy-frontend-${{ github.ref_name }}
cancel-in-progress: false
jobs:
frontend:
uses: vts-studio/.github/.github/workflows/deploy-static-site.yml@main
permissions:
contents: read
id-token: write
secrets: inherit # only while the project still uses AWS access keys
with:
environment: ${{ github.ref_name == 'deploy-production' && 'production' || 'staging' }}| Input | Default | Description |
|---|---|---|
environment |
β (required) | GitHub environment holding the deployment variables |
working-directory |
frontend |
Path to the front project (. at the repository root) |
node-version |
24 |
Node.js version |
package-manager |
npm |
npm or yarn (dependency cache) |
install-command |
npm ci |
Dependency installation |
build-command |
npm run build |
Build (yarn generate for Nuxt) |
output-directory |
dist |
Build output, relative to working-directory |
env-prefix |
VITE_ |
Environment variables with this prefix are passed to the build (empty = none) |
build-variables |
β | Space-separated names of other environment variables passed to the build |
hashed-assets-path |
assets |
Directory of content-hashed files (_nuxt for Nuxt) |
well-known-content-type |
β | Content-Type forced on .well-known/ files, e.g. application/json for iOS/Android app links |
Variables of each GitHub environment (Settings β Environments): S3_BUCKET, CLOUDFRONT_DISTRIBUTION_ID, optionally AWS_REGION (default eu-west-3) and FRONTEND_URL, plus the build variables.
AWS access:
- Recommended β GitHub OIDC: set
AWS_DEPLOY_ROLE_ARNon the environment. The IAM role trustsrepo:vts-studio/<repo>:environment:<environment>in itstoken.actions.githubusercontent.com:subcondition, and only needss3:ListBucket,s3:GetObject,s3:PutObject,s3:DeleteObjecton the bucket andcloudfront:CreateInvalidationon the distribution. No AWS key is stored in GitHub. - Transition β access keys: without
AWS_DEPLOY_ROLE_ARN, theAWS_ACCESS_KEY_ID/AWS_SECRET_ACCESS_KEYsecrets are used (passsecrets: inherit). Moving to OIDC later = set the variable, then delete the secrets and the IAM user's keys.
If your project uses private Composer packages (e.g. Laravel Nova), add a COMPOSER_AUTH secret to your repo with your credentials.