Skip to content
PREFLIGHT 0.1.1

Wayne State app stack · CI templates

PREFLIGHT

Every push is cleared for takeoff.

pre·flight noun The checklist a pilot runs before takeoff. Every push runs this one before Citadel.

GitLab CI/CD components that every stack project and starter includes: PROCTOR, PHP tests on each supported version, a Composer audit, an SBOM, Pint, PHPStan and ESLint. One include: block, the same checks on every app.

.gitlab-ci.yml

include:
  - component: $CI_SERVER_FQDN/enterprise-apps/preflight/php-test@0.1.1

Run the checklist File a flight plan

PREFLIGHT mark: a runway in perspective with a gold centreline

Normal procedures

Before takeoff

Every push runs the same list, in the app's own pipeline, before anything reaches Citadel. Scroll, and it runs itself.

WSU app stack · normal checklist

Before takeoff · every push

  1. PROCTORChecked

    Checks the app against the stack's standards and publishes the result as a GitLab Code Quality report.

    vendor/bin/proctor check --format=codequality
  2. PHP tests8.3 · 8.4 · 8.5 pass

    One job per supported PHP version, through parallel:matrix. End-of-life PHP is not on the list.

    vendor/bin/phpunit
  3. Composer auditNo advisories

    Audits the lock file, not a fresh resolve, and fails the pipeline on a known advisory.

    composer audit --locked
  4. SBOMValidated

    A CycloneDX bill of materials, validated and kept as a job artifact. The app's composer.json is never touched.

    composer CycloneDX:make-sbom --output-format=JSON --validate
  5. PintClean

    The app's own Laravel Pint, in test mode, with the app's own pint.json.

    vendor/bin/pint --test --config=pint.json
  6. PHPStanNo errors

    The app's own PHPStan, writing its findings as a Code Quality report.

    vendor/bin/phpstan analyse --error-format=gitlab
  7. ESLint · PrettierClean

    The app's own ESLint and prettier --check, installed from the lock with scripts off.

    npx --no-install eslint .
  8. ClearanceCleared for takeoff

    Every gate green. The release is free to leave for Citadel.

Checklist complete. Tray tables up, tests green.

  • PROCTOR
  • PHP 8.3
  • PHP 8.4
  • PHP 8.5
  • AUDIT
  • SBOM
  • PINT
  • PHPSTAN
  • ESLINT
  • A11Ycoming soon
  • CONTRACTcoming soon
  • FRESHNESScoming soon
  • CLEARED FOR TAKEOFF
Makes the Composer audit fail, to show the pipeline holding short.

Cockpit placards

Seven components, one include each

Each one is an ordinary GitLab job with typed inputs and a sensible default. Every one is in the 0.1.1 tag, so pin it there.

in 0.1.1

proctor

Watches the cabin.

Runs PROCTOR's checks and publishes them as a Code Quality report.

- component: $CI_SERVER_FQDN/enterprise-apps/preflight/proctor@0.1.1
6 inputs
stage
test
image
php:8.4-cli@sha256:…
composer_version
2.10.3
allow_failure
false
proctor_command
vendor/bin/proctor check --format=codequality
working_dir
.

in 0.1.1

php-test

Three engines, all running.

The test command on each supported PHP version, one job per version.

- component: $CI_SERVER_FQDN/enterprise-apps/preflight/php-test@0.1.1
5 inputs
stage
test
php_versions
["8.3", "8.4", "8.5"]
composer_version
2.10.3
test_command
vendor/bin/phpunit
working_dir
.

in 0.1.1

composer-audit

Checks the passenger list.

composer audit --locked, failing on any advisory.

- component: $CI_SERVER_FQDN/enterprise-apps/preflight/composer-audit@0.1.1
3 inputs
stage
test
image
composer:2@sha256:…
working_dir
.

in 0.1.1

sbom

The cargo manifest.

A validated CycloneDX SBOM, published as an artifact. The plugin installs globally, so the app's files stay as they are.

- component: $CI_SERVER_FQDN/enterprise-apps/preflight/sbom@0.1.1
4 inputs
stage
test
image
composer:2.10.3@sha256:…
omit_dev
true
output
sbom.cdx.json

in 0.1.1

pint

Uniform pressed.

The app's own Laravel Pint in test mode. The app requires laravel/pint and ships a pint.json.

- component: $CI_SERVER_FQDN/enterprise-apps/preflight/pint@0.1.1
4 inputs
stage
test
image
composer:2.10.3@sha256:…
config
pint.json
working_dir
.

in 0.1.1

phpstan

Instruments cross-checked.

The app's own PHPStan, with a Code Quality report. The app requires phpstan/phpstan and ships a phpstan.neon.

- component: $CI_SERVER_FQDN/enterprise-apps/preflight/phpstan@0.1.1
5 inputs
stage
test
image
composer:2.10.3@sha256:…
config
phpstan.neon
memory_limit
1G
working_dir
.

in 0.1.1

eslint

The front cabin, too.

The app's own ESLint and Prettier. The app requires @waynestate/pinstripe, eslint and prettier.

- component: $CI_SERVER_FQDN/enterprise-apps/preflight/eslint@0.1.1
5 inputs
stage
test
image
node:22.13-alpine@sha256:…
working_dir
.
eslint_args
.
prettier
true

in 0.1.1

php-package.yml

Two cockpits, one checklist.

Components stay inside one GitLab instance, so GitHub mirrors call this reusable workflow instead: composer ci on each PHP version, then a Composer audit.

