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
|
14 | then 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 |
|
64 | The tool is distributed as an NPM package and can be installed via `npm` or `yarn`:
|
65 |
|
66 | ```bash
|
67 | yarn global add @sentry/craft
|
68 |
|
69 | # Or (not preferred):
|
70 |
|
71 | npm install -g @sentry/craft
|
72 | ```
|
73 |
|
74 | ## Usage
|
75 |
|
76 | ```plain
|
77 | $ craft -h
|
78 | craft <command>
|
79 |
|
80 | Commands:
|
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 |
|
85 | Options:
|
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 |
|
101 | Global configuration for `craft` can be done either by using environment variables
|
102 | or by adding values to a configuration file (see below).
|
103 |
|
104 | In either case, at least the following two values must be configured in order
|
105 | for 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 |
|
119 | Additional configuration may be required when publishing to specific
|
120 | targets (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
|
125 | following 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 |
|
133 | The above locations will be checked in the order specified above, with values
|
134 | found in one location overwriting anything found in previous locations. In other
|
135 | words, environment variables will take precedence over either configuration
|
136 | file, and the project-specific file will take precedence over the file in
|
137 | `$HOME`.
|
138 |
|
139 | The files must be written in shell (`sh`/`bash`) format. Leading `export` is allowed.
|
140 |
|
141 | Example:
|
142 |
|
143 | ```sh
|
144 | # ~/.craft.env
|
145 | GITHUB_TOKEN=token123
|
146 | export NUGET_API_TOKEN=abcdefgh
|
147 | ```
|
148 |
|
149 | ## Workflow
|
150 |
|
151 | ### `craft prepare`: Preparing a New Release
|
152 |
|
153 | This command will create a new release branch, check the changelog entries,
|
154 | run a version-bumping script, and push the new branch to GitHub.
|
155 |
|
156 | ```plain
|
157 | craft prepare NEW-VERSION
|
158 |
|
159 | 🚢 Prepare a new release branch
|
160 |
|
161 | Positionals:
|
162 | NEW-VERSION The new version you want to release [string] [required]
|
163 |
|
164 | Options:
|
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 |
|
177 | The command will find a release branch for the provided version (tag) and
|
178 | publish the existing artifacts from the configured artifact provider to selected targets.
|
179 |
|
180 | ```plain
|
181 | craft publish NEW-VERSION
|
182 |
|
183 | 🛫 Publish artifacts
|
184 |
|
185 | Positionals:
|
186 | NEW-VERSION Version to publish [string] [required]
|
187 |
|
188 | Options:
|
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 |
|
207 | Let's imagine we want to release a new version of our package, and the version
|
208 | in question is `1.2.3`.
|
209 |
|
210 | We run `prepare` command first:
|
211 |
|
212 | `$ craft prepare 1.2.3`
|
213 |
|
214 | After 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`),
|
216 | commits the changes made by the script, and then pushes the new branch to
|
217 | GitHub. At this point CI systems kick in, and the results of those builds, as
|
218 | well as built artifacts (binaries, NPM archives, Python wheels) are gradually
|
219 | uploaded to Zeus.
|
220 |
|
221 | To publish the built artifacts we run `publish`:
|
222 |
|
223 | `$ craft publish 1.2.3`
|
224 |
|
225 | This command will find our release branch (`release/1.2.3`), check the build
|
226 | status of the respective git revision in Zeus, and then publish available
|
227 | artifacts to configured targets (for example, to GitHub and NPM in the case of
|
228 | Craft).
|
229 |
|
230 | ## Configuration File: `.craft.yml`
|
231 |
|
232 | Project configuration for `craft` is stored in `.craft.yml` configuration file,
|
233 | located in the project root.
|
234 |
|
235 | ### GitHub project
|
236 |
|
237 | One of the required settings you need to specify is GitHub project parameters. For example:
|
238 |
|
239 | ```yaml
|
240 | github:
|
241 | owner: getsentry
|
242 | repo: sentry-javascript
|
243 | ```
|
244 |
|
245 | ### Pre-release Command
|
246 |
|
247 | This command will run on your newly created release branch as part of `prepare`
|
248 | command. By default, it is set to `bash scripts/bump-version.sh`. Please refer
|
249 | to the [Pre-release version bumping script conventions section](#pre-release-version-bumping-script-conventions)
|
250 | for more details.
|
251 |
|
252 | ```yaml
|
253 | preReleaseCommand: bash scripts/bump-version.sh
|
254 | ```
|
255 |
|
256 | ### Post-release Command
|
257 |
|
258 | This 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
|
260 | missing though, as this may not be needed by all projects. Please refer to the
|
261 | [Post-release script conventions section](#post-release-script-conventions)
|
262 | for more details.
|
263 |
|
264 | ```yaml
|
265 | postReleaseCommand: bash scripts/post-release.sh
|
266 | ```
|
267 |
|
268 | ### Release Branch Name
|
269 |
|
270 | This overrides the prefix for the release branch name. The full branch name used
|
271 | for a release is `{releaseBranchPrefix}/{version}`. The prefix defaults to
|
272 | `"release"`.
|
273 |
|
274 | ```yaml
|
275 | releaseBranchPrefix: 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 |
|
283 | In `simple` mode, `craft prepare` will remind you to add a changelog entry to the
|
284 | changelog file (`CHANGELOG.md` by default).
|
285 |
|
286 | In `auto` mode, `craft prepare` will use the following logic:
|
287 |
|
288 | 1. If there's already an entry for the given version, use that
|
289 | 2. Else if there is an entry named `Unreleased`, rename that to the given
|
290 | version
|
291 | 3. 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
|
304 | changelog: CHANGES
|
305 | changelogPolicy: 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
|
323 | changelog: CHANGES
|
324 | changelogPolicy: 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 |
|
339 | Additionally, `.craft.yml` is used for listing targets where you want to
|
340 | publish your new release.
|
341 |
|
342 | ### Minimal Version
|
343 |
|
344 | It is possible to specify minimal `craft` version that is required to work with
|
345 | your configuration.
|
346 |
|
347 | **Example:**
|
348 |
|
349 | ```yaml
|
350 | minVersion: '0.5.0'
|
351 | ```
|
352 |
|
353 | ### Required Files
|
354 |
|
355 | You can provide a list of patterns for files that _have to be_ available before
|
356 | proceeding with publishing. In other words, for every pattern in the given list
|
357 | there has to be a file present that matches that pattern. This might be helpful
|
358 | to ensure that we're not trying to do an incomplete release.
|
359 |
|
360 | **Example:**
|
361 |
|
362 | ```yaml
|
363 | requireNames:
|
364 | - /^sentry-craft.*\.tgz$/
|
365 | - /^gh-pages.zip$/
|
366 | ```
|
367 |
|
368 | ## Status Provider
|
369 |
|
370 | You can configure which status providers `craft` will use to check for your build status.
|
371 | By default, it will take Zeus but you can also use GitHub directly.
|
372 | This 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
|
384 | statusProvider:
|
385 | name: github
|
386 | config:
|
387 | contexts:
|
388 | - Travis CI - Branch
|
389 | ```
|
390 |
|
391 | ## Artifact Provider
|
392 |
|
393 | You can configure which artifact providers `craft` will use to fetch artifacts from.
|
394 | By default, Zeus is used, but in case you don't need use any artifacts in your
|
395 | project, 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
|
406 | artifactProvider:
|
407 | name: none
|
408 | ```
|
409 |
|
410 | ### Using Github Actions with Github Artifact Provider
|
411 |
|
412 | When using Github Action you can use the Github Artifact Provider for managing your release artifacts.
|
413 | The way it works is simple, use the official GHA `actions/upload-artifact@v2` action to upload your assets.
|
414 | Craft can work with them and use it instead of Zeus.
|
415 | Here 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 |
|
428 | A 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 |
|
435 | The configuration specifies which release targets to run for the repository. To
|
436 | run more targets, list the target identifiers under the `targets` key in
|
437 | `.craft.yml`.
|
438 |
|
439 | **Example:**
|
440 |
|
441 | ```yaml
|
442 | targets:
|
443 | - name: github
|
444 | - name: npm
|
445 | ```
|
446 |
|
447 | ### Per-target options
|
448 |
|
449 | The 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 |
|
456 | If neither option is included, all artifacts for the release will be processed by the target.
|
457 |
|
458 | **Example:**
|
459 |
|
460 | ```yaml
|
461 | targets:
|
462 | - name: github
|
463 | includeNames: /^.*\.exe$/
|
464 | excludeNames: /^test.exe$/
|
465 | ```
|
466 |
|
467 | ### GitHub (`github`)
|
468 |
|
469 | Create a release on Github. If a Markdown changelog is present in the
|
470 | repository, this target tries to read the release name and description from the
|
471 | changelog. Otherwise, defaults to the tag name and tag's commit message.
|
472 |
|
473 | If `previewReleases` is set to `true` (which is the default), the release
|
474 | created on GitHub will be marked as a pre-release version if the release name
|
475 | contains 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
|
495 | targets:
|
496 | - name: github
|
497 | tagPrefix: v
|
498 | previewReleases: false
|
499 | annotatedTag: false
|
500 | ```
|
501 |
|
502 | ### NPM (`npm`)
|
503 |
|
504 | Releases an NPM package to the public registry. This requires a package tarball
|
505 | generated by `npm pack` in the artifacts. The file will be uploaded to the
|
506 | registry with `npm publish`, or with `yarn publish` if `npm` is not found. This
|
507 | requires NPM to be authenticated with sufficient permissions to publish the package.
|
508 |
|
509 | **Environment**
|
510 |
|
511 | The `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
|
531 | targets:
|
532 | - name: npm
|
533 | access: public
|
534 | ```
|
535 |
|
536 | ### Python Package Index (`pypi`)
|
537 |
|
538 | Uploads source dists and wheels to the Python Package Index via [twine](https://pypi.org/project/twine/).
|
539 | The source code bundles and/or wheels must be in the release assets.
|
540 |
|
541 | **Environment**
|
542 |
|
543 | The `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
|
558 | targets:
|
559 | - name: pypi
|
560 | ```
|
561 |
|
562 | ### Homebrew (`brew`)
|
563 |
|
564 | Pushes a new or updated homebrew formula to a brew tap repository. The formula
|
565 | is committed directly to the master branch of the tap on GitHub, therefore the
|
566 | bot needs rights to commit to `master` on that repository. Therefore, formulas
|
567 | on `homebrew/core` are not supported, yet.
|
568 |
|
569 | The tap is configured with the mandatory `tap` parameter in the same format as
|
570 | the `brew` utility. A tap `<org>/<name>` will expand to the GitHub repository
|
571 | `github.com:<org>/homebrew-<name>`.
|
572 |
|
573 | The formula contents are given as configuration value and can be interpolated
|
574 | with Mustache template syntax (`{{ variable }}`). The interpolation context
|
575 | contains 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
|
600 | targets:
|
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 |
|
622 | Uploads packages to [NuGet](https://www.nuget.org/) via [.NET Core](https://github.com/dotnet/core).
|
623 | By default, `craft` publishes all packages with `.nupkg` extension.
|
624 |
|
625 | **Environment**
|
626 |
|
627 | The `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
|
641 | targets:
|
642 | - name: nuget
|
643 | ```
|
644 |
|
645 | ### Rust Crates (`crates`)
|
646 |
|
647 | Publishes a single Rust package or entire workspace on the public crate registry
|
648 | ([crates.io](https://crates.io)). If the workspace contains multiple crates,
|
649 | they 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
|
669 | targets:
|
670 | - name: crates
|
671 | noDevDeps: false
|
672 | ```
|
673 |
|
674 | ### Google Cloud Storage (`gcs`)
|
675 |
|
676 | Uploads artifacts to a bucket in Google Cloud Storage.
|
677 |
|
678 | The 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 |
|
685 | Google 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 |
|
692 | If 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
|
708 | targets:
|
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 |
|
720 | Extracts an archive with static assets and pushes them to the specified git
|
721 | branch (`gh-pages` by default). Thus, it can be used to publish documentation
|
722 | or any other assets to [GitHub Pages](https://pages.github.com/), so they will be later automatically rendered
|
723 | by GitHub.
|
724 |
|
725 | By default, this target will look for an artifact named `gh-pages.zip`, extract it,
|
726 | and commit its contents to `gh-pages` branch.
|
727 |
|
728 | _WARNING!_ The destination branch will be completely overwritten by the contents
|
729 | of 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
|
746 | targets:
|
747 | - name: gh-pages
|
748 | branch: gh-pages
|
749 | ```
|
750 |
|
751 | ### Sentry Release Registry (`registry`)
|
752 |
|
753 | The target will update the Sentry release registry repo(https://github.com/getsentry/sentry-release-registry/) with the latest version of the
|
754 | project `craft` is used with. The release registry repository will be checked out
|
755 | locally, and then the new version file will be created there, along with the necessary
|
756 | symbolic links.
|
757 |
|
758 | Two package types are supported: "sdk" and "app". Type "sdk" means that the package
|
759 | is uploaded to one of the public registries (PyPI, NPM, Nuget, etc.), and that
|
760 | the corresponding package directory can be found inside "packages" directory of the
|
761 | release regsitry. Type "app" indicates that the package's version files are located
|
762 | in "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
|
782 | targets:
|
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 |
|
800 | Pushes a new podspec to the central cocoapods repository. The Podspec is fetched
|
801 | from the Github repository with the revision that is being released. No release
|
802 | assets are required for this target.
|
803 |
|
804 | **Environment**
|
805 |
|
806 | The `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
|
822 | targets:
|
823 | - name: cocoapods
|
824 | specPath: MyProject.podspec
|
825 | ```
|
826 |
|
827 | ### Docker (`docker`)
|
828 |
|
829 | Pulls an existing source image tagged with the revision SHA, and then pushed it
|
830 | to a new target tagged with the released version. No release
|
831 | assets are required for this target except for the source image at the provided
|
832 | source image location so it would be a good idea to add a status check that
|
833 | ensures 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,
|
835 | non-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
|
859 | targets:
|
860 | - name: docker
|
861 | source: us.gcr.io/sentryio/craft
|
862 | target: getsentry/craft
|
863 | # Optional but strongly recommended
|
864 | statusProvider:
|
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 |
|
873 | Pushes a gem [Ruby Gems](https://rubygems.org).
|
874 | It 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
|
891 | targets:
|
892 | - name: gem
|
893 | ```
|
894 |
|
895 | ### AWS Lambda Layer (`aws-lambda-layer`)
|
896 |
|
897 | The target will create a new public lambda layer in each available region with
|
898 | the extracted artifact from the artifact provider, and update the Sentry release
|
899 | registry 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
|
921 | targets:
|
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 |
|
935 | Here 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 |
|
951 | Among other actions, `craft prepare` runs an external, project-specific command
|
952 | or script that is responsible for version bumping. By default, this script
|
953 | should be located at: `./scripts/bump-version.sh`. The command can be configured
|
954 | by specifying the `preReleaseCommand` configuration option in `craft.yml`.
|
955 |
|
956 | The 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
|
971 | set -eux
|
972 | OLD_VERSION="${1}"
|
973 | NEW_VERSION="${2}"
|
974 |
|
975 | # Do not tag and commit changes made by "npm version"
|
976 | export npm_config_git_tag_version=false
|
977 | npm version "${NEW_VERSION}"
|
978 | ```
|
979 |
|
980 | ## Post-release Script: Conventions
|
981 |
|
982 | Among other actions, `craft publish` runs an external, project-specific command
|
983 | or script that can do things like bumping the development version. By default,
|
984 | this script should be located at: `./scripts/post-release.sh`. Unlike the
|
985 | pre-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
|
987 | configured by specifying `postReleaseCommand` configuration option in `craft.yml`.
|
988 |
|
989 | The 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
|
1003 | set -eux
|
1004 | OLD_VERSION="${1}"
|
1005 | NEW_VERSION="${2}"
|
1006 |
|
1007 | # Ensure master branch
|
1008 | git 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
|
1012 | git diff --quiet || git commit -anm 'meta: Bump new development version' && git pull --rebase && git push
|
1013 | ```
|
1014 |
|
1015 | ## Development
|
1016 |
|
1017 | ### Logging Level
|
1018 |
|
1019 | Logging level for `craft` can be configured via setting `CRAFT_LOG_LEVEL`
|
1020 | environment variable.
|
1021 |
|
1022 | Accepted values are: `debug`, `success` (default), `info`, `warn`, `error`.
|
1023 |
|
1024 | ### Dry-run Mode
|
1025 |
|
1026 | Dry-run mode can be enabled via setting `DRY_RUN` environment variable to any
|
1027 | truthy value (any value other than `unset`, `""`, `0`, `false` and `no`).
|
1028 |
|
1029 | In dry-run mode no destructive actions will be performed (creating branches,
|
1030 | pushing tags, committing files, etc.)
|
1031 |
|
1032 | ### Sentry Support
|
1033 |
|
1034 | Errors you encounter while using Craft can be sent to Sentry. To use this feature,
|
1035 | add `CRAFT_SENTRY_DSN` variable to your environment (or "craft" configuration file) that
|
1036 | contains a Sentry project's DSN.
|
1037 |
|
1038 | For example:
|
1039 |
|
1040 | ```bash
|
1041 | export CRAFT_SENTRY_DSN='https://1234@sentry.io/2345'
|
1042 | ```
|
1043 |
|
1044 | ### Releasing
|
1045 |
|
1046 | `craft` obviously uses `craft` for preparing and publishing new releases!
|