Deployment
Deployment puts the code that passed CI on your hosting platform. This page is for the lead or DevOps engineer who sets up deployments for a project built from Vortex. It covers choosing the deployment types, what triggers a deployment and how to skip or gate a deployment.
The vortex-deploy router script runs every deployment by handing off to
1 script per deployment type. It ships in the
drevops/vortex-tooling
Composer package and installs at vendor/bin/vortex-deploy.
The CI pipeline's deploy job runs the router after the build and lint
jobs pass.
On GitHub Actions, a manual
deployment
runs the deploy job on its own and skips the checks. It works for every
type except artifact, which needs the codebase that the build job
exports. With artifact in the list, the manual deployment fails before the
other types run. Outside CI, ahoy deploy runs the same script from your
machine after you confirm.
The deployment scripts read their settings from environment variables. Each
script loads .env from the project root, then .env.local when it exists.
A variable already set in the CI job's environment wins over both files.
The tables on the deployment type pages give each variable's Location:
.envmeans a value committed with the project.CImeans a value set in your CI provider: a project environment variable on CircleCI, or a repository variable or secret on GitHub Actions. A GitHub Actions variable reaches the script only when the workflow'sDeploystep passes it.
$VORTEX_DEPLOY_TYPES in .env lists the deployment types to run,
separated by commas, for example VORTEX_DEPLOY_TYPES=artifact,webhook. The
router supports 3 types:
webhook- calls a webhook URL withcurl.artifact- packages the built codebase as an artifact and pushes it to a remote Git repository.lagoon- asks the Lagoon platform, through the Lagoon CLI, to deploy the branch or pull request.
The types always run in the same order, artifact, then webhook, then
lagoon, whatever the order you list them in. The router matches the names
as substrings and doesn't validate them, so a misspelled type deploys
nothing and the job still passes. An empty list stops the job with the
message Missing required value for VORTEX_DEPLOY_TYPES.
The installer's default follows your hosting choice:
artifactfor Acquialagoonfor Lagoonwebhookfor any other hosting
After the code lands on Acquia or Lagoon, the hosting platform runs the
provisioning and notification scripts. That part runs on the hosting side,
outside the deploy job, so Hosting and
Notifications cover it.
Expand to see deployment in the complete code lifecycle
Local Development
═════════════════════════════════════════════════════════════════════════════════════════
Developer writes code ──► Build and test locally ──► Commit changes
│
▼
Git Repository
═════════════════════════════════════════════════════════════════════════════════════════
Push to remote branch ──► Open/Update Pull Request
│
▼
┌─ CI Pipeline ─────────────────────────────────── ─────────────────────────────────────────┐
│ │
│ ┌─ Database Job (Nightly) ───────────────────────────────────────────────────────────┐ │
│ │ │ │
│ │ Scheduled ──► Download production ──► Import and export ──► Store database cache │ │
│ │ trigger database to validate the dump │ │
│ │ │ │
│ └─────────────────────────────────────┬──────────────────────────────────────────────┘ │
│ │ Provides cached database │
│ ▼ │
│ ┌─ Lint Job ────────────┐ ┌─ Database Job ────────────────┐ ┌─ Audit Job ──────────┐ │
│ │ │ │ ◆ Nightly cache exists? │ │ Composer audit │ │
│ │ Composer validate │ │ Yes ──► job succeeds │ │ (advisories) │ │
│ │ ▼ │ │ No ──► download, validate, │ │ ▼ │ │
│ │ Hadolint │ │ store cache │ │ npm audit │ │
│ │ ▼ │ └───────────────┬───────────────┘ │ (advisories) │ │
│ │ DCLint │ ▼ │ ▼ │ │
│ │ ▼ │ ┌─ Build Job ───────────────────┐ │ Gitleaks │ │
│ │ Build CLI container │ │ Code assembly │ │ (committed secrets) │ │
│ │ ▼ │ │ Docker, Composer deps, │ │ │ │
│ │ Composer normalize │ │ NPM deps, assets │ │ │ │
│ │ ▼ │ │ ▼ │ │ │ │
│ │ PHPCS │ │ Website setup │ │ │ │
│ │ ▼ │ │ Import cached DB, drush │ │ │ │
│ │ PHPStan │ │ deploy, custom scripts │ │ │ │
│ │ ▼ │ │ ▼ │ │ │ │
│ │ Rector │ │ Testing │ │ │ │
│ │ ▼ │ │ Jest ──► PHPUnit ──► Behat │ │ │ │
│ │ Twig CS Fixer │ └───────────────┬──────────── ───┘ │ │ │
│ │ ▼ │ │ │ │ │
│ │ Gherkin Lint │ │ │ │ │
│ │ ▼ │ │ │ │ │
│ │ ESLint / Stylelint │ │ │ │ │
│ │ │ │ │ │ │
│ └──────────┬────────────┘ │ │ │ │
│ │ │ │ │ │
│ ▼ ▼ │ │ │
│ ┌─ Deployment Job ─────────────────────────────────────────┐ │ │ │
│ │ │ │ │ │
│ │ Webhook Artifact Lagoon │ │ Does not gate │ │
│ │ Call URL Package artifact Run Lagoon CLI deploy │ │ deployment │ │
│ │ │ │ │ │
│ └──────────────────────────────────────────────────────────┘ └──────────────────────┘ │
│ │
└──────────────────────────────────────────────────────────────────────────────────────────┘
│
▼
Hosting Platform
═════════════════════════════════════════════════════════════════════════════════════════
◆ Environment ──No──► Sync DB from production ───┐
exists? │
│ Yes ▼
└──────────────────────────────────► drush deploy ──► Custom scripts ──► Notifications
Available Environments
═════════════════════════════════════════════════════════════════════════════════════════
┊ PR Environment ┊ Dev Staging Production
┊ (auto-removed) ┊ develop branch main branch production branch or tag
Deployment targets
Vortex deploys branches, pull requests and tags. The CI configuration files decide which of them deploy. The hosting platform decides how each one maps to an environment.
On GitHub Actions, a push to any of these branches triggers a deployment by default:
productionmainmasterdeveloprelease/**hotfix/**project/**
The router then deploys the branch with each type in
$VORTEX_DEPLOY_TYPES.
On GitHub Actions, a pull request deploys its branch when it's opened,
updated or reopened against a branch in the preceding list, a feature/*
branch or a bugfix/* branch. Depending on the hosting platform, a pull
request deployment can create a temporary environment named after it, such
as pr-123 on Lagoon.
On GitHub Actions, short-lived feature/* and bugfix/* branches deploy
through their pull requests rather than direct pushes, because deploying
both would double every CI run and every deployment. Branches that
automated dependency updates create (deps/*) never deploy, on either CI
provider.
CircleCI matches branch names against regular expressions. Its patterns
also match pushes to feature/*, bugfix/* and ci* branches and to major
version branches such as 2.x. The patterns match release/* and
hotfix/* branches only when the name after the slash is a version or a
date. CircleCI builds each push: when a deployed branch has an open pull
request, the build deploys it as that pull request, such as pr-123.
A project/* branch is a long-lived branch for a larger feature or project
that spans several pull requests. A migration branch is a typical case: its
code and configuration aren't ready to merge into develop, but it needs a
remote environment for testing. You sync such a branch with develop by
hand.
On GitHub Actions, a project/* branch deploys on direct pushes, and its
pull requests don't deploy, so each change deploys once. CircleCI skips the
deployment of a project/* branch whenever the branch has an open pull
request.
Tags deploy too. GitHub Actions deploys any pushed tag. CircleCI deploys
tags that look like a semantic version (1.2.3, 1.2.3-rc.1) or a date
(2023-04-17, 2023-04-17.1). A tag runs in tag mode
(VORTEX_DEPLOY_MODE=tag), and each deployment type handles it in its own
way:
artifactpushes to adeployment/[tags:-]branch, named after the tags on the deployed commit.webhookcalls its URL, as it does for a branch.lagoonskips the deployment, because Lagoon doesn't support tag deployments.
The provider pages list the exact patterns and show how to change them. See GitHub Actions > Update trigger branches and CircleCI > Update deployment branches.
Deployment action
By default, a deployment keeps the environment's existing database.
$VORTEX_DEPLOY_ACTION sets what a deployment does:
deploy- deploys the code and keeps the environment's database. An empty value, the default, does the same.deploy_override_db- deploys the code and replaces the environment's database during provisioning with a copy from the configured database source, which is production by default on Lagoon. On a Lagoon production environment,.lagoon.ymlsetsVORTEX_PROVISION_OVERRIDE_DB=0, so production keeps its database. A site that provisions from a profile reads that value from.envinstead.destroy- removes the deployed environment, on platforms that support it (Lagoon).
Only the Lagoon deployment reads the action. VORTEX_DEPLOY_LAGOON_ACTION
overrides it for Lagoon alone. On GitHub Actions, checking override_db on
a manual deployment sets the action to deploy_override_db.
Skip deployments
To skip every deployment, set VORTEX_DEPLOY_SKIP to 1. CI still builds
and tests the code, and the deploy job stops before it deploys anything.
Its log shows Found flag to skip all deployments.
On GitHub Actions, the workflow reads the skip and gate variables from repository variables of the same name:
VORTEX_DEPLOY_SKIPVORTEX_DEPLOY_ALLOW_SKIPVORTEX_DEPLOY_SKIP_PRSVORTEX_DEPLOY_SKIP_BRANCHESVORTEX_DEPLOY_ALLOW_LABEL
On CircleCI, set them in the project's environment variables or in .env.
Skip deployments for specific pull requests or branches
To skip specific pull requests or branches:
- Set
$VORTEX_DEPLOY_ALLOW_SKIPto1. - List the pull requests in
$VORTEX_DEPLOY_SKIP_PRS, the branches in$VORTEX_DEPLOY_SKIP_BRANCHESor both, as the following sections show.
Each list takes a single value or a comma-separated list without spaces. Entries match exactly, with no wildcards.
Confirm that the next build of a listed pull request or branch skips its
deployment. The deploy job log shows Found PR 42 in skip list. or
Found branch feature/test in skip list., followed by Skipped deployment
and your deployment types.
Skip specific pull requests
Set $VORTEX_DEPLOY_SKIP_PRS to the pull request numbers. Use the bare
number, without a pr- prefix:
# Skip a single PR
VORTEX_DEPLOY_ALLOW_SKIP=1
VORTEX_DEPLOY_SKIP_PRS=42
# Skip multiple PRs
VORTEX_DEPLOY_ALLOW_SKIP=1
VORTEX_DEPLOY_SKIP_PRS=42,123,456
Skip specific branches
Set $VORTEX_DEPLOY_SKIP_BRANCHES to the branch names. A pull request
build is skipped by its branch name too, because CI passes the branch name
with the pull request number:
# Skip a single branch
VORTEX_DEPLOY_ALLOW_SKIP=1
VORTEX_DEPLOY_SKIP_BRANCHES=feature/test
# Skip multiple branches
VORTEX_DEPLOY_ALLOW_SKIP=1
VORTEX_DEPLOY_SKIP_BRANCHES=feature/test,hotfix/urgent,project/experimental
Combined usage
A match in either list skips the deployment:
VORTEX_DEPLOY_ALLOW_SKIP=1
VORTEX_DEPLOY_SKIP_PRS=42,123
VORTEX_DEPLOY_SKIP_BRANCHES=feature/test,hotfix/urgent
Gate deployments on a PR label
The label gate makes pull request deployments opt-in: a pull request gets an environment only after someone labels it. The skip lists work the other way: everything deploys except what they list. Use the gate to limit the number and cost of per-PR environments, or to keep work-in-progress pull requests out of environments.
To turn the gate on, set $VORTEX_DEPLOY_ALLOW_LABEL to the name of the
label that authorizes deployment:
VORTEX_DEPLOY_ALLOW_LABEL=deploy
With this setting, a pull request deploys only when it carries the deploy
label. The name matches exactly, including case. When the variable is empty
or unset, the default, the gate is off.
The gate applies only to pull request builds. Branch and tag deployments have no pull request label, so the gate never blocks them.
The router reads the pull request's labels from $VORTEX_DEPLOY_PR_LABELS,
a comma-separated list that CI fills in from the pull request event:
- GitHub Actions fills it in for you. The workflow has no
labeledtrigger, so a label added to an open pull request takes effect on the next push. A manual deployment of a pull request carries no labels, so the gate skips it. - CircleCI doesn't provide labels, so to use the gate there, fill in
$VORTEX_DEPLOY_PR_LABELSyourself, for example from the GitHub API.
Confirm that the gate works: the deploy job of a pull request without the
label logs PR 123 does not carry the "deploy" label. and deploys nothing.
The label gate and the skip lists combine. The router checks the skip lists
first, and a match always wins. A pull request listed in
$VORTEX_DEPLOY_SKIP_PRS is skipped even when it carries the gate label.
See also
The following pages cover each deployment type and the notifications sent after a deployment:
| Topic | Description |
|---|---|
| Webhook | Deploy by calling a webhook URL |
| Artifact | Deploy code artifacts to remote repositories |
| Lagoon | Deploy to the Lagoon hosting platform |
| Notifications | Send deployment notifications |