First, we should be aware of the branches and environments, as these form the basis of what we deploy from, and what we deploy to.
Also, this project employs a continuous integration and continuous delivery system (CI/CD).
Details about the environments:
- Development - developer workstations.
- Staging - an experimental environment. It is deployed manually as engineers choose.
- Demo - an acceptance testing and demonstration environment. It remains up to date with
main
thanks to continuous deployment. Unlike Staging, it is rarely used for experimentation. - Production - the public, visible environment. The Production environment
is the deploy target of the
release
branch.
Links to the environments:
- Dev: GYR, CTC
- Demo: GYR, CTC, Spanish-by-default
- Staging: GYR, CTC, Spanish-by-default
- Production: GYR, CTC, Spanish-by-default
main
- this is the central trunk ofvita-min
development. This branch contains the most up-to-date code, merged in from various work branches. Themain
branch is deployed to the Demo and Staging environments automatically.release
- this branch represents the code currently in the Production environment. It tends to lag behindmain
by a few commits. Therelease
branch is deployed to the Production environment automatically.- work branches - most development occurs in a work branch. These branches form
the sources for Pull Requests on GitHub, and a place to work without
disrupting the
main
branch.
To deploy to Demo, commit/merge to main
and push to Github. This will trigger a CI/CD build and deploy to the Demo environment. Deploying to staging is done manually by merging changes to the staging
branch.
Deploying to staging is the only way to test XML changes since the schemas aren't on Heroku. Our current process is to either open a PR off the staging branch and merge it or push directly to staging, so that Product can perform acceptance tests on this environment.
git checkout staging
git pull
git checkout -b {my_new_feature#pivotal-hash1234}
git cherry-pick {shah}
# This will be the shah for the commit on main if you have a PR there. You can also base your work entirely off staging and cherry-pick to main once it's been accepted.git push
- Open a PR from the staging branch
git checkout staging
git checkout -b {your_branch}
- Merging the PR will kick off the pipeline and deploy to the Aptible staging environment.
Once your PR has been merged and accepted in staging, you can cherry pick your commit from staging into main like:
- Find the shah of your commit by going to the GitHub UI or running
git log
git checkout main
git checkout {new_branch}
git cherry-pick {shah}
# from step 1- Open a PR on main with the code that was accepted on staging.
To deploy to Production, run the bin/release
script from the project root. In
most cases, you will want to run this from the main
branch. It can be run
from a different branch, however this may complicate subsequent releases
unless the release
branch is merged back into main
after the fact.
This script will undertake all the necessary steps for a deployment. If there is
a merge conflict when merging main
into release
, the conflicts must be
resolved by hand, then re-run bin/release
.
The script also creates a tag. For regular releases, we use version-N.N.N
,
incrementing the appropriate number. Please consult
semver.org for advice on semantic versioning.
The steps the bin/release
script automates are as follows:
- fetches from origin
- prompts for new tag name
- opens editor with template, includes list of changes
- merges current branch (usually
main
) intorelease
- creates tag and GitHub release using
hub
tool
After this, CircleCI runs and deploys if the tests pass.
To issue a release without using the script, follow the steps listed above:
git pull
the main and release branches- from the
release
branch,git merge --ff main
git tag <version name>
with the next versiongit push && git push --tags
To issue a release from Github, use the same naming convention, but begin by clicking the 'releases' button on the main page. Github provides useful documentation here.
It may be necessary in some circumstances to trigger a deploy of code that isn't on master. Here is a set of steps you can follow.
git fetch
to make sure you have the latest codegit checkout release
to switch to the release branchgit reset --hard origin/release
to make your release branch match what's on GitHubgit log
to validate that you're on an identical commit toorigin/release
- Make whatever commits you need to make. Consider
git cherry-pick
to grab individual commits from main. For examplegit cherry-pick commitId
will grab a commit whose ID iscommitId
. git tag version-N.N.N
with the next version. You can find the previous versions listed on the GitHub releases page, or in the output ofgit tag
.git push --tags
to push the tag to GitHub- Visit https://github.com/codeforamerica/vita-min/releases and create a new Release based the tag; this automatically informs #tax-team about the release.
git push origin release
to push the release branch to GitHub. This will trigger the hotfix deploy.
Check CircleCI and see that it's going out.
Now we'll merge the hotfix code into main to avoid merge conflict confusion down the road.
git checkout main
to switch to the main branchgit merge release
to merge the code into maingit push
to push the changes to main to GitHub
You can check out and work directly on the release
branch, performing a push
when complete. You should immediately merge release
into main
.
Create a hotfix branch directly from release
(rather than main
) if a PR is
recommended. When creating the PR, set the PR to target release
rather than
main
. When reviewed and merged, merge release
back into main
.
A deployment can be safely rolled back so long as the code you're rolling-back to can read a database version created by the new code. Our rollback process does not run reverse migrations.
There are three steps to performing a rollback:
- Identify the commit you wish to roll back to
- Say on Slack you'll do a rollback
- Force-push the old commit ID to Aptible
- Force-push the old commit ID to the release branch
To roll back to a version, you'll need either its version-x.y.z
name, or a git commit ID, or another ID git understands.
Visit the releases page to find the release you want to roll back to.
The release script will print a message like this the end of execution:
🧷 Old release was: version-1.2.3
Copy this ID to your clipboard.
On #gyr-eng and #gyr-team please write something like the following:
Performing a rollback to version-1.2.3
The fastest way to rollback is to directly push this ID to Aptible. Assuming you want to roll back to version-1.2.3
,
you can do so with:
git fetch aptible-prod
git push aptible-prod version-1.2.3:master --force-with-lease
This approach is best for a fast rollback. It needs to be a force push in order to go backwards in git history.
It is faster than pushing release first because it skips CircleCI. You must use the branch name master
because that
is Aptible's main branch.
If you do not have the aptible-prod
git remote, you can add it with this command, then re-try the push.
git remote add aptible-prod [email protected]:vita-min-prod/vita-min-prod.git
It's good to keep the release
branch up to date. Assuming you are rolling back to version-1.2.3
, you can run:
git push origin version-1.2.3:release --force-with-lease
This will trigger CircleCI, and CircleCI may or may not have difficulty with the final step of releasing to Aptible production. Since you already released to Aptible production, this is peaceful.
To view a detailed list of releases, visit https://github.com/codeforamerica/vita-min/releases
To view a list of tags (with the highest releases at the top):
git tag | sort --version-sort -r
To view a list of releases with their SHAs (latest first):
bin/show-tags
To tag a release:
git tag version-N.N.N
Once a release has been tagged, you'll want to push the tag to GitHub:
git push --tags