Skip to content

Commit

Permalink
feat: generate homebrew formula on publish
Browse files Browse the repository at this point in the history
Note: This will not work until we cut another release, since the
formula relies on a fix in a prior commit to work properly.
  • Loading branch information
edvald committed Jun 18, 2018
1 parent 74bdead commit 72c4b4d
Show file tree
Hide file tree
Showing 10 changed files with 187 additions and 100 deletions.
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,9 @@ src/**/*.js
src/**/*.map
src/**/*.d.ts
static/bin/garden.js
support/**/*.js
support/**/*.map
support/**/*.d.ts
test/**/*.js
test/**/*.map
*.tgz
60 changes: 7 additions & 53 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,7 @@ All that said, Garden can already be highly useful if the following applies to y
* **You keep all your services in a single repository** _(multi-repo support coming soon!)._
* **You really don't want to spend your precious hours building your own developer tooling!**

If that sounds right for you, please give it a go and don't hesitate to report issues or come right over
to our [Gitter](https://gitter.im/garden-io/Lobby#) for a chat!
If that sounds right for you, please give it a go and don't hesitate to report issues.


## Features
Expand All @@ -41,60 +40,15 @@ Garden is also designed to be pluggable and modular, with Kubernetes being just
Over time we will add native support for a variety of platforms, including AWS (Lambda, ECS, Fargate and more),
GCP, Heroku, OpenFaaS... and the list will continue growing.

Please read the [Motivation](https://docs.garden.io/introduction/motivation) section in our documentation
for a brief discussion on why we're building Garden.

## Setup

### Dependencies
## Usage

You need to set up the following on your local machine to use garden:
* Node.js >= 8.x
* Docker
* Git
* rsync
* [Watchman](https://facebook.github.io/watchman/docs/install.html)
* Local installation of Kubernetes

To install Kubernetes, we recommend [Docker for Mac/Windows (edge version)](https://docs.docker.com/engine/installation/)
on Mac/Windows, and you can use [Minikube](https://github.com/kubernetes/minikube) on any supported platform.
You'll just need to configure a [kubectl context](https://kubernetes.io/docs/reference/kubectl/cheatsheet/#kubectl-context-and-configuration)
to point to your local instance.

<!--- TODO: explain kubectl contexts somewhere in more detail --->

On Mac, we recommend using Homebrew on Mac to install everything except Docker, but use whatever works for you!

Note that you need to install the _edge version_ of Docker for Mac/Windows in
order to enable Kubernetes support. Once installed, you need to open the
Docker preferences, go to the Kubernetes section, tick `Enable Kubernetes` and
save. For more information, see [here for Mac](https://docs.docker.com/docker-for-mac/kubernetes/)
or [here for Windows](https://docs.docker.com/docker-for-windows/kubernetes/).

### Installation

Once you have the above dependencies set up, simply run

npm install -g garden-cli

Then go on to our [getting started guide](docs/introduction/getting-started.md), or try out the simple hello-world
example below to kick things off.


## Examples

The `examples/` directory contains usage examples for the framework. You might want to start with
the `hello-world` example project, to see an example of basic build, deployment and interaction
flows. Take a look around the projects, taking special note of the `garden.yml` files -
it's pretty straightforward, we promise :)

To spin it up, `cd` to any of the directories under `examples/` and run:

garden deploy

Once you've deployed the `hello-world` project, you can try querying the `/hello` endpoint:

garden call hello-container/hello

For more details, please head over to our [getting started guide](docs/introduction/getting-started.md).
Head over to our [Getting Started guide](https://docs.garden.io/introduction/getting-started) for details
on how to set up and use Garden, or look through our [Simple Project](https://docs.garden.io/examples/simple-project)
guide to get a quick sense of how it works.


## Contributing
Expand Down
8 changes: 6 additions & 2 deletions docs/guides/minikube.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,13 @@ Garden can be used with [Minikube](https://github.com/kubernetes/minikube) on su

For Minikube installation instructions, please see the
[official guide](https://github.com/kubernetes/minikube#installation).

You'll likely also need to install a driver to run the Minikube VM, please follow the
[instructions here](https://github.com/kubernetes/minikube/blob/master/docs/drivers.md#hyperkit-driver)
and note the name of the driver.
[instructions here](https://github.com/kubernetes/minikube/blob/master/docs/drivers.md)
and note the name of the driver you use. The driver you choose will likely vary depending on your
OS/platform. We recommend [hyperkit](https://github.com/kubernetes/minikube/blob/master/docs/drivers.md#hyperkit-driver)
for macOS and [kvm2](https://github.com/kubernetes/minikube/blob/master/docs/drivers.md#kvm2-driver) on most Linux
platforms.

Once Minikube and the appropriate driver for your OS is installed, you can start it by running:

Expand Down
95 changes: 52 additions & 43 deletions docs/introduction/getting-started.md
Original file line number Diff line number Diff line change
@@ -1,73 +1,82 @@
# Getting Started

This guide will walk you through setting up the Garden framework.
This guide will walk you through setting up the Garden framework.

## Install dependencies

You need the following dependencies on your local machine to use Garden:
* Node.js >= 8.x
* [Docker](https://docs.docker.com/)
* Git
* rsync
* [Watchman](https://facebook.github.io/watchman/docs/install.html)
* [Helm](https://github.com/kubernetes/helm)
* Local installation of Kubernetes
## Installation

### OSX
### macOS

#### Step 1: Docker and local Kubernetes
To install Docker and Kubernetes, we recommend [Docker for Mac (edge version)](https://docs.docker.com/engine/installation/).
For Mac, we recommend the following steps to install Garden. You can also follow the manual installation
steps below if you prefer.

_Note: you need to install the _edge version_ of Docker for Mac in
order to enable Kubernetes support._
#### Step 1: Install homebrew

Once installed, open the
Docker preferences, go to the Kubernetes section, tick `Enable Kubernetes` and
save.
If you haven't already set up homebrew, please follow [their instructions](https://brew.sh/) to set it up.

Alternatively, you can use [Minikube](../guides/minikube.md) on any supported platform.
#### Step 2: Docker and local Kubernetes
To install Docker, Kubernetes and kubectl, we strongly recommend Docker for Mac (edge version).

#### Step 2: Other dependencies
For installing the other dependencies, we recommend using Homebrew.
_Note: you need to install the **edge version** of Docker for Mac in
order to enable Kubernetes support._

### Linux
Once installed, open the Docker for Mac preferences, go to the Kubernetes section,
tick `Enable Kubernetes` and save. Please refer to their
[installation guide](https://docs.docker.com/engine/installation/) for details.

#### Step 1: Docker
To install Docker, please follow the instructions in the [official documentation](https://docs.docker.com/install/linux/docker-ce/ubuntu/).
Alternatively, you can use Minikube. We generally find it less stable and more hassle to
configure and use, but we do fully support it on Mac if you have it running. Please look at our
[Minikube guide](../guides/minikube.md) for details.

#### Step 2: Local Kubernetes
For local Kubernetes, you can use Minikube. Please see the
[official installation guide](https://github.com/kubernetes/minikube#installation) for instructions.

You'll likely also need to install a driver to run the Minikube VM. Please follow the
[instructions here](https://github.com/kubernetes/minikube/blob/master/docs/drivers.md#hyperkit-driver),
and note the name of the driver.

Once Minikube and the appropriate driver for your OS is installed, you can start it by running:
#### Step 3: Install `garden-cli`

We have a Homebrew tap and package that you can use to easily install `garden-cli` and all dependencies:

```sh
minikube start --vm-driver=<your vm driver> # e.g. hyperkit on macOS
brew tap garden-io/garden
brew install garden-cli
```

Finally, you will need to configure a [kubectl context](https://kubernetes.io/docs/reference/kubectl/cheatsheet/#kubectl-context-and-configuration)
to point to your local instance.
To later upgrade to the newest version, simply run `brew update` and then `brew upgrade garden-cli`
(or `brew upgrade` to upgrade all your Homebrew packages).


### Linux / manual installation

<!-- More detailed docs for configuring kubectl context -->
You need the following dependencies on your local machine to use Garden:

* Node.js >= 8.x
* [Docker](https://docs.docker.com/)
* Git
* rsync
* [Watchman](https://facebook.github.io/watchman/docs/install.html)
* [Helm](https://github.com/kubernetes/helm)
* Local installation of Kubernetes and kubectl

#### Step 1: Docker
To install Docker, please follow the instructions in the [official documentation](https://docs.docker.com/install/).

Check out our [Minikube guide](../guides/minikube.md) for further information on using Garden with Minikube.
#### Step 2: Local Kubernetes
For local Kubernetes, you can use [Minikube](https://github.com/kubernetes/minikube). Please see our
[Minikube guide](../guides/minikube.md) for instructions.

#### Step 3: Other dependencies
Other dependencies can be installed with the package manager of your choice
#### Step 3: Install other dependencies

## Install the Garden CLI
Use your preferred method or package manager to install `node` (version 8.x or higher), `git`, `rsync`,
[Watchman](https://facebook.github.io/watchman/docs/install.html) and
[Helm](https://github.com/kubernetes/helm).

Once you have the dependencies set up, simply run:
#### Step 4: Install `garden-cli`

Once you have the dependencies set up, install the Garden CLI via `npm`:

```sh
npm install -g garden-cli
```

To later upgrade to the newest version, run `npm install -g -U garden-cli`.


## Using the CLI

With the CLI installed, we can now try out a few commands using the [hello-world](https://github.com/garden-io/garden-examples/tree/master/hello-world) project from our Github [examples repository](https://github.com/garden-io/garden-examples). The example consists of a container service that runs an [Express](http://expressjs.com/) app, a serverless function, and an npm library package.
Expand Down Expand Up @@ -99,4 +108,4 @@ And that's it! The services are now running on the Garden framework. You can see
$ garden call hello-container/hello
```

Check out our [Commands guide](../guides/commands.md) for other features like auto-reload, streaming service logs, running tests and lots more, or see how a Garden project is configured from scratch in our [Simple Project](../guides/simple-project.md) guide.
Check out our [Commands guide](../guides/commands.md) for other features like auto-reload, streaming service logs, running tests and lots more, or see how a Garden project is configured from scratch in our [Simple Project](../guides/simple-project.md) guide.
74 changes: 72 additions & 2 deletions gulpfile.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,18 +2,31 @@ import {
spawn as _spawn,
ChildProcess,
} from "child_process"
import { writeFileSync } from "fs"
import {
writeFileSync,
} from "fs"
import {
ensureDir,
pathExists,
readFile,
remove,
writeFile,
} from "fs-extra"
import * as handlebars from "handlebars"
import {
join,
relative,
} from "path"
import { generateDocs } from "./src/docs/generate"
import { getUrlChecksum } from "./support/support-util"
import execa = require("execa")

const gulp = require("gulp")
const cached = require("gulp-cached")
const checkLicense = require("gulp-license-check")
// const debug = require("gulp-debug")
// const exec = require("gulp-exec")
const packageJson = require("./package.json")
const pegjs = require("gulp-pegjs")
const sourcemaps = require("gulp-sourcemaps")
const gulpTslint = require("gulp-tslint")
Expand All @@ -29,7 +42,8 @@ const tsSources = "src/**/*.ts"
const testTsSources = "test/**/*.ts"
const pegjsSources = "src/*.pegjs"

const licenseHeaderPath = "static/license-header.txt"
const tmpDir = join(__dirname, "tmp")
const licenseHeaderPath = "support/license-header.txt"

const destDir = "build"

Expand Down Expand Up @@ -180,6 +194,62 @@ gulp.task("tslint-tests", () =>
.pipe(gulpTslint.report()),
)

/**
* Updates our Homebrew tap with the current released package version. Should be run after relasing to NPM.
*/
gulp.task("update-brew", async () => {
// clone the homebrew-garden tap repo
const brewRepoDir = join(tmpDir, "homebrew-garden")
if (await pathExists(brewRepoDir)) {
await remove(brewRepoDir)
}
await execa("git", ["clone", "[email protected]:garden-io/homebrew-garden.git"], { cwd: tmpDir })

// read the existing formula
const formulaDir = join(brewRepoDir, "Formula")
await ensureDir(formulaDir)
const formulaPath = join(formulaDir, "garden-cli.rb")
const existingFormula = await pathExists(formulaPath) ? (await readFile(formulaPath)).toString() : ""

// compile the formula handlebars template
const templatePath = join(__dirname, "support", "homebrew-formula.rb")
const templateString = (await readFile(templatePath)).toString()
const template = handlebars.compile(templateString)

// get the metadata from npm
const metadataJson = await execa.stdout("npm", ["view", "garden-cli", "--json"])
const metadata = JSON.parse(metadataJson)
const version = metadata["dist-tags"].latest
const tarballUrl = metadata.dist.tarball
const sha256 = metadata.dist.shasum.length === 64 ? metadata.dist.shasum : await getUrlChecksum(tarballUrl, "sha256")

const formula = template({
version,
homepage: metadata.homepage || packageJson.homepage,
description: metadata.description,
tarballUrl,
sha256,
})

if (formula === existingFormula) {
console.log("No changes to formula")
} else {
await writeFile(formulaPath, formula)

// check if the formula is OK
await execa("brew", ["audit", formulaPath])

for (const args of [
["add", formulaPath],
["commit", "-m", `update to ${version}`],
["tag", version],
["push", "--tags"],
]) {
await execa("git", args, { cwd: brewRepoDir })
}
}
})

gulp.task("watch-code", () => {
const verify = (path) => {
try {
Expand Down
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,7 @@
"generate-docs": "gulp generate-docs",
"integ": "./test/integ/run",
"lint": "gulp lint",
"postpublish": "gulp update-brew",
"prepare": "npm run snyk-protect",
"prepublishOnly": "npm run dist",
"preversion": "npm test",
Expand Down
22 changes: 22 additions & 0 deletions support/homebrew-formula.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
require "language/node"

class GardenCli < Formula
desc "{{description}}"
homepage "{{{homepage}}}"
url "{{{tarballUrl}}}"
sha256 "{{sha256}}"

depends_on "node"
depends_on "rsync"
depends_on "watchman"
depends_on "python" => :build

def install
system "npm", "install", *Language::Node.std_npm_install_args(libexec)
bin.install_symlink Dir["#{libexec}/bin/*"]
end

test do
# add a meaningful test here
end
end
File renamed without changes.
File renamed without changes.
24 changes: 24 additions & 0 deletions support/support-util.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import Axios from "axios"
import { createHash } from "crypto"

export async function getUrlChecksum(url: string, algorithm = "sha256") {
const response = await Axios({
method: "GET",
url,
responseType: "stream",
})

return new Promise((resolve, reject) => {
const hash = createHash(algorithm)

response.data.on("data", (chunk) => {
hash.update(chunk)
})

response.data.on("end", () => {
resolve(hash.digest("hex"))
})

response.data.on("error", reject)
})
}

0 comments on commit 72c4b4d

Please sign in to comment.