Include tags when syncing master -> test * include tags when syncing master -> test Approved-by: Linus Flood
netlify-plugin-branch-sync
This is a Netlify build plugin.
Its purpose is to sync a configured source branch to other configured destination branches.
The configuration is done inside of index.js instead of using environment variables so that the branch configurations are version controlled.
SYNC_SOURCE is the source branch that will be pushed to the destination branches.
SYNC_DEST is an array of destination branches that will receive the push from SYNC_SOURCE.
This plugin only executes its sync operations when the branch being built in Netlify is the SYNC_SOURCE branch and the build context is 'Branch build'. Any other branch or build context is ignored and this plugin does nothing.
How to setup
In Bitbucket, create an access token for the repository this plugin will act on, e.g. https://bitbucket.org/scandic-swap/web/admin/access-tokens.
It needs to have the following permissions:
repositoryrepository:write
Add the following environment variables in the Netlify dashboard.
IMPORTANT!
Be sure to set them to only be available in the "Builds" scope and only set a value for the "Branch deploys" configuration.
- BITBUCKET_USER_EMAIL: The email for the access token (Bitbucket generates this and provides it when creating an access token)
- BITBUCKET_ACCESS_TOKEN: The access token
How it works
It uses two build plugin events:
onPreBuildonPostBuild
It fails the whole build if the plugin does not complete the sync to all the branches.
Since it uses git directly and we want to sync to latest always, the plugin can be rerun in case of failures and git will resume where needed.
Event: onPreBuild
- Checks that the current branch being built is
SYNC_SOURCEand the build context is a branch build, otherwise does nothing. - Checks for the presence of the required environment variables.
- Uses
gitto configure theuser.emailand set it to environment variableBITBUCKET_USER_EMAIL - Attempts to restore the clone from the build cache and if that fails proceeds to clone it.
- Uses
gitto fetches the configured branches,SYNC_SOURCEandSYNC_DESTfrom origin, skipping all tags. - Loops over the branches and uses
gitto sequentially push the latest ref onSYNC_SOURCEto eachSYNC_DESTbranch respectively. Since a single push completes fast (under 200 ms), we opt to not push in parallel to try and avoid any rate limits. - Reports to Netlify the completion and provides some info to the "Deploy summary" for the build.
- If anything throws an error during execution the whole build is failed
Event: onPostBuild
- Checks that the current branch being built is
SYNC_SOURCEand the build context is a branch build, otherwise does nothing. - Attempts to save the clone to the build cache. If it fails by throwing an error the whole build is failed. If it fails without throwing an error the build will succeed.
Under the hood
Bare repository
Since this plugin only does git operations that do not need a working copy, it clones the repository it uses for the operations as a bare repository.
The layout of a bare repository differs from a working copy. The way git identifies a working copy with through the presence of a folder named .git. Bare repositories do not have this folder. Instead git uses different heuristics to determine if the directory is a clone, one of which is the presence of a folder named refs.
The folder named refs only contains two folders after a bare clone operation, heads and tags. These two folder are both empty themselves.
This fact poses a challenge for the build cache because it only caches files and not empty directories.
Build cache usage
This plugin uses the utilities for caching files in Netlify Build.
This utility uses cpy to copy files to and from the cache and uses move-file to move files to and from the cache.
The use of cpy is what causes the build cache to not include empty directories because cpy only copies files and skips empty directories.
So to work around the problem this plugin uses the move mode of the build cache API which instead uses move-file instead of cpy, keeping the full directory layout as git requires it.
The move mode is required for both the restore() and save() build cache operations for the workaround to work. It is done by passing move: true as options to the calls.