Skip to content

Commit

Permalink
Merge pull request #534 from garden-io/release-v0.9.1
Browse files Browse the repository at this point in the history
Release v0.9.1
  • Loading branch information
edvald authored Feb 13, 2019
2 parents d44f4b3 + 81143de commit d02851e
Show file tree
Hide file tree
Showing 14 changed files with 324 additions and 190 deletions.
154 changes: 70 additions & 84 deletions CHANGELOG.md

Large diffs are not rendered by default.

8 changes: 6 additions & 2 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -104,15 +104,19 @@ Our release process generates the following packages:

To make a new release, set your current working directory to the garden root directory and follow the steps below.

1. Run the release script: `./bin/release <version>`. The script does the following:
1. Run the release script: `./bin/release.tsx <minor | patch | preminor | prepatch | prerelease> [--force]`. The script does the following:
* Checks out a branch named `release-<version>`.
* Updates `package.json` and `package-lock.json` for `garden-service` and the changelog.
* Commits the changes, tags the commit and pushes the tag, triggering a CI process the creates the release artifacts.
2. Open the [Garden project on CircleCI](https://circleci.com/gh/garden-io/garden) and browse to the job marked `release-service-pkg`. Open the **Artifacts** tab and download the listed artifacts.
3. Go to our Github [Releases tab](https://github.com/garden-io/garden/releases) and click the **Draft a new release** button.
4. Fill in the **Tag version** and **Release title** fields with the new release version (same as you used for the tag).
5. Upload the downloaded artifacts.
6. Write release notes (not necessary for RCs). The notes should _at least_ contain the changelog.
6. Write release notes (not necessary for RCs). The notes should _at least_ contain the changelog. To generate a changelog for just that tag, run `git-chglog <tag-name>`.
7. Click the **Publish release** button.
8. Push the branch and make a pull request.
9. If you're making an RC, you're done! Otherwise, you need to update Homebrew package: `gulp update-brew`.

## Changelog

We keep a changelog under `CHANGELOG.md` that get's updated on every release. For pre-releases, we include every pre-release tag in that release cycle in the changelog. So if we're releasing, say, `v0.9.1-3`, the changelog will include entries for `v0.9.1-0`, `v0.9.1-1`, `v0.9.1-2`, assuming those tags exist. Once we make a proper release, we remove the pre-release tags so that the changelog only shows changes between `v0.9.0` and `v0.9.1`. A changelog with the pre-releases is of course always available in our Git history.
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ You can find the Garden documentation at [https://docs.garden.io](https://docs.g
Overview:
- [Basics](https://docs.garden.io/basics), for installation instructions, our quick start guide, and an overview of the main concepts around Garden.
- [Using Garden](https://docs.garden.io/using-garden), for features and usage, Garden configuration files, usage with remote clusters, and setting up hot reload.
- [Example Projects](https://docs.garden.io/examples) contains guides based on some of the [examples](https://github.com/garden-io/garden/tree/master/examples).
- [Example Projects](https://docs.garden.io/examples) contains guides based on some of the [examples](https://github.com/garden-io/garden/tree/v0.9.0/examples).
- [Reference](https://docs.garden.io/reference), for the glossary, commands reference, configuration files reference, and template strings reference.
- [FAQs](https://docs.garden.io/faqs).

Expand All @@ -44,7 +44,7 @@ Overview:

## Examples

There are many examples of how to use Garden in a myriad of different ways in the [examples](https://github.com/garden-io/garden/tree/master/examples) folder of our repository.
There are many examples of how to use Garden in a myriad of different ways in the [examples](https://github.com/garden-io/garden/tree/v0.9.0/examples) folder of our repository.

For written guides based on some of these examples, check out the [examples section](https://docs.garden.io/examples) of our documentation.

Expand Down
90 changes: 0 additions & 90 deletions bin/release

This file was deleted.

212 changes: 212 additions & 0 deletions bin/release.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,212 @@
#!/usr/bin/env ts-node

import * as execa from "execa"
import * as semver from "semver"
import * as inquirer from "inquirer"
import chalk from "chalk"
import parseArgs = require("minimist")
import replace = require("replace-in-file")
import deline = require("deline")
import { resolve, join } from "path"

type ReleaseType = "minor" | "patch" | "preminor" | "prepatch" | "prerelease"
const RELEASE_TYPES = ["minor", "patch", "preminor", "prepatch", "prerelease"]

/**
* Performs the following steps to prepare for a release:
* 1. Check out to a branch named release-${version}
* 2. Bump the version in garden-service/package.json and garden-service/package-lock.json.
* 5. Update the changelog.
* 6. Add and commit CHANGELOG.md, garden-service/package.json and garden-service/package-lock.json
* 7. Tag the commit.
* 8. Push the tag. This triggers CircleCI process that creates the release artifacts.
* 9. If we're making a minor release, update links to examples and re-push the tag.
*
* Usage: ./bin/release.ts <minor | patch | preminor | prepatch | prerelease> [--force]
*/
async function release() {
// Parse arguments
const argv = parseArgs(process.argv.slice(2))
const releaseType = <ReleaseType>argv._[0]
const force = argv.force
const gardenRoot = resolve(__dirname, "..")
const gardenServiceRoot = join(gardenRoot, "garden-service")

// Check if branch is clean
try {
await execa("git", ["diff", "--exit-code"], { cwd: gardenRoot })
} catch (_) {
throw new Error("Current branch has unstaged changes, aborting.")
}

if (!RELEASE_TYPES.includes(releaseType)) {
throw new Error(`Invalid release type ${releaseType}, available types are: ${RELEASE_TYPES.join(", ")}`)
}

// Bump package.json and package-lock.json version. Returns the version that was set.
const version = await execa.stdout("npm", [
"version", "--no-git-tag-version", releaseType,
], { cwd: gardenServiceRoot })

// Check if user wants to continue
const proceed = await prompt(version)
if (!proceed) {
await rollBack(gardenRoot)
return
}

// Pull remote tags
console.log("Pulling remote tags...")
await execa("git", ["fetch", "origin", "--tags"], { cwd: gardenRoot })

// Verify tag doesn't exist
const tags = (await execa.stdout("git", ["tag"], { cwd: gardenRoot })).split("\n")
if (tags.includes(version) && !force) {
await rollBack(gardenRoot)
throw new Error(`Tag ${version} already exists. Use "--force" to override.`)
}

// Checkout to a release branch
const branchName = `release-${version}`
console.log(`Checking out to branch ${branchName}...`)
await execa("git", ["checkout", "-b", branchName], { cwd: gardenRoot })

// Remove pre-release tags so they don't get included in the changelog
await stripPrereleaseTags(tags, version)

// Update changelog
console.log("Updating changelog...")
await execa("git-chglog", [
"--next-tag", version,
"--output", "CHANGELOG.md",
`..${version}`,
], { cwd: gardenRoot })

// Add and commit changes
console.log("Committing changes...")
await execa("git", [
"add",
"CHANGELOG.md", "garden-service/package.json", "garden-service/package-lock.json",
], { cwd: gardenRoot })
await execa("git", [
"commit",
"-m", `chore(release): bump version to ${version}`,
], { cwd: gardenRoot })

// Tag the commit and push the tag
console.log("Pushing tag...")
await createTag(version, gardenRoot, force)

// Reset local tag state (after stripping release tags)
await execa("git", ["fetch", "origin", "--tags"], { cwd: gardenRoot })

// For minor releases, we update links to examples in the docs so that they point to the relevant tag.
// E.g.: "github.com/garden-io/tree/v0.8.0/example/..." becomes "github.com/garden-io/tree/v0.9.0/example/..."
// Note that we do this after pushing the tag originally. This because we check that links are valid in CI
// and the check would fail if the tag hasen't been created in the first place.
if (releaseType === "minor") {
console.log("Updating links to examples and re-pushing tag...")
await updateExampleLinks(version)

// Add and commit changes to example links
await execa("git", [
"add",
"README.md", "docs",
], { cwd: gardenRoot })
await execa("git", ["commit", "--amend", "--no-edit"], { cwd: gardenRoot })

// Tag the commit and force push the tag after updating the links (this triggers another CI build)
await createTag(version, gardenRoot, true)
}

console.log(deline`
\nVersion ${chalk.bold.cyan(version)} has been ${chalk.bold("tagged")}, ${chalk.bold("committed")},
and ${chalk.bold("pushed")} to Github! 🎉\n
A CI job that creates the release artifacts is currently in process: https://circleci.com/gh/garden-io/garden\n
Please refer to our contributing docs for the next steps:
https://github.com/garden-io/garden/blob/master/CONTRIBUTING.md
`)
}

async function createTag(version: string, gardenRoot: string, force: boolean) {
// Tag the commit
const createTagArgs = ["tag", "-a", version, "-m", `chore(release): release ${version}`]
if (force) {
createTagArgs.push("-f")
}
await execa.stdout("git", createTagArgs, { cwd: gardenRoot })

// Push the tag
const pushTagArgs = ["push", "origin", version, "--no-verify"]
if (force) {
pushTagArgs.push("-f")
}
await execa("git", pushTagArgs, { cwd: gardenRoot })
}

async function updateExampleLinks(version: string) {
const options = {
files: ["docs/**/*.md", "README.md"],
from: /github\.com\/garden-io\/garden\/tree\/.*\/examples/g,
to: `github.com/garden-io/garden/tree/${version}/examples/`,
}
const changes = await replace(options)
console.log("Modified files:", changes.join(", "))
}

async function rollBack(gardenRoot: string) {
// Clean up changes to package.json and package-lock.json. This is safe since we know the branch is clean.
console.log("Undoing changes to package.json and package-lock.json")
await execa.stdout("git", [
"checkout",
"garden-service/package.json",
"garden-service/package-lock.json",
], { cwd: gardenRoot })
}

async function prompt(version: string): Promise<boolean> {
const message = deline`
Running this script will create a tag for ${chalk.bold.cyan(version)} and push it to Github.
This triggers a CI process that creates the release artifacts.\n
Are you sure you want to continue?
`
const ans = await inquirer.prompt({
name: "continue",
message,
})
return ans.continue.startsWith("y")
}

/**
* We don't include pre-release tags in the changelog except for the current release cycle.
* So if we're releasing, say, v0.9.1-3, we include the v0.9.1-0, v0.9.1-1, and v0.9.1-2 tags.
*
* Once we release v0.9.1, we remove the pre-release tags, so the changelog will only show the changes
* between v0.9.0 and v0.9.1.
*/
async function stripPrereleaseTags(tags: string[], version: string) {
const prereleaseTags = tags.filter(t => !!semver.prerelease(t))

for (const tag of prereleaseTags) {
// If we're not releasing a pre-release, we remove the tag. Or,
// if we are releasing a pre-release and the tag is not from the same cycle, we remove it.
// E.g., if the current tag is v0.5.0-2 and we're releasing v0.9.0-2, we remove it.
// If the current tag is v0.9.0-0 and we're releasing v0.9.0-2, we keep it.
if (!semver.prerelease(version) || semver.diff(version, tag) !== "prerelease") {
await execa.stdout("git", ["tag", "-d", tag])
}
}
}

(async () => {
try {
await release()
process.exit(0)
} catch (err) {
console.log(err)
process.exit(1)
}
})().catch(() => { })
4 changes: 2 additions & 2 deletions docs/examples/hello-world.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,9 @@ In this example, we'll have a practical look at the main characteristics of a Ga
- Ports, endpoints, and health check settings
- Tests

This project contains four configuration files. [This one](https://github.com/garden-io/garden/tree/master/examples/hello-world/garden.yml) for project-wide settings, and three separate ones for each of the modules: [`hello-container`](https://github.com/garden-io/garden/tree/master/examples/hello-world/services/hello-container/garden.yml), [`hello-function`](https://github.com/garden-io/garden/tree/master/examples/hello-world/services/hello-function/garden.yml), and [`hello-npm-package`](https://github.com/garden-io/garden/tree/master/examples/hello-world/libraries/hello-npm-package/garden.yml).
This project contains four configuration files. [This one](https://github.com/garden-io/garden/tree/v0.9.0/examples/hello-world/garden.yml) for project-wide settings, and three separate ones for each of the modules: [`hello-container`](https://github.com/garden-io/garden/tree/v0.9.0/examples/hello-world/services/hello-container/garden.yml), [`hello-function`](https://github.com/garden-io/garden/tree/v0.9.0/examples/hello-world/services/hello-function/garden.yml), and [`hello-npm-package`](https://github.com/garden-io/garden/tree/v0.9.0/examples/hello-world/libraries/hello-npm-package/garden.yml).

_Note: The source code for this project can be found at: [https://github.com/garden-io/garden/tree/master/examples/hello-world](https://github.com/garden-io/garden/tree/master/examples/hello-world)._
_Note: The source code for this project can be found at: [https://github.com/garden-io/garden/tree/v0.9.0/examples/hello-world](https://github.com/garden-io/garden/tree/v0.9.0/examples/hello-world)._

# Configuring dependencies

Expand Down
4 changes: 2 additions & 2 deletions docs/examples/remote-sources.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,11 @@ Important concepts:
> Remote _module_: The remote source code for a single Garden module. In this case, the `garden.yml` config file is stored in the main project repository while the module code itself is in the remote repository.
_Note: The source code for this project can be found at: [https://github.com/garden-io/garden/tree/master/examples/remote-sources](https://github.com/garden-io/garden/tree/master/examples/remote-sources)._
_Note: The source code for this project can be found at: [https://github.com/garden-io/garden/tree/v0.9.0/examples/remote-sources](https://github.com/garden-io/garden/tree/v0.9.0/examples/remote-sources)._

## About

This project is the same as the [vote example](https://github.com/garden-io/garden/tree/master/examples/vote)—except that in this case the services live in their own repositories. The repositories are:
This project is the same as the [vote example](https://github.com/garden-io/garden/tree/v0.9.0/examples/vote)—except that in this case the services live in their own repositories. The repositories are:

* [Database services](https://github.com/garden-io/garden-example-remote-sources-db-services) (contains the Postgres and Redis services)
* [Web services](https://github.com/garden-io/garden-example-remote-sources-web-services) (contains the Python Vote web service and the Node.js Result web service)
Expand Down
2 changes: 1 addition & 1 deletion docs/examples/simple-project.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ This tutorial assumes that you have already have a running [installation of Gard

## Clone the example repo

The code for this tutorial can be found in our Github repository under the [examples directory](https://github.com/garden-io/garden/tree/master/examples). We'll use the [simple-project-start](https://github.com/garden-io/garden/tree/master/examples/simple-project-start/) example and work our way from there. The final version is under [simple-project](https://github.com/garden-io/garden/tree/master/examples/simple-project).
The code for this tutorial can be found in our Github repository under the [examples directory](https://github.com/garden-io/garden/tree/v0.9.0/examples). We'll use the [simple-project-start](https://github.com/garden-io/garden/tree/v0.9.0/examples/simple-project-start/) example and work our way from there. The final version is under [simple-project](https://github.com/garden-io/garden/tree/v0.9.0/examples/simple-project).

First, let's clone the examples repo, change into the directory, and take a look inside:
```sh
Expand Down
2 changes: 1 addition & 1 deletion docs/examples/tls-project.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ This project shows how you can configure a TLS certificate to use for local deve
For the example to work you need to configure a local certificate authority (CA) on your computer for development. We'll use
[mkcert](https://github.com/FiloSottile/mkcert) for this purpose.

_Note: The source code for this project can be found at: [https://github.com/garden-io/garden/tree/master/examples/local-tls](https://github.com/garden-io/garden/tree/master/examples/local-tls)._
_Note: The source code for this project can be found at: [https://github.com/garden-io/garden/tree/v0.9.0/examples/local-tls](https://github.com/garden-io/garden/tree/v0.9.0/examples/local-tls)._

## Setup

Expand Down
2 changes: 1 addition & 1 deletion examples/remote-sources/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ Important concepts:
## About

This project is the same as the [vote example](https://github.com/garden-io/garden/tree/master/examples/vote)—except that in this case the services live in their own repositories. The repositories are:
This project is the same as the [vote example](https://github.com/garden-io/garden/tree/v0.9.0/examples/vote)—except that in this case the services live in their own repositories. The repositories are:

* [Database services](https://github.com/garden-io/garden-example-remote-sources-db-services) (contains the Postgres and Redis services)
* [Web services](https://github.com/garden-io/garden-example-remote-sources-web-services) (contains the Python Vote web service and the Node.js Result web service)
Expand Down
Loading

0 comments on commit d02851e

Please sign in to comment.