uses: waynestate/preflight/.github/workflows/php-package.yml@0.1.1
3 inputs
php-versions
'["8.3","8.4","8.5"]'
ci-command
composer ci
working-directory
.

Deferred items

On the list, not yet on board. Nothing to include until they land.

  • Coming soonAccessibility suiteAimed at WCAG 2.2 Level AA, the floor WayneUI's own gate uses, with a manual review step kept.
  • Coming soonContract suiteNamed in the best practices as coming later. Not built yet.
  • Coming soonSite freshnessPlanned. Not in this repo yet.

Quick start

File a flight plan

Four boxes. Fill them in once, and every merge request and every push to the default branch runs the checklist.

1 Route · .gitlab-ci.yml

Include the components

The workflow:rules block has to live in the app's own file: a component cannot set when the pipeline runs.

workflow:
  rules:
    - if: $CI_PIPELINE_SOURCE == "merge_request_event"
    - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH

include:
  - component: $CI_SERVER_FQDN/enterprise-apps/preflight/proctor@0.1.1
  - component: $CI_SERVER_FQDN/enterprise-apps/preflight/php-test@0.1.1
  - component: $CI_SERVER_FQDN/enterprise-apps/preflight/composer-audit@0.1.1
  - component: $CI_SERVER_FQDN/enterprise-apps/preflight/sbom@0.1.1
  - component: $CI_SERVER_FQDN/enterprise-apps/preflight/pint@0.1.1
  - component: $CI_SERVER_FQDN/enterprise-apps/preflight/phpstan@0.1.1
  - component: $CI_SERVER_FQDN/enterprise-apps/preflight/eslint@0.1.1

2 Switches · project settings

Three settings that make gates harder to skip

All three work on GitLab Community Edition. Flip each one as you set it.

0 of 3 set

3 Alternate · GitHub mirror

Mirrored to GitHub? Same checks there

A package mirrored to github.com/waynestate keeps its checks in a ci script in composer.json and calls the reusable workflow from .github/workflows/ci.yml. A release tag is not done until it is green on both sides.

name: CI

on:
  push:
    branches: ['**']
    tags: ['v*', '*.*.*']

jobs:
  ci:
    uses: waynestate/preflight/.github/workflows/php-package.yml@0.1.1

4 Ground check · your machine

Run PREFLIGHT's own checks locally

From a clone of this repo: the template lint, its fixture tests, Pint and PHPStan through composer ci, then the inputs contract.

PowerShell 7. composer ci needs PHP 8.3+ and Composer; the contract check runs yq in Docker.

PS> composer install
PS> composer ci
PS> pwsh -File tests/check-contract.ps1

No PHP on the machine? Docker does it:

PS> docker run --rm -v "${PWD}:/app" -w /app composer:2 composer install
PS> docker run --rm -v "${PWD}:/app" -w /app composer:2 composer ci

From the flight manual

Read before flight

What a shared template can do, what it cannot, and how PREFLIGHT keeps its own house in order.

Warning

A component is not a lock. An app's own .gitlab-ci.yml is merged over the included jobs, so it can override a job's keys, skip it with rules, or delete the include: line. PREFLIGHT makes the safe pipeline the easy one; ROLLCALL is where skipped or weakened gates show up.

A preflight checklist only works if the pilot reads it.

Caution

Same instance only. Components work only inside the GitLab instance that hosts PREFLIGHT; across instances, only by mirroring. Until git.wayne.edu has one, CI runs on the instance that has a runner. A git.wayne.edu instance runner is strongly recommended.

Note

Every image is pinned by digest (name:tag@sha256:…), so a repointed tag cannot quietly change what a pipeline runs. The php-test matrix is the one exception, tag-pinned on purpose so each job gets the newest PHP patch. Pins change only through a reviewed merge request.

$ docker buildx imagetools inspect <image>:<tag>

Preflight's own preflight

The checklist checks the checklist

composer ci lints every template and workflow for unsafe CI patterns before the fixture tests run.

  • privileged privileged: true
  • dind-service Docker-in-Docker services
  • docker-sock references to docker.sock
  • kaniko-image Kaniko images
  • unpinned-action GitHub uses: not pinned to a 40-character SHA
  • image-no-tag an image with no tag
  • image-latest an image on latest
  • image-no-digest a warning: tagged, but not pinned by digest

A known warning goes in lint-allow.yml with a required reason, so an allowlist entry is a reviewed decision, not a silence. And on every pipeline, contract/inputs.json holds each input's name, type and default, and each job's name, steady inside a major version.

Wayne State app stack

Departures

PREFLIGHT is one stop on the way to Citadel. Here is everyone else on the board.

  • WayneUI The interface. Its a11y floor is the one PREFLIGHT's accessibility suite will aim at.
  • CREED The written standards, and the policy every other part reads.
  • Pinstripe The coding standard behind the Pint, PHPStan and ESLint jobs.
  • PROCTOR One command that checks an app. First item on the checklist.
  • PREFLIGHT Shared CI on every push. You are here.
  • SQUIRE Carries the cleared release to Citadel.
  • ROLLCALL Every app answers "present". Skipped gates show up here.
  • BOOSTER Keeps an app's PHP current, so it stays on the test matrix.
  • HELMET Security headers and runtime hardening.
  • SESAME Sign-in for the app.
  • DRAWBRIDGE The Citadel sign-in gateway, lowered on request.
  • ADVISOR Ask what applies to your app, and what to do next.
  • Sourdough Starters you feed, with PREFLIGHT already in the pipeline.
  • WELD One app with every part already joined.