shipwright
A simple/consistent way to create build artifacts with calculated tags and then update related repositories (think packages, tarballs, docker builds, etc.).
Why Not Bash?
- copy pasta'd shell script is tough to maintain, "did I copy that change to all 20+ repos?"
- automated testing is nicer than pushing to CI to see what will happen
- with an increasing set of integration/features I prefer JS as a way to develop and share these features/ideas
Install
npm i @npm-wharf/shipwright
CLI
Right now this mashes a lot of other tools into a promise chain behind a single command.
shipwright build image
Builds a docker image with all default options. Read carefully, there are kindovalot.
-
--repo
- the image repository to build for, no default -
--name
- defaults to the package'sname
-
--name-prefix
- optionally prefix default package name -
--name-postfix
- optionally postfix default package name -
--working-path
- the working directory for the build, defaults to./
-
--docker-file
- the DockerFile to use, defaults to./Dockerfile
-
--build-arg
- used to define anARG
key in the Dockerfile. (example: `--build-arg key=value) -
--tags
- defaults are: (see buildgoggles for tag specifications)-
lt,v_s,v,miv,ma
[ 'latest', '1.2.3_abcdefgh', '1.2.3', '1.2', '1' ]
- for tagged builds -
v_c_s
[ '1.2.3_10_abcdefgh' ]
- for master commits -
b_v_c_s
[ 'branch_1.2.3_10_abcdefgh' ]
- in any other branch when:-
--always-build
is an argument -
--build-branches
contains the current branch - the commit message contains
[build-image]
-
-
-
--registry
- defaults to hub.docker.com -
--lts-only
- defaults totrue
: when true, skips everything for non-LTS Node versions -
--skip-prs
- defaults totrue
: should anything other than a Docker build is done for PRs -
--no-push
- prevents shipwright from pushing the image to the registry -
--update-with
- specify an instruction file for how to send a PR to another GitHub repository's file -
--sudo
- defaults totrue
: use sudo with Docker commands -
--verbose
- defaults tofalse
: include Docker build output in console logs -
--always-build
- always produce a build regardless of the branch by providing the default tag specification[ 'b_v_c_s' ]
if no other tags have been specified -
--build-branches
- defaults to[ 'staging', 'qa', 'dev' ]
: a list of branches to build for (other than master) with the default tag specification[ 'b_v_c_s' ]
if no other tags have been specified. -
--cache-from-latest
- will cause shipwright to add a--cache-from
argument to Docker with the current image name and thelatest
tag. -
--cache-from
- will cause shipwright to pass the argument on to docker's--cache-from
-
--flatten
- creates a new flattened image with no history and a single layer
--always-build
and --build-branches
Use cases for These flags are intended to supply ways to get shipwright to generate build images for development branches without disrupting the useful default tag specs provided for master and tagged builds and without having to constantly rely on filling your commit log with [build-image]
.
The build-branches
defaults effectively guarantee you'll get build images if you push to branches named staging
, qa
, or dev
.
Default Build Behavior
With all the tags, it is a bit unclear what the shipwright's default behavior actually would be if you were to, for example, just add the following lines to travis:
after_success:
- docker login -u="$DOCKER_USERNAME" -p="$DOCKER_PASSWORD"
- shipwright build image --repo=myRepo --name=imageName
For Builds On Master (With Git Tags On The Commit)
A docker image will get built, tagged and pushed with the following tags:
latest
1
1.2
1.2.3
1.2.3_abcdefgh
For Builds On Master (Without Git Tags On The Commit)
A docker image will get built, tagged and pushed with a tag that contains the version, build number and commit sha:
1.2.3_10_abcdefgh
--build-branches
(staging
, qa
, dev
)
For Builds On A A docker image will get built, tagged and pushed with a tag that contains the branch name, version, build number, and commit sha:
branch-name_1.2.3_10_abcdefgh
[build-image]
In The Commit Message
For Builds With Even without adding flags, you can still get a build on any branch with the tag specification that contains the branch, version:
branch-name_1.2.3_10_abcdefgh
For PRs and Builds On Non-LTS Versions of Node
shipwright won't do anything at all. This is to avoid drawing out the build times on your CI server. You can change these behaviors with the skip-prs
and lts-only
flags, of course, but this is about default build behavior.
Caching Support
shipwright has three different caching support options you can use to populate Docker's --cache-from
argument.
In the event that any of these flags result in an error from the Docker CLI, shipwright will fall back to making the command without the --cache-from
argument. If your build is not getting faster, check your log output and make sure that the image it's trying to cache from actually exists in the target Docker repository.
cache-from-latest
This flag will append the latest
tag to your current image and attempt to use that to populate Docker's --cache-from
argument.
cache-from
This argument allows you to provide your own full specification to shipwright that it will then pass through to Docker.
updateWith
- Instruction Files & PR Plugins
The updateWith
argument is way to plug in your own transformers after the fact to get shipwright to send a PR to another GitHub repository in order to update a single file.
This uses github-change-remote-file so the limitation here is that it can change 1 file at a time. The transformer plugin you write will get passed a buildInfo
hash with all the context of the build and the instruction file with any static arguments you'd like to pass it.
plugin format
The plugin module should export a function that takes the build information and instruction file content and returns a function that transforms the target file's contents (passed as a string) and returns the changed content.
module.exports = function( buildInfo, instructions ) {
return function( raw ) {
// do something to the file
return changedContent;
};
}
instruction file
You can provide an instruction file in either JSON or YAML.
The source properties control the repository and branch the pull request will be made from and what file will be changed. The source owner
, repo
, and file
values are required to specify the target GitHub repository and path to the file relative to the repository's root. If the source branch
is left out, it will default to master
. The module
argument is required and should be the name of an installed npm module or the relative path to a JS module in the current repository that satisfies the plugin behavior. The branch
name is also optional and if left off, will be calculated based off the current build parameters.
Any other values included in the file itself will be deserialized and passed to your plugin.
{
"source": {
"owner": "me",
"repo": "test",
"file": "somefile.txt",
"branch": "master"
},
"module": "myPlugin",
"branch": "pr"
}
source:
owner: me
repo: test
file: somefile.txt
branch: master
module: myPlugin
branch: pr
buildInfo
hash
The build information hash will contain the following properties:
{
"owner": "npm",
"repository": "shipwright",
"branch": "master",
"version": "0.1.0",
"build": 10,
"slug": "a1b2c3d4",
"tag": "arobson_build-goggles_master_0.1.0_1_a1b2c3d4",
"isLTS": true,
"commitMessage": "the commit message used",
"ci": {
"inCI": "true",
"tagged": false,
"pullRequest": false
},
"imageName": "repo/image"
}
Note: the
imageName
property will only exist if an artifact (like a Docker image) was produced as part of the build
Roadmap
- separate command so that build and push are represented as different steps
- add support for additional artifact types
- support multiple artifact types per build