UNPKG

42.1 kBMarkdownView Raw
1<p align="center">
2 <img src="img/logo.svg" width="280">
3 <br />
4</p>
5
6# Craft: Universal Release Tool (And More) <!-- omit in toc -->
7
8[![Travis](https://img.shields.io/travis/getsentry/craft.svg)](https://travis-ci.org/getsentry/craft)
9[![GitHub release](https://img.shields.io/github/release/getsentry/craft.svg)](https://github.com/getsentry/craft/releases/latest)
10[![npm version](https://img.shields.io/npm/v/@sentry/craft.svg)](https://www.npmjs.com/package/@sentry/craft)
11[![license](https://img.shields.io/github/license/getsentry/craft.svg)](https://github.com/getsentry/craft/blob/master/LICENSE)
12
13`craft` is a command line tool that helps to automate and pipeline package releases. It suggests, and
14then enforces a specific workflow for managing release branches, changelogs, artifact publishing, etc.
15
16## Table of Contents <!-- omit in toc -->
17
18- [Installation](#installation)
19- [Usage](#usage)
20- [Caveats](#caveats)
21- [Global Configuration](#global-configuration)
22 - [Environment Files](#environment-files)
23- [Workflow](#workflow)
24 - [`craft prepare`: Preparing a New Release](#craft-prepare-preparing-a-new-release)
25 - [`craft publish`: Publishing the Release](#craft-publish-publishing-the-release)
26 - [Example](#example)
27- [Configuration File: `.craft.yml`](#configuration-file-craftyml)
28 - [GitHub project](#github-project)
29 - [Pre-release Command](#pre-release-command)
30 - [Post-release Command](#post-release-command)
31 - [Release Branch Name](#release-branch-name)
32 - [Changelog Policies](#changelog-policies)
33 - [Minimal Version](#minimal-version)
34 - [Required Files](#required-files)
35- [Status Provider](#status-provider)
36- [Artifact Provider](#artifact-provider)
37 - [Using Github Actions with Github Artifact Provider](#using-github-actions-with-github-artifact-provider)
38- [Target Configurations](#target-configurations)
39 - [Per-target options](#per-target-options)
40 - [GitHub (`github`)](#github-github)
41 - [NPM (`npm`)](#npm-npm)
42 - [Python Package Index (`pypi`)](#python-package-index-pypi)
43 - [Homebrew (`brew`)](#homebrew-brew)
44 - [NuGet (`nuget`)](#nuget-nuget)
45 - [Rust Crates (`crates`)](#rust-crates-crates)
46 - [Google Cloud Storage (`gcs`)](#google-cloud-storage-gcs)
47 - [GitHub Pages (`gh-pages`)](#github-pages-gh-pages)
48 - [Sentry Release Registry (`registry`)](#sentry-release-registry-registry)
49 - [Cocoapods (`cocoapods`)](#cocoapods-cocoapods)
50 - [Docker (`docker`)](#docker-docker)
51 - [Ruby Gems Index (`gem`)](#ruby-gems-index-gem)
52 - [AWS Lambda Layer (`aws-lambda-layer`)](#aws-lambda-layer-aws-lambda-layer)
53- [Integrating Your Project with `craft`](#integrating-your-project-with-craft)
54- [Pre-release (Version-bumping) Script: Conventions](#pre-release-version-bumping-script-conventions)
55- [Post-release Script: Conventions](#post-release-script-conventions)
56- [Development](#development)
57 - [Logging Level](#logging-level)
58 - [Dry-run Mode](#dry-run-mode)
59 - [Sentry Support](#sentry-support)
60 - [Releasing](#releasing)
61
62## Installation
63
64The tool is distributed as an NPM package and can be installed via `npm` or `yarn`:
65
66```bash
67yarn global add @sentry/craft
68
69# Or (not preferred):
70
71npm install -g @sentry/craft
72```
73
74## Usage
75
76```plain
77$ craft -h
78craft <command>
79
80Commands:
81 craft prepare NEW-VERSION 🚢 Prepare a new release branch
82 [aliases: p, prerelease, prepublish, prepare, release]
83 craft publish NEW-VERSION 🛫 Publish artifacts [aliases: pp, publish]
84
85Options:
86 --no-input Suppresses all user prompts [boolean] [default: false]
87 --dry-run Dry run mode: do not perform any real actions
88 [boolean] [default: false]
89 -v, --version Show version number [boolean]
90 -h, --help Show help [boolean]
91```
92
93## Caveats
94
95- When interacting with remote GitHub repositories, `craft` uses by default the
96 "origin" remote. If you have a different setup, set the `CRAFT_REMOTE`
97 environment variable.
98
99## Global Configuration
100
101Global configuration for `craft` can be done either by using environment variables
102or by adding values to a configuration file (see below).
103
104In either case, at least the following two values must be configured in order
105for craft to function properly:
106
107- `GITHUB_TOKEN`
108
109 Get your personal GitHub API token here: https://github.com/settings/tokens
110
111 The token only needs "repo" scope ("repo:status" and "public_repo" subscopes, to be even more precise).
112
113- `ZEUS_API_TOKEN`
114
115 You can generate your personal Zeus token here: https://zeus.ci/settings/token
116
117 Required only for `craft publish`.
118
119Additional configuration may be required when publishing to specific
120targets (e.g. `TWINE_USERNAME` and `TWINE_PASSWORD` for PyPI target).
121
122### Environment Files
123
124`craft` will read configuration variables (keys, tokens, etc.) from the
125following locations:
126
127- `$HOME/.craft.env`
128- `$PROJECT_DIR/.craft.env`
129- the shell's environment
130
131...where `$HOME` is the current user's home directory, and `$PROJECT_DIR` is the directory where `.craft.yml` is located.
132
133The above locations will be checked in the order specified above, with values
134found in one location overwriting anything found in previous locations. In other
135words, environment variables will take precedence over either configuration
136file, and the project-specific file will take precedence over the file in
137`$HOME`.
138
139The files must be written in shell (`sh`/`bash`) format. Leading `export` is allowed.
140
141Example:
142
143```sh
144# ~/.craft.env
145GITHUB_TOKEN=token123
146export NUGET_API_TOKEN=abcdefgh
147```
148
149## Workflow
150
151### `craft prepare`: Preparing a New Release
152
153This command will create a new release branch, check the changelog entries,
154run a version-bumping script, and push the new branch to GitHub.
155
156```plain
157craft prepare NEW-VERSION
158
159🚢 Prepare a new release branch
160
161Positionals:
162 NEW-VERSION The new version you want to release [string] [required]
163
164Options:
165 --no-input Suppresses all user prompts [boolean] [default: false]
166 --dry-run Dry run mode: do not perform any real actions
167 [boolean] [default: false]
168 --no-push Do not push the release branch [boolean] [default: false]
169 --no-git-checks Ignore local git changes and unsynchronized remotes
170 [boolean] [default: false]
171 --no-changelog Do not check for changelog entries [boolean] [default: false]
172 --publish Run "publish" right after "release"[boolean] [default: false]
173```
174
175### `craft publish`: Publishing the Release
176
177The command will find a release branch for the provided version (tag) and
178publish the existing artifacts from the configured artifact provider to selected targets.
179
180```plain
181craft publish NEW-VERSION
182
183🛫 Publish artifacts
184
185Positionals:
186 NEW-VERSION Version to publish [string] [required]
187
188Options:
189 --no-input Suppresses all user prompts [boolean] [default: false]
190 --dry-run Dry run mode: do not perform any real actions
191 [boolean] [default: false]
192 --target, -t Publish to this target
193 [string] [choices: "brew", "cocoapods", "crates", "gcs", "gh-pages", "github",
194 "npm", "nuget", "pypi", "registry", "all", "none"] [default: "all"]
195 --rev, -r Source revision to publish [string]
196 --no-merge Do not merge the release branch after publishing
197 [boolean] [default: false]
198 --keep-branch Do not remove release branch after merging it
199 [boolean] [default: false]
200 --keep-downloads Keep all downloaded files [boolean] [default: false]
201 --no-status-check Do not check for build status in Zeus
202 [boolean] [default: false]
203```
204
205### Example
206
207Let's imagine we want to release a new version of our package, and the version
208in question is `1.2.3`.
209
210We run `prepare` command first:
211
212`$ craft prepare 1.2.3`
213
214After some basic sanity checks this command creates a new release branch
215`release/1.2.3`, runs the version-bumping script (`scripts/bump-version.sh`),
216commits the changes made by the script, and then pushes the new branch to
217GitHub. At this point CI systems kick in, and the results of those builds, as
218well as built artifacts (binaries, NPM archives, Python wheels) are gradually
219uploaded to Zeus.
220
221To publish the built artifacts we run `publish`:
222
223`$ craft publish 1.2.3`
224
225This command will find our release branch (`release/1.2.3`), check the build
226status of the respective git revision in Zeus, and then publish available
227artifacts to configured targets (for example, to GitHub and NPM in the case of
228Craft).
229
230## Configuration File: `.craft.yml`
231
232Project configuration for `craft` is stored in `.craft.yml` configuration file,
233located in the project root.
234
235### GitHub project
236
237One of the required settings you need to specify is GitHub project parameters. For example:
238
239```yaml
240github:
241 owner: getsentry
242 repo: sentry-javascript
243```
244
245### Pre-release Command
246
247This command will run on your newly created release branch as part of `prepare`
248command. By default, it is set to `bash scripts/bump-version.sh`. Please refer
249to the [Pre-release version bumping script conventions section](#pre-release-version-bumping-script-conventions)
250for more details.
251
252```yaml
253preReleaseCommand: bash scripts/bump-version.sh
254```
255
256### Post-release Command
257
258This command will run after a successful `publish`. By default, it is set to
259`bash scripts/post-release.sh`. It will _not_ error if the default script is
260missing though, as this may not be needed by all projects. Please refer to the
261[Post-release script conventions section](#post-release-script-conventions)
262for more details.
263
264```yaml
265postReleaseCommand: bash scripts/post-release.sh
266```
267
268### Release Branch Name
269
270This overrides the prefix for the release branch name. The full branch name used
271for a release is `{releaseBranchPrefix}/{version}`. The prefix defaults to
272`"release"`.
273
274```yaml
275releaseBranchPrefix: publish
276```
277
278### Changelog Policies
279
280`craft` can help you to maintain change logs for your projects. At the moment,
281`craft` supports two approaches: `simple`, and `auto` to changelog management.
282
283In `simple` mode, `craft prepare` will remind you to add a changelog entry to the
284changelog file (`CHANGELOG.md` by default).
285
286In `auto` mode, `craft prepare` will use the following logic:
287
2881. If there's already an entry for the given version, use that
2892. Else if there is an entry named `Unreleased`, rename that to the given
290 version
2913. Else, create a new section for the version and populate it with a default
292 text: `- No documented changes for this release.`
293
294**Configuration**
295
296| Option | Description |
297| ----------------- | ------------------------------------------------------------------------------------------ |
298| `changelog` | **optional**. Path to the changelog file. Defaults to `CHANGELOG.md` |
299| `changelogPolicy` | **optional**. Changelog management mode (`none`, `simple`, or `auto`). Defaults to `none`. |
300
301**Example (`simple`):**
302
303```yaml
304changelog: CHANGES
305changelogPolicy: simple
306```
307
308**Valid changelog example:**
309
310```text
311## 1.3.5
312
313* Removed something
314
315## 1.3.4
316
317* Added something
318```
319
320**Example (`auto`):**
321
322```yaml
323changelog: CHANGES
324changelogPolicy: auto
325```
326
327**Changelog with staged changes example:**
328
329```text
330## Unreleased
331
332* Removed something
333
334## 1.3.4
335
336* Added something
337```
338
339Additionally, `.craft.yml` is used for listing targets where you want to
340publish your new release.
341
342### Minimal Version
343
344It is possible to specify minimal `craft` version that is required to work with
345your configuration.
346
347**Example:**
348
349```yaml
350minVersion: '0.5.0'
351```
352
353### Required Files
354
355You can provide a list of patterns for files that _have to be_ available before
356proceeding with publishing. In other words, for every pattern in the given list
357there has to be a file present that matches that pattern. This might be helpful
358to ensure that we're not trying to do an incomplete release.
359
360**Example:**
361
362```yaml
363requireNames:
364 - /^sentry-craft.*\.tgz$/
365 - /^gh-pages.zip$/
366```
367
368## Status Provider
369
370You can configure which status providers `craft` will use to check for your build status.
371By default, it will take Zeus but you can also use GitHub directly.
372This is helpful if you don't want to rely on Zeus for asking if you build is green or not.
373
374**Configuration**
375
376| Option | Description |
377| -------- | -------------------------------------------------------------------------------------------------- |
378| `name` | Name of the status provider: either `zeus` (default) or `github` |
379| `config` | In case of `github`: may include `contexts` key that contains a list of required contexts (checks) |
380
381**Example:**
382
383```yaml
384statusProvider:
385 name: github
386 config:
387 contexts:
388 - Travis CI - Branch
389```
390
391## Artifact Provider
392
393You can configure which artifact providers `craft` will use to fetch artifacts from.
394By default, Zeus is used, but in case you don't need use any artifacts in your
395project, you can set it to `none`.
396
397**Configuration**
398
399| Option | Description |
400| ------ | -------------------------------------------------------------------------- |
401| `name` | Name of the artifact provider: can be `zeus` (default), `github` or `none` |
402
403**Example:**
404
405```yaml
406artifactProvider:
407 name: none
408```
409
410### Using Github Actions with Github Artifact Provider
411
412When using Github Action you can use the Github Artifact Provider for managing your release artifacts.
413The way it works is simple, use the official GHA `actions/upload-artifact@v2` action to upload your assets.
414Craft can work with them and use it instead of Zeus.
415Here is an example config (step) of an archive job:
416
417```yaml
418- name: Archive Artifacts
419 uses: actions/upload-artifact@v2
420 with:
421 name: ${{ github.sha }}
422 path: |
423 ${{ github.workspace }}/*.tgz
424 ${{ github.workspace }}/packages/tracing/build/**
425 ${{ github.workspace }}/packages/**/*.tgz
426```
427
428A few important things to note:
429
430- The name of the artifacts is very important and needs to be `name: ${{ github.sha }}`. Craft uses this as a unique id to fetch the artifacts.
431- Keep in mind that this action maintains the folder structure and zips everything together. Craft will download the zip and recursively walk it to find all assets.
432
433## Target Configurations
434
435The configuration specifies which release targets to run for the repository. To
436run more targets, list the target identifiers under the `targets` key in
437`.craft.yml`.
438
439**Example:**
440
441```yaml
442targets:
443 - name: github
444 - name: npm
445```
446
447### Per-target options
448
449The following options can be applied to every target individually:
450
451| Name | Description |
452| -------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
453| `includeNames` | **optional**. Regular expression: only matched files will be processed by the target. There is one special case that `includeNames` supports, if your build doesn't any artifacts you can write `includeNames: /none/`, this will skip the check for artifacts towards Zeus entirely. |
454| `excludeNames` | **optional**. Regular expression: the matched files will be skipped by the target. Matching is performed after testing for inclusion (via `includeNames`). |
455
456If neither option is included, all artifacts for the release will be processed by the target.
457
458**Example:**
459
460```yaml
461targets:
462 - name: github
463 includeNames: /^.*\.exe$/
464 excludeNames: /^test.exe$/
465```
466
467### GitHub (`github`)
468
469Create a release on Github. If a Markdown changelog is present in the
470repository, this target tries to read the release name and description from the
471changelog. Otherwise, defaults to the tag name and tag's commit message.
472
473If `previewReleases` is set to `true` (which is the default), the release
474created on GitHub will be marked as a pre-release version if the release name
475contains any one of `preview`, `pre`, `rc`, `dev`,`alpha`, `beta`, `unstable`,
476`a`, or `b`.
477
478**Environment**
479
480| Name | Description |
481| -------------- | ------------------------------------------------------------------ |
482| `GITHUB_TOKEN` | Personal GitHub API token (see https://github.com/settings/tokens) |
483
484**Configuration**
485
486| Option | Description |
487| ----------------- | -------------------------------------------------------------------------------------------- |
488| `tagPrefix` | **optional**. Prefix for new git tags (e.g. "v"). Empty by default. |
489| `previewReleases` | **optional**. Automatically detect and create preview releases. `true` by default. |
490| `annotatedTag` | **optional**. Creates an annotated tag, set to false for lightweight tag. `true` by default. |
491
492**Example:**
493
494```yaml
495targets:
496 - name: github
497 tagPrefix: v
498 previewReleases: false
499 annotatedTag: false
500```
501
502### NPM (`npm`)
503
504Releases an NPM package to the public registry. This requires a package tarball
505generated by `npm pack` in the artifacts. The file will be uploaded to the
506registry with `npm publish`, or with `yarn publish` if `npm` is not found. This
507requires NPM to be authenticated with sufficient permissions to publish the package.
508
509**Environment**
510
511The `npm` utility must be installed on the system.
512
513| Name | Description |
514| ------------------- | ------------------------------------------------------------------- |
515| `NPM_TOKEN` | An [automation token][npm-automation-token] allowed to publish. |
516| `NPM_BIN` | **optional**. Path to the npm executable. Defaults to `npm` |
517| `YARN_BIN` | **optional**. Path to the yarn executable. Defaults to `yarn` |
518| `CRAFT_NPM_USE_OTP` | **optional**. If set to "1", you will be asked for an OTP (for 2FA) |
519
520[npm-automation-token]: https://docs.npmjs.com/creating-and-viewing-access-tokens
521
522**Configuration**
523
524| Option | Description |
525| -------- | -------------------------------------------------------------------------------- |
526| `access` | **optional**. Visibility for scoped packages: `restricted` (default) or `public` |
527
528**Example**
529
530```yaml
531targets:
532 - name: npm
533 access: public
534```
535
536### Python Package Index (`pypi`)
537
538Uploads source dists and wheels to the Python Package Index via [twine](https://pypi.org/project/twine/).
539The source code bundles and/or wheels must be in the release assets.
540
541**Environment**
542
543The `twine` Python package must be installed on the system.
544
545| Name | Description |
546| ---------------- | ----------------------------------------------------- |
547| `TWINE_USERNAME` | User name for PyPI with access rights for the package |
548| `TWINE_PASSWORD` | Password for the PyPI user |
549| `TWINE_BIN` | **optional**. Path to twine. Defaults to `twine` |
550
551**Configuration**
552
553_none_
554
555**Example**
556
557```yaml
558targets:
559 - name: pypi
560```
561
562### Homebrew (`brew`)
563
564Pushes a new or updated homebrew formula to a brew tap repository. The formula
565is committed directly to the master branch of the tap on GitHub, therefore the
566bot needs rights to commit to `master` on that repository. Therefore, formulas
567on `homebrew/core` are not supported, yet.
568
569The tap is configured with the mandatory `tap` parameter in the same format as
570the `brew` utility. A tap `<org>/<name>` will expand to the GitHub repository
571`github.com:<org>/homebrew-<name>`.
572
573The formula contents are given as configuration value and can be interpolated
574with Mustache template syntax (`{{ variable }}`). The interpolation context
575contains the following variables:
576
577- `version`: The new version
578- `revision`: The tag's commit SHA
579- `checksums`: A map containing sha256 checksums for every release asset. Use
580 the full filename to access the sha, e.g. `checksums.MyProgram-x86`
581
582**Environment**
583
584| Name | Description |
585| -------------- | ------------------------------------------------------------------ |
586| `GITHUB_TOKEN` | Personal GitHub API token (seeh ttps://github.com/settings/tokens) |
587
588**Configuration**
589
590| Option | Description |
591| ---------- | ------------------------------------------------------------------ |
592| `tap` | The name of the homebrew tap used to access the GitHub repo |
593| `template` | The template for contents of the formula file (ruby code) |
594| `formula` | **optional**. Name of the formula. Defaults to the repository name |
595| `path` | **optional**. Path to store the formula in. Defaults to `Formula` |
596
597**Example**
598
599```yaml
600targets:
601 - name: brew
602 tap: octocat/tools # Expands to github.com:octocat/homebrew-tools
603 formula: myproject # Creates the file myproject.rb
604 path: HomebrewFormula # Creates the file in HomebrewFormula/
605 template: >
606 class MyProject < Formula
607 desc "This is a test for homebrew formulae"
608 homepage "https://github.com/octocat/my-project"
609 url "https://github.com/octocat/my-project/releases/download/{{version}}/binary-darwin"
610 version "{{version}}"
611 sha256 "{{checksums.binary-darwin}}"
612
613 def install
614 mv "binary-darwin", "myproject"
615 bin.install "myproject"
616 end
617 end
618```
619
620### NuGet (`nuget`)
621
622Uploads packages to [NuGet](https://www.nuget.org/) via [.NET Core](https://github.com/dotnet/core).
623By default, `craft` publishes all packages with `.nupkg` extension.
624
625**Environment**
626
627The `dotnet` tool must be available on the system.
628
629| Name | Description |
630| ------------------ | ---------------------------------------------------------------- |
631| `NUGET_API_TOKEN` | NuGet personal API token (https://www.nuget.org/account/apikeys) |
632| `NUGET_DOTNET_BIN` | **optional**. Path to .NET Core. Defaults to `dotnet` |
633
634**Configuration**
635
636_none_
637
638**Example**
639
640```yaml
641targets:
642 - name: nuget
643```
644
645### Rust Crates (`crates`)
646
647Publishes a single Rust package or entire workspace on the public crate registry
648([crates.io](https://crates.io)). If the workspace contains multiple crates,
649they are published in an order depending on their dependencies.
650
651**Environment**
652
653"cargo" must be installed and configured on the system.
654
655| Name | Description |
656| ----------------- | ------------------------------------------------- |
657| `CRATES_IO_TOKEN` | The access token to the crates.io account |
658| `CARGO_BIN` | **optional**. Path to cargo. Defaults to `cargo`. |
659
660**Configuration**
661
662| Option | Description |
663| ----------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
664| `noDevDeps` | **optional**. Strips `devDependencies` from crates before publishing. This is useful if a workspace crate uses circular dependencies for docs. Requires [`cargo-hack`](https://github.com/taiki-e/cargo-hack#readme) installed. Defaults to `false`. |
665
666**Example**
667
668```yaml
669targets:
670 - name: crates
671 noDevDeps: false
672```
673
674### Google Cloud Storage (`gcs`)
675
676Uploads artifacts to a bucket in Google Cloud Storage.
677
678The bucket paths (`paths`) can be interpolated using Mustache syntax (`{{ variable }}`). The interpolation context contains the following variables:
679
680- `version`: The new project version
681- `revision`: The SHA revision of the new version
682
683**Environment**
684
685Google Cloud credentials can be provided using either of the following two environment variables.
686
687| Name | Description |
688| ----------------------------- | ------------------------------------------------------------------------ |
689| `CRAFT_GCS_TARGET_CREDS_PATH` | Local filesystem path to Google Cloud credentials (service account file) |
690| `CRAFT_GCS_TARGET_CREDS_JSON` | Full service account file contents, as a JSON string |
691
692If defined, `CRAFT_GCS_TARGET_CREDS_JSON` will be preferred over `CRAFT_GCS_TARGET_CREDS_PATH`.
693
694_Note:_ `CRAFT_GCS_TARGET_CREDS_JSON` and `CRAFT_GCS_TARGET_CREDS_PATH` were formerly called `CRAFT_GCS_CREDENTIALS_JSON` and `CRAFT_GCS_CREDENTIALS_PATH`, respectively. While those names will continue to work for the foreseeable future, you'll receive a warning encouraging you to switch to the new names.
695
696**Configuration**
697
698| Option | Description |
699| ---------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
700| `bucket` | The name of the GCS bucket where artifacts are uploaded. |
701| `paths` | A list of path objects that represent bucket paths. |
702| `paths.path` | Template-aware bucket path, which can contain `{{ version }}` and/or `{{ revision }}`. |
703| `paths.metadata` | **optional** [Metadata](https://cloud.google.com/storage/docs/json_api/v1/objects/insert#request_properties_JSON) for uploaded files. By default, it sets `Cache-Control` to `"public, max-age=300"`. |
704
705**Example**
706
707```yaml
708targets:
709 - name: gcs
710 bucket: bucket-name
711 paths:
712 - path: release/{{version}}/download
713 metadata:
714 cacheControl: `public, max-age=3600`
715 - path: release/{{revision}}/platform/package
716```
717
718### GitHub Pages (`gh-pages`)
719
720Extracts an archive with static assets and pushes them to the specified git
721branch (`gh-pages` by default). Thus, it can be used to publish documentation
722or any other assets to [GitHub Pages](https://pages.github.com/), so they will be later automatically rendered
723by GitHub.
724
725By default, this target will look for an artifact named `gh-pages.zip`, extract it,
726and commit its contents to `gh-pages` branch.
727
728_WARNING!_ The destination branch will be completely overwritten by the contents
729of the archive.
730
731**Environment**
732
733_none_
734
735**Configuration**
736
737| Option | Description |
738| ------------- | --------------------------------------------------------------------------------------- |
739| `branch` | **optional** The name of the branch to push the changes to. `gh-pages` by default. |
740| `githubOwner` | **optional** GitHub project owner, defaults to the value from the global configuration. |
741| `githubRepo` | **optional** GitHub project name, defaults to the value from the global configuration. |
742
743**Example**
744
745```yaml
746targets:
747 - name: gh-pages
748 branch: gh-pages
749```
750
751### Sentry Release Registry (`registry`)
752
753The target will update the Sentry release registry repo(https://github.com/getsentry/sentry-release-registry/) with the latest version of the
754project `craft` is used with. The release registry repository will be checked out
755locally, and then the new version file will be created there, along with the necessary
756symbolic links.
757
758Two package types are supported: "sdk" and "app". Type "sdk" means that the package
759is uploaded to one of the public registries (PyPI, NPM, Nuget, etc.), and that
760the corresponding package directory can be found inside "packages" directory of the
761release regsitry. Type "app" indicates that the package's version files are located
762in "apps" directory of the registry.
763
764**Environment**
765
766_none_
767
768**Configuration**
769
770| Option | Description |
771| ------------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
772| `type` | Type of the package: can be "sdk" or "app". |
773| `config.canonical` | Canonical name of the package that includes package registry name (e.g. NPM, PyPI) and the full package name. |
774| `urlTemplate` | **optional** URL template that will be used to generate download links for "app" package type. |
775| `linkPrereleases` | **optional** Update package versions even if the release is a preview release, "false" by default. |
776| `checksums` | **optional** A list of checksums that will be computed for matched files (see `includeNames`). Every checksum entry is an object with two attributes: algorithm (one of "sha256", "sha384", and "sha512) and format ("base64" and "hex"). |
777| `onlyIfPresent` | **optional** A file pattern. The target will be executed _only_ when the matched file is found. |
778
779**Example**
780
781```yaml
782targets:
783 - name: registry
784 type: sdk
785 config:
786 canonical: 'npm:@sentry/browser'
787
788 - name: registry
789 type: app
790 urlTemplate: 'https://example.com/{{version}}/{{file}}'
791 config:
792 canonical: 'npm:@sentry/browser'
793 checksums:
794 - algorithm: sha256
795 format: hex
796```
797
798### Cocoapods (`cocoapods`)
799
800Pushes a new podspec to the central cocoapods repository. The Podspec is fetched
801from the Github repository with the revision that is being released. No release
802assets are required for this target.
803
804**Environment**
805
806The `cocoapods` gem must be installed on the system.
807
808| Name | Description |
809| ----------------------- | ----------------------------------------- |
810| `COCOAPODS_TRUNK_TOKEN` | The access token to the cocoapods account |
811| `COCOAPODS_BIN` | **optional**. Path to `pod` executable. |
812
813**Configuration**
814
815| Option | Description |
816| ---------- | ------------------------------------------ |
817| `specPath` | Path to the Podspec file in the repository |
818
819**Example**
820
821```yaml
822targets:
823 - name: cocoapods
824 specPath: MyProject.podspec
825```
826
827### Docker (`docker`)
828
829Pulls an existing source image tagged with the revision SHA, and then pushed it
830to a new target tagged with the released version. No release
831assets are required for this target except for the source image at the provided
832source image location so it would be a good idea to add a status check that
833ensures the source image exists, otherwise `craft publish` will fail at the
834`docker pull` step, causing an interrupted publish. This is an issue for other,
835non-idempotent targets, not for the Docker target.
836
837**Environment**
838
839`docker` executable (or something equivalent) must be installed on the system.
840
841| Name | Description |
842| ----------------- | ------------------------------------------ |
843| `DOCKER_USERNAME` | The username for the Docker registry. |
844| `DOCKER_PASSWORD` | The personal access token for the account. |
845| `DOCKER_BIN` | **optional**. Path to `docker` executable. |
846
847**Configuration**
848
849| Option | Description |
850| -------------- | ------------------------------------------------------------------------ |
851| `source` | Path to the source Docker image to be pulled |
852| `sourceFormat` | Format for the source image name. Default: `{{{source}}}:{{{revision}}}` |
853| `target` | Path to the target Docker image to be pushed |
854| `targetFormat` | Format for the target image name. Default: `{{{target}}}:{{{version}}}` |
855
856**Example**
857
858```yaml
859targets:
860 - name: docker
861 source: us.gcr.io/sentryio/craft
862 target: getsentry/craft
863# Optional but strongly recommended
864statusProvider:
865 name: github
866 config:
867 contexts:
868 - Travis CI - Branch # or whatever builds and pushes your source image
869```
870
871### Ruby Gems Index (`gem`)
872
873Pushes a gem [Ruby Gems](https://rubygems.org).
874It also requires you to be logged in with `gem login`.
875
876**Environment**
877
878`gem` must be installed on the system.
879
880| Name | Description |
881| --------- | --------------------------------------------------------- |
882| `GEM_BIN` | **optional**. Path to "gem" executable. Defaults to `gem` |
883
884**Configuration**
885
886_none_
887
888**Example**
889
890```yaml
891targets:
892 - name: gem
893```
894
895### AWS Lambda Layer (`aws-lambda-layer`)
896
897The target will create a new public lambda layer in each available region with
898the extracted artifact from the artifact provider, and update the Sentry release
899registry with the new layer versions afterwards.
900
901**Environment**
902
903| Name | Description |
904| --------------------- | -------------------------------------------------------------------------- |
905| AWS_ACCESS_KEY | The access key of the AWS account to create and publish the layers. |
906| AWS_SECRET_ACCESS_KEY | The secret access key of the AWS account to create and publish the layers. |
907
908**Configuration**
909
910| Option | Description |
911| ------------------ | ------------------------------------------------------------------------------------------------------------------------------------------- |
912| linkPrereleases | **optional** Updates layer versions even if the release is a preview release, `false` by default. |
913| includeNames | **optional** Exists for all targets, [see here](##per-target-options). It must filter exactly one artifact. |
914| layerName | The name of the layer to be published. |
915| compatibleRuntimes | A list of compatible runtimes for the layer. Each compatible runtime consists on the name of the runtime and a list of compatible versions. |
916| license | The license of the layer. |
917
918**Example**
919
920```yaml
921targets:
922 - name: aws-lambda-layer
923 includeNames: /^sentry-node-serverless-\d+(\.\d+)*\.zip$/
924 layerName: SentryNodeServerlessSDK
925 compatibleRuntimes:
926 - name: node
927 versions:
928 - nodejs10.x
929 - nodejs12.x
930 license: MIT
931```
932
933## Integrating Your Project with `craft`
934
935Here is how you can integrate your GitHub project with `craft`:
936
937- Enable your project in Zeus: https://zeus.ci/settings/github/repos
938- Configure your CI systems (Travis, AppVeyor, etc.) to send build artifacts to Zeus
939 - Allow building release branches (their names follow `release/{VERSION}` by
940 default, configurable through `releaseBranchPrefix`)
941 - Add ZEUS_HOOK_BASE as protected to CI environment
942- Add `.craft.yml` configuration file to your project
943 - List there all the targets you want to publish to
944 - Configure additional options (changelog management policy, tag prefix, etc.)
945- Add a [pre-release script](#pre-release-version-bumping-script-conventions) to your project.
946- Get various [configuration tokens](#global-configuration)
947- Start releasing!
948
949## Pre-release (Version-bumping) Script: Conventions
950
951Among other actions, `craft prepare` runs an external, project-specific command
952or script that is responsible for version bumping. By default, this script
953should be located at: `./scripts/bump-version.sh`. The command can be configured
954by specifying the `preReleaseCommand` configuration option in `craft.yml`.
955
956The following requirements are on the script interface and functionality:
957
958- The script should accept at least two arguments. Craft will pass the old ("from")
959 version and the new ("to") version as the last two arguments, respectively.
960- The script must replace all relevant occurrences of the old version string
961 with the new one.
962- The script must not commit the changes made.
963- The script must not change the state of the git repository (e.g. changing branches)
964
965**Example**
966
967```bash
968#!/bin/bash
969### Example of a version-bumping script for an NPM project.
970### Located at: ./scripts/bump-version.sh
971set -eux
972OLD_VERSION="${1}"
973NEW_VERSION="${2}"
974
975# Do not tag and commit changes made by "npm version"
976export npm_config_git_tag_version=false
977npm version "${NEW_VERSION}"
978```
979
980## Post-release Script: Conventions
981
982Among other actions, `craft publish` runs an external, project-specific command
983or script that can do things like bumping the development version. By default,
984this script should be located at: `./scripts/post-release.sh`. Unlike the
985pre-release command, this script is not mandatory so if the file does not exist,
986`craft` will report this fact and then move along as usual. This command can be
987configured by specifying `postReleaseCommand` configuration option in `craft.yml`.
988
989The following requirements are on the script interface and functionality:
990
991- The script should accept at least two arguments. Craft will pass the old ("from")
992 version and the new ("to") version as the last two arguments, respectively.
993- The script is responsible for any and all `git` state management as `craft` will
994 simply exit after running this script as the final step. This means the script
995 is responsible for committing and pushing any changes that it may have made.
996
997**Example**
998
999```bash
1000#!/bin/bash
1001### Example of a dev-version-bumping script for a Python project
1002### Located at: ./scripts/post-release.sh
1003set -eux
1004OLD_VERSION="${1}"
1005NEW_VERSION="${2}"
1006
1007# Ensure master branch
1008git checkout master
1009# Advance the CalVer release by one-month and add the `.dev0` suffix
1010./scripts/bump-version.sh '' $(date -d "$(echo $NEW_VERSION | sed -e 's/^\([0-9]\{2\}\)\.\([0-9]\{1,2\}\)\.[0-9]\+$/20\1-\2-1/') 1 month" +%y.%-m.0.dev0)
1011# Only commit if there are changes, make sure to `pull --rebase` before pushing to avoid conflicts
1012git diff --quiet || git commit -anm 'meta: Bump new development version' && git pull --rebase && git push
1013```
1014
1015## Development
1016
1017### Logging Level
1018
1019Logging level for `craft` can be configured via setting `CRAFT_LOG_LEVEL`
1020environment variable.
1021
1022Accepted values are: `debug`, `success` (default), `info`, `warn`, `error`.
1023
1024### Dry-run Mode
1025
1026Dry-run mode can be enabled via setting `DRY_RUN` environment variable to any
1027truthy value (any value other than `unset`, `""`, `0`, `false` and `no`).
1028
1029In dry-run mode no destructive actions will be performed (creating branches,
1030pushing tags, committing files, etc.)
1031
1032### Sentry Support
1033
1034Errors you encounter while using Craft can be sent to Sentry. To use this feature,
1035add `CRAFT_SENTRY_DSN` variable to your environment (or "craft" configuration file) that
1036contains a Sentry project's DSN.
1037
1038For example:
1039
1040```bash
1041export CRAFT_SENTRY_DSN='https://1234@sentry.io/2345'
1042```
1043
1044### Releasing
1045
1046`craft` obviously uses `craft` for preparing and publishing new releases!