Add release automation (#346)

See `RELEASING.md` for directions
This commit is contained in:
Christian Legnitto 2019-05-11 23:51:28 -07:00 committed by GitHub
parent edd1b26d71
commit 794568e463
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
16 changed files with 254 additions and 44 deletions

View file

@ -26,15 +26,15 @@ env:
before_script:
- |
if [ "$TRAVIS_OS_NAME" = 'windows' ]; then
powershell -executionpolicy bypass -file _build/cargo-make.ps1 -version "0.15.3" -target "x86_64-pc-windows-msvc"
powershell -executionpolicy bypass -file _build/cargo-make.ps1 -version "0.19.1" -target "x86_64-pc-windows-msvc"
fi
- |
if [ "$TRAVIS_OS_NAME" = 'linux' ]; then
_build/cargo-make.sh "0.15.3" "x86_64-unknown-linux-musl"
_build/cargo-make.sh "0.19.1" "x86_64-unknown-linux-musl"
fi
- |
if [ "$TRAVIS_OS_NAME" = 'osx' ]; then
_build/cargo-make.sh "0.15.3" "x86_64-apple-darwin"
_build/cargo-make.sh "0.19.1" "x86_64-apple-darwin"
fi
script:
- cargo make workspace-ci-flow --no-workspace

View file

@ -2,16 +2,87 @@
[env]
CARGO_MAKE_EXTEND_WORKSPACE_MAKEFILE = "true"
# Run `cargo make release` to push a new minor release of every crate.
#
# Run `RELEASE_LEVEL=(patch|major|minor) cargo make release` to push a new release of every crate.
# Run `RELEASE_LEVEL=(patch|major|minor) CARGO_MAKE_WORKSPACE_SKIP_MEMBERS="crate1;crate2;" cargo make release`
# to push a new release of some crates.
#
[tasks.release]
args = ["release", "--config", "../_build/release.toml"]
condition = { env_set = [ "RELEASE_LEVEL" ] }
workspace = false
env = { "CARGO_MAKE_WORKSPACE_SKIP_MEMBERS" = "integration_tests/*" }
run_task = { name = "release-INTERNAL", fork = true }
# Run `cargo make release-patch` to push a new patch release of every crate.
[tasks.release-patch]
args = ["release", "--config", "../_build/release.toml", "patch"]
# Run `cargo make release-dry-run` to do a dry run.
[tasks.release-some]
condition = { env_set = [ "RELEASE_LEVEL", "CARGO_MAKE_WORKSPACE_SKIP_MEMBERS" ] }
workspace = false
env = { "CARGO_MAKE_WORKSPACE_SKIP_MEMBERS" = "integration_tests/*" }
run_task = { name = "release-some-INTERNAL", fork = true }
# Hack to filter out crates we do not want to release.
# See <https://github.com/sagiegurari/cargo-make/issues/212#issuecomment-481123564>
[tasks.release-INTERNAL]
private = true
condition = { env_set = [ "RELEASE_LEVEL" ] }
command = "cargo-release"
args = ["release", "--config", "${CARGO_MAKE_WORKING_DIRECTORY}/../_build/release.toml", "${RELEASE_LEVEL}"]
#
# Run `RELEASE_LEVEL=(patch|major|minor) cargo make release-dry-run` to do a dry run.
# Run `RELEASE_LEVEL=(patch|major|minor) CARGO_MAKE_WORKSPACE_SKIP_MEMBERS="crate1;crate2;" cargo make release-some-dry-run`
# to do a dry run with some crates.
#
[tasks.release-dry-run]
condition = { env_set = [ "RELEASE_LEVEL" ] }
workspace = false
env = { "CARGO_MAKE_WORKSPACE_SKIP_MEMBERS" = "integration_tests/*" }
run_task = { name = "release-dry-run-INTERNAL", fork = true }
[tasks.release-some-dry-run]
condition = { env_set = [ "CARGO_MAKE_WORKSPACE_SKIP_MEMBERS", "RELEASE_LEVEL" ] }
workspace = false
run_task = { name = "release-some-dry-run-INTERNAL", fork = true }
# Hack to filter out crates we do not want to release.
# See <https://github.com/sagiegurari/cargo-make/issues/212#issuecomment-481123564>
[tasks.release-dry-run-INTERNAL]
private = true
condition = { env_set = [ "RELEASE_LEVEL" ] }
env = { "CARGO_MAKE_WORKSPACE_SKIP_MEMBERS" = "integration_tests/*" }
description = "Run `cargo-release --dry-run` for every crate"
command = "${HOME}/src/cargo-release/target/debug/cargo-release"
args = ["release", "--config", "../_build/release.toml", "--dry-run"]
command = "cargo-release"
args = ["release", "--config", "${CARGO_MAKE_WORKING_DIRECTORY}/../_build/release.toml", "--dry-run", "${RELEASE_LEVEL}"]
#
# Run `RELEASE_LEVEL=(patch|major|minor) cargo make release-local-test` to do actually make changes locally but
# not push them up to crates.io or Github.
# Run `RELEASE_LEVEL=(patch|major|minor) cargo make release-some-local-test` to do actually make changes locally but
# not push some crates up to crates.io or Github.
#
[tasks.release-local-test]
condition = { env_set = [ "RELEASE_LEVEL" ] }
workspace = false
env = { "CARGO_MAKE_WORKSPACE_SKIP_MEMBERS" = "integration_tests/*" }
run_task = { name = "release-local-test-INTERNAL", fork = true }
[tasks.release-some-local-test]
condition = { env_set = [ "CARGO_MAKE_WORKSPACE_SKIP_MEMBERS", "RELEASE_LEVEL" ] }
workspace = false
run_task = { name = "release-some-local-test-INTERNAL", fork = true }
# Hack to filter out crates we do not want to release.
# See <https://github.com/sagiegurari/cargo-make/issues/212#issuecomment-481123564>
[tasks.release-local-test-INTERNAL]
private = true
condition = { env_set = [ "RELEASE_LEVEL" ] }
description = "Run `cargo-release` for every crate, but only make changes locally"
command = "cargo-release"
args = ["release", "--config", "${CARGO_MAKE_WORKING_DIRECTORY}/../_build/release.toml", "--no-confirm", "--skip-publish", "--skip-push", "--skip-tag", "${RELEASE_LEVEL}"]

72
RELEASING.md Normal file
View file

@ -0,0 +1,72 @@
# How to release new crate versions
## Prerequisites
We use [`cargo-make`](cargo-make) and [`cargo-release`](cargo-release) to automate crate releases. You will need to install them locally:
- `cargo install -f cargo-make`
- `cargo install -f cargo-release`
## Preparing for a release
There are two general classes of release and each require running different automation commands:
1. All public workspace crates should be released and all share the same release level ("patch", "minor", "major"). _These commands take the form `release-[whatever]`._
2. A subset of workspace crates need to be released, or not all crate releases share the same release level. _These commands start with `release-skip-[whatever]`._
## Determine new release level
For each crate, determine the desired release level (`patch`, `minor`, `major`). Set the `RELEASE_LEVEL` env variable to the desired release level.
## Determine which crates to exclude
If a subset of workspace crates need to be released, or not all crate releases share the same release level, set the `CARGO_MAKE_WORKSPACE_SKIP_MEMBERS` env
variable to filter out specific workspace crates. The value is a list of semicolon-delineated crate names or a regular expression.
**Important:** You likely want to always exclude `integration_tests/*`.
## Dry run
It is a good idea to do a dry run to sanity check what actions will be performed.
- For case #1 above, run `cargo make release-dry-run`.
If the command finishes super quickly with no output you likely did not set `RELEASE_LEVEL`.
- For case #2 above, run `cargo make release-some-dry-run`.
If the command finishes super quickly with no output you likely did not set `RELEASE_LEVEL` or `CARGO_MAKE_WORKSPACE_SKIP_MEMBERS`.
## Local test
Not everything is captured in the dry run. It is a good idea to run a local test.
In a local test, all the release actions are performed on your local checkout
but nothing is pushed to Github or crates.io.
- For case #1 above, run `cargo make release-local-test`.
If the command finishes super quickly with no output you likely did not set `RELEASE_LEVEL`.
- For case #2 above, run `cargo make release-some-local-test`.
If the command finishes super quickly with no output you likely did not set `RELEASE_LEVEL` or `CARGO_MAKE_WORKSPACE_SKIP_MEMBERS`.
After, your local git repository should have the changes ready to push to Github.
Use `git rebase -i HEAD~10` and drop the new commits.
## Release
After testing locally and via a dry run, it is time to release. A release
consists of bumping versions, starting a new changelog section, pushing a tag to Github, and updating crates.io. This should all be handled by running the automated commands.
- For case #1 above, run `cargo make release`.
If the command finishes super quickly with no output you likely did not set `RELEASE_LEVEL`.
- For case #2 above, run `cargo make release-some`.
If the command finishes super quickly with no output you likely did not set `RELEASE_LEVEL` or `CARGO_MAKE_WORKSPACE_SKIP_MEMBERS`.
[cargo-make]: https://github.com/sagiegurari/cargo-make
[cargo-release]: https://github.com/sunng87/cargo-release

View file

@ -36,15 +36,15 @@ jobs:
displayName: Query rust and cargo versions
- ${{ if eq(parameters.name, 'Linux') }}:
# Linux.
- script: _build/cargo-make.sh "0.15.3" "x86_64-unknown-linux-musl"
- script: _build/cargo-make.sh "0.19.1" "x86_64-unknown-linux-musl"
displayName: Install cargo-make binary
- ${{ if eq(parameters.name, 'macOS') }}:
# Mac.
- script: _build/cargo-make.sh "0.15.3" "x86_64-apple-darwin"
- script: _build/cargo-make.sh "0.19.1" "x86_64-apple-darwin"
displayName: Install cargo-make binary
- ${{ if eq(parameters.name, 'Windows') }}:
# Windows.
- script: powershell -executionpolicy bypass -file _build/cargo-make.ps1 -version "0.15.3" -target "x86_64-pc-windows-msvc"
- script: powershell -executionpolicy bypass -file _build/cargo-make.ps1 -version "0.19.1" -target "x86_64-pc-windows-msvc"
displayName: Install cargo-make binary
- script: cargo make workspace-ci-flow --no-workspace
env: { CARGO_MAKE_RUN_CODECOV: true }

View file

@ -4,5 +4,5 @@ pro-release-commit-message = "Bump {{crate_name}} version to {{next_version}}"
tag-message = "Release {{crate_name}} {{version}}"
upload-doc = false
pre-release-replacements = [
{file="CHANGELOG.md", search="# master", replace="# master\n\n- No changes yet\n\n# [[{{version}}] {{date}}](https://github.com/graphql-rust/juniper/releases/tag/{{crate_name}}-{{version}})"},
{file="CHANGELOG.md", search="# master", replace="# master\n\n- Compatibility with the latest `juniper`.\n\n# [[{{version}}] {{date}}](https://github.com/graphql-rust/juniper/releases/tag/{{crate_name}}-{{version}})"},
]

View file

@ -1,4 +1,8 @@
jobs:
###################################################
# Formatting
###################################################
- job: check_formatting
displayName: Check formatting
pool:
@ -12,6 +16,10 @@ jobs:
$HOME/.cargo/bin/cargo fmt -- --check
displayName: Run rustfmt
###################################################
# Book
###################################################
- job: run_book_tests
displayName: Book code example tests
pool:
@ -42,6 +50,10 @@ jobs:
- script: |
./docs/book/ci-build.sh master
###################################################
# Main Builds
###################################################
- template: _build/azure-pipelines-template.yml
parameters:
name: Linux
@ -56,3 +68,38 @@ jobs:
parameters:
name: Windows
vmImage: vs2017-win2016
###################################################
# Releases
###################################################
- job: check_release_automation
displayName: Check release automation
pool:
vmImage: ubuntu-16.04
steps:
- script: |
curl https://sh.rustup.rs -sSf | sh -s -- -y
displayName: Install stable Rust
- script: |
_build/cargo-make.sh "0.19.1" "x86_64-unknown-linux-musl"
displayName: Install cargo-make binary
- script: |
$HOME/.cargo/bin/cargo install cargo-release
displayName: Install cargo-release binary
- script: |
git config --local user.name "Release Test Bot"
git config --local user.email "juniper@example.com"
displayName: Set up git
- script: |
RELEASE_LEVEL="minor" "$HOME/.cargo/bin/cargo" make release-dry-run
displayName: Dry run mode
- script: |
RELEASE_LEVEL="minor" "$HOME/.cargo/bin/cargo" make release-local-test
displayName: Local test mode
- script: |
git --no-pager log -p HEAD...HEAD~20
displayName: Echo local changes
- script: |
cargo make workspace-ci-flow --no-workspace
displayName: Make sure build and tests still work

View file

@ -7,9 +7,13 @@ args = ["test", "--verbose"]
[tasks.release]
disabled = true
[tasks.release-patch]
[tasks.release-some]
disabled = true
[tasks.release-local-test]
disabled = true
[tasks.release-some-local-test]
disabled = true
[tasks.release-dry-run]
disabled = true
[tasks.release-some-dry-run]
disabled = true

View file

@ -1,8 +1,11 @@
[tasks.release]
args = ["release"]
# This is needed as the release config is at a different path than the top-level
# release config.
[tasks.release-patch]
args = ["release", "patch"]
[tasks.release-INTERNAL]
args = ["release", "--config", "${CARGO_MAKE_WORKING_DIRECTORY}/release.toml", "${RELEASE_LEVEL}"]
[tasks.release-dry-run]
args = ["release", "--dry-run"]
[tasks.release-dry-run-INTERNAL]
args = ["release", "--config", "${CARGO_MAKE_WORKING_DIRECTORY}/release.toml", "--dry-run", "${RELEASE_LEVEL}"]
[tasks.release-local-test-INTERNAL]
args = ["release", "--config", "${CARGO_MAKE_WORKING_DIRECTORY}/release.toml", "--no-confirm", "--skip-publish", "--skip-push", "--skip-tag", "${RELEASE_LEVEL}"]

View file

@ -4,12 +4,21 @@ pro-release-commit-message = "Bump {{crate_name}} version to {{next_version}}"
tag-message = "Release {{crate_name}} {{version}}"
upload-doc = false
pre-release-replacements = [
# Juniper's changelog
{file="CHANGELOG.md", search="# master", replace="# master\n\n- No changes yet\n\n# [[{{version}}] {{date}}](https://github.com/graphql-rust/juniper/releases/tag/{{crate_name}}-{{version}})"},
{file="../integration_tests/juniper_tests/Cargo.toml", search="juniper = { version = \"0.11.0\"", replace="juniper = { version = \"{{version}}\""},
{file="../juniper_hyper/Cargo.toml", search="juniper = { version = \"0.11.0\"", replace="juniper = { version = \"{{version}}\""},
{file="../juniper_iron/Cargo.toml", search="juniper = { version = \"0.11.0\"", replace="juniper = { version = \"{{version}}\""},
{file="../juniper_rocket/Cargo.toml", search="juniper = { version = \"0.11.0\"", replace="juniper = { version = \"{{version}}\""},
{file="../juniper_tests/Cargo.toml", search="juniper = { version = \"0.11.0\"", replace="juniper = { version = \"{{version}}\""},
{file="../juniper_warp/Cargo.toml", search="juniper = { version = \"0.11.0\"", replace="juniper = { version = \"{{version}}\""},
{file="release.toml", search="0.11.0", replace="{{version}}"},
# Tests.
{file="../integration_tests/juniper_tests/Cargo.toml", search="juniper = \\{ version = \"[^\"]+\"", replace="juniper = { version = \"{{version}}\""},
# Hyper
{file="../juniper_hyper/Cargo.toml", search="juniper = \\{ version = \"[^\"]+\"", replace="juniper = { version = \"{{version}}\""},
{file="../juniper_hyper/Cargo.toml", search="\\[dev-dependencies\\.juniper\\]\nversion = \"[^\"]+\"", replace="[dev-dependencies.juniper]\nversion = \"{{version}}\""},
# Iron
{file="../juniper_iron/Cargo.toml", search="juniper = \\{ version = \"[^\"]+\"", replace="juniper = { version = \"{{version}}\""},
{file="../juniper_iron/Cargo.toml", search="\\[dev-dependencies\\.juniper\\]\nversion = \"[^\"]+\"", replace="[dev-dependencies.juniper]\nversion = \"{{version}}\""},
# Rocket
{file="../juniper_rocket/Cargo.toml", search="juniper = \\{ version = \"[^\"]+\"", replace="juniper = { version = \"{{version}}\""},
{file="../juniper_rocket/Cargo.toml", search="\\[dev-dependencies\\.juniper\\]\nversion = \"[^\"]+\"", replace="[dev-dependencies.juniper]\nversion = \"{{version}}\""},
# Warp
{file="../juniper_warp/Cargo.toml", search="juniper = \\{ version = \"[^\"]+\"", replace="juniper = { version = \"{{version}}\""},
{file="../juniper_warp/Cargo.toml", search="\\[dev-dependencies\\.juniper\\]\nversion = \"[^\"]+\"", replace="[dev-dependencies.juniper]\nversion = \"{{version}}\""},
]

View file

@ -1,8 +1,11 @@
[tasks.release]
args = ["release"]
# This is needed as the release config is at a different path than the top-level
# release config.
[tasks.release-patch]
args = ["release", "patch"]
[tasks.release-INTERNAL]
args = ["release", "--config", "${CARGO_MAKE_WORKING_DIRECTORY}/release.toml", "${RELEASE_LEVEL}"]
[tasks.release-dry-run]
args = ["release", "--dry-run"]
[tasks.release-dry-run-INTERNAL]
args = ["release", "--config", "${CARGO_MAKE_WORKING_DIRECTORY}/release.toml", "--dry-run", "${RELEASE_LEVEL}"]
[tasks.release-local-test-INTERNAL]
args = ["release", "--config", "${CARGO_MAKE_WORKING_DIRECTORY}/release.toml", "--no-confirm", "--skip-publish", "--skip-push", "--skip-tag", "${RELEASE_LEVEL}"]

View file

@ -4,6 +4,5 @@ pro-release-commit-message = "Bump {{crate_name}} version to {{next_version}}"
tag-message = "Release {{crate_name}} {{version}}"
upload-doc = false
pre-release-replacements = [
{file="../juniper/Cargo.toml", search="juniper_codegen = { version = \"0.11.0\"", replace="juniper_codegen = { version = \"{{version}}\""},
{file="release.toml", search="0.11.0", replace="{{version}}"},
{file="../juniper/Cargo.toml", search="juniper_codegen = \\{ version = \"[^\"]+\"", replace="juniper_codegen = { version = \"{{version}}\""},
]

View file

@ -1,5 +1,7 @@
# master
- Compatibility with the latest `juniper`.
# 0.2.0 [2018-12-18]
## Breaking changes

View file

@ -1,6 +1,6 @@
# master
- No changes yet
- Compatibility with the latest `juniper`.
# [0.3.0] 2018-12-17

View file

@ -1,6 +1,6 @@
# master
- No changes yet
- Compatibility with the latest `juniper`.
# [0.2.0] 2018-12-17

View file

@ -1,6 +1,6 @@
# master
- No changes yet
- Compatibility with the latest `juniper`.
# [0.2.0] 2018-12-17

View file

@ -10,7 +10,7 @@ edition = "2018"
[dependencies]
warp = "0.1.8"
juniper = { path = "../juniper", version = "0.11.0", default-features = false }
juniper = { version = "0.11.0", path = "../juniper", default-features = false }
serde_json = "1.0.24"
serde_derive = "1.0.75"
failure = "0.1.2"
@ -19,7 +19,7 @@ serde = "1.0.75"
tokio-threadpool = "0.1.7"
[dev-dependencies]
juniper = { path = "../juniper", version = "0.11.0", features = ["expose-test-schema", "serde_json"] }
juniper = { version = "0.11.0", path = "../juniper", features = ["expose-test-schema", "serde_json"] }
env_logger = "0.5.11"
log = "0.4.3"
percent-encoding = "1.0"