Shared composite actions and reusable workflows for Genero's Bedrock/Sage WordPress projects.
This is a private repository. To allow other repos in the org to use these actions:
- Go to Settings → Actions → General on this repo
- Under "Access", select "Accessible from repositories in the 'generoi' organization"
| Action | Description |
|---|---|
setup | PHP + Node.js setup with caching, Fontawesome and Packagist auth |
install-wordpress | MySQL + WP dev server install (single or multisite) |
setup-ddev | DDEV setup (pinned SHA) |
ssh-agent | SSH agent wrapper (pinned SHA) |
- uses: generoi/github-actions/setup@v2with:
npm_fontawesome_auth_token: ${{ secrets.NPM_FONTAWESOME_AUTH_TOKEN }}composer_bot_private_key: ${{ secrets.COMPOSER_BOT_PRIVATE_KEY }}
- uses: generoi/github-actions/install-wordpress@v1with:
multisite: 'true'setup needs a credential that can read our private plugin repositories. Pass
exactly one:
composer_bot_private_key— preferred. The private key for thegenero-composer-botGitHub App; the action mints an installation token per run, valid for an hour and revoked when the job ends.packagist_github_token— the older path, a PAT on thegeneroi-deploymachine user. Still accepted so repositories can migrate one at a time.
Passing neither fails the run immediately rather than surfacing later as a 404 on a private package.
Both are handled by composer-auth, which setup calls after
installing PHP. Use it directly only if you drive setup-php yourself and so
cannot go through setup — vulnerability-scan.yml is the one case in this
repo. It must run after Composer exists, since it configures through
composer config.
- uses: generoi/github-actions/composer-auth@v2with:
composer_bot_private_key: ${{ secrets.COMPOSER_BOT_PRIVATE_KEY }}| Workflow | Description |
|---|---|
test.yml | Lint + install WP + smoke test + phpunit |
deploy.yml | SSH + build + test + deployer |
e2e.yml | Playwright E2E tests against a URL |
vulnerability-scan.yml | WP vuln scan + Google Chat notification |
plugin-changelog.yml | Comment wp.org changelogs for changed wp-plugin/* |
jobs:
test:
uses: generoi/github-actions/.github/workflows/test.yml@v1secrets: inheritwith:
multisite: truesmoke_grep: 'app/themes/gds/public/scripts/app.js'Dependabot renders release notes for every github-sourced package and nothing at
all for wp-plugin/*: WP Packages publishes the wp.org SVN tag as the package
source, and Dependabot only resolves git sources — then falls back to a metadata
lookup hardcoded to repo.packagist.org, where those packages do not exist. No
dependabot.yml setting changes either half.
plugin-changelog.yml fills the gap from api.wordpress.org instead. It runs
only on Dependabot's PRs — a human opening a composer update PR picked the
versions and already knows what moved. The caller owns the trigger and the
token, because a reusable workflow can only narrow the caller's permissions,
never widen them:
on:
pull_request:
paths:
- composer.lockpermissions:
contents: readpull-requests: writejobs:
changelog:
if: github.event.pull_request.user.login == 'dependabot[bot]'uses: generoi/github-actions/.github/workflows/plugin-changelog.yml@v2Keep that if even though the shared workflow guards on the author too: the
job-level one skips the reusable-workflow call outright, while the shared one
only runs after the call has been made.
Dependabot's pull_request events get a read-only token by default, but an
explicit permissions: block still elevates it — so this needs no
pull_request_target, and should not use one. Drop contents: read and the
comment still posts, from a diff-hunk fallback that quietly misses plugins.
vulnerability-scan.yml does not sleep to spread load — runner time is billed,
so the stagger belongs in the cron expression, which is free. Give each repo
its own minute (and ideally its own hour) rather than copying 5 4 * * *:
on:
schedule:
- cron: '17 3 * * *'# unique per repoSharing one minute across repos means every scan hits the advisory and GitHub APIs simultaneously, and GitHub also delays runs scheduled on popular minutes.
The scheduled scan is gated on the repo's maintenance organization custom
property. It runs only for monthly, bi-monthly, quarterly and
critical-only; hosted-only, none and an unset property skip the run.
That means adding the workflow to a repo is not enough — the repo also needs a
maintenance value, or its nightly scan silently no-ops:
gh api repos/generoi/<repo>/properties/values \
--jq '.[] | select(.property_name == "maintenance") | .value'Two deliberate escape hatches:
- A manual
workflow_dispatchalways scans, whatever the tier. - If the property API call fails, the scan runs anyway. An untagged repo is a visible state someone can fix; a transient 5xx is not, and it must never silently skip a security scan.
Projects pin to the major tag (@v1). Patch updates are automatic.
Dependabot monitors upstream action SHAs — merge its PRs to update all projects at once.