Skip to content

Commit

Permalink
Implementation of RFC 0001 (#6)
Browse files Browse the repository at this point in the history
* Bootsrapped files and failing integration tests

* working detect

Signed-off-by: Arjun Sreedharan <[email protected]>

* build executable

Signed-off-by: Arjun Sreedharan <[email protected]>

* Add tests for graceful shutdown

Update README and CODEOWNERS

Signed-off-by: Sophie Wigmore <[email protected]>

Co-authored-by: Arjun Sreedharan <[email protected]>
  • Loading branch information
sophiewigmore and arjun024 authored Sep 1, 2020
1 parent 2a7d52f commit 0b0a6ab
Show file tree
Hide file tree
Showing 34 changed files with 1,058 additions and 0 deletions.
1 change: 1 addition & 0 deletions .github/.syncignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
CODEOWNERS
1 change: 1 addition & 0 deletions .github/CODEOWNERS
Validating CODEOWNERS rules …
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
* @paketo-buildpacks/nodejs-maintainers
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
/.bin
/.build
Empty file added .packit
Empty file.
19 changes: 19 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -1 +1,20 @@
# Yarn Start Cloud Native Buildpack

## `gcr.io/paketo-community/yarn-install`

The Yarn Start CNB sets the start command for the given application.

## Integration

This CNB writes a command, so there's currently no scenario we can
imagine that you would need to require it as dependency.

To package this buildpack for consumption:
```
$ ./scripts/package.sh
```
This builds the buildpack's source using GOOS=linux by default. You can supply another value as the first argument to package.sh.

## `buildpack.yml` Configurations

There are no extra configurations for this buildpack based on `buildpack.yml`.
28 changes: 28 additions & 0 deletions build.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package yarnstart

import (
"github.com/paketo-buildpacks/packit"
"github.com/paketo-buildpacks/packit/scribe"
)

func Build(logger scribe.Logger) packit.BuildFunc {
return func(context packit.BuildContext) (packit.BuildResult, error) {
logger.Title("%s %s", context.BuildpackInfo.Name, context.BuildpackInfo.Version)

logger.Process("Writing start command")
command := "tini -g -- yarn start"
logger.Subprocess(command)

return packit.BuildResult{
Plan: packit.BuildpackPlan{
Entries: []packit.BuildpackPlanEntry{},
},
Processes: []packit.Process{
{
Type: "web",
Command: command,
},
},
}, nil
}
}
80 changes: 80 additions & 0 deletions build_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
package yarnstart_test

import (
"bytes"
"io/ioutil"
"os"
"testing"

"github.com/paketo-buildpacks/packit"
"github.com/paketo-buildpacks/packit/scribe"
yarnstart "github.com/paketo-buildpacks/yarn-start"
"github.com/sclevine/spec"

. "github.com/onsi/gomega"
)

func testBuild(t *testing.T, context spec.G, it spec.S) {
var (
Expect = NewWithT(t).Expect

layersDir string
workingDir string
cnbDir string
buffer *bytes.Buffer

build packit.BuildFunc
)

it.Before(func() {
var err error
layersDir, err = ioutil.TempDir("", "layers")
Expect(err).NotTo(HaveOccurred())

cnbDir, err = ioutil.TempDir("", "cnb")
Expect(err).NotTo(HaveOccurred())

workingDir, err = ioutil.TempDir("", "working-dir")
Expect(err).NotTo(HaveOccurred())

buffer = bytes.NewBuffer(nil)
logger := scribe.NewLogger(buffer)

build = yarnstart.Build(logger)
})

it.After(func() {
Expect(os.RemoveAll(layersDir)).To(Succeed())
Expect(os.RemoveAll(cnbDir)).To(Succeed())
Expect(os.RemoveAll(workingDir)).To(Succeed())
})

it("returns a result that builds correctly", func() {
result, err := build(packit.BuildContext{
WorkingDir: workingDir,
CNBPath: cnbDir,
Stack: "some-stack",
BuildpackInfo: packit.BuildpackInfo{
Name: "Some Buildpack",
Version: "some-version",
},
Plan: packit.BuildpackPlan{
Entries: []packit.BuildpackPlanEntry{},
},
Layers: packit.Layers{Path: layersDir},
})
Expect(err).NotTo(HaveOccurred())

Expect(result).To(Equal(packit.BuildResult{
Plan: packit.BuildpackPlan{
Entries: []packit.BuildpackPlanEntry{},
},
Processes: []packit.Process{
{
Type: "web",
Command: "tini -g -- yarn start",
},
},
}))
})
}
15 changes: 15 additions & 0 deletions buildpack.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
api = "0.2"

[buildpack]
id = "paketo-buildpacks/yarn-start"
name = "Yarn-Start Buildpack"

[[stacks]]
id = "io.buildpacks.stacks.bionic"

[[stacks]]
id = "org.cloudfoundry.stacks.cflinuxfs3"

[metadata]
include_files = ["bin/run","bin/build","bin/detect","buildpack.toml"]
pre_package = "./scripts/build.sh"
8 changes: 8 additions & 0 deletions constants.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package yarnstart

const (
Node = "node"
NodeModules = "node_modules"
Tini = "tini"
Yarn = "yarn"
)
52 changes: 52 additions & 0 deletions detect.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
package yarnstart

import (
"fmt"
"os"
"path/filepath"

"github.com/paketo-buildpacks/packit"
)

func Detect() packit.DetectFunc {
return func(context packit.DetectContext) (packit.DetectResult, error) {
_, err := os.Stat(filepath.Join(context.WorkingDir, "yarn.lock"))
if err != nil {
if os.IsNotExist(err) {
return packit.DetectResult{}, packit.Fail
}
return packit.DetectResult{}, fmt.Errorf("failed to stat yarn.lock: %w", err)
}

return packit.DetectResult{
Plan: packit.BuildPlan{
Requires: []packit.BuildPlanRequirement{
{
Name: Node,
Metadata: map[string]interface{}{
"launch": true,
},
},
{
Name: NodeModules,
Metadata: map[string]interface{}{
"launch": true,
},
},
{
Name: Yarn,
Metadata: map[string]interface{}{
"launch": true,
},
},
{
Name: Tini,
Metadata: map[string]interface{}{
"launch": true,
},
},
},
},
}, nil
}
}
103 changes: 103 additions & 0 deletions detect_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
package yarnstart_test

import (
"io/ioutil"
"os"
"path/filepath"
"testing"

"github.com/paketo-buildpacks/packit"
yarnstart "github.com/paketo-buildpacks/yarn-start"
"github.com/sclevine/spec"

. "github.com/onsi/gomega"
)

func testDetect(t *testing.T, context spec.G, it spec.S) {
var (
Expect = NewWithT(t).Expect

workingDir string
detect packit.DetectFunc
)

it.Before(func() {
var err error
workingDir, err = ioutil.TempDir("", "working-dir")
Expect(err).NotTo(HaveOccurred())

detect = yarnstart.Detect()
})

it.After(func() {
Expect(os.RemoveAll(workingDir)).To(Succeed())
})

context("when there is a yarn.lock", func() {
it.Before(func() {
Expect(ioutil.WriteFile(filepath.Join(workingDir, "yarn.lock"), nil, 0644)).To(Succeed())
})
it("detects", func() {
result, err := detect(packit.DetectContext{
WorkingDir: workingDir,
})
Expect(err).NotTo(HaveOccurred())
Expect(result.Plan).To(Equal(packit.BuildPlan{
Requires: []packit.BuildPlanRequirement{
{
Name: "node",
Metadata: map[string]interface{}{
"launch": true,
},
},
{
Name: "node_modules",
Metadata: map[string]interface{}{
"launch": true,
},
},
{
Name: "yarn",
Metadata: map[string]interface{}{
"launch": true,
},
},
{
Name: "tini",
Metadata: map[string]interface{}{
"launch": true,
},
},
},
}))
})
})

context("when there is no yarn.lock", func() {
it("fails detection", func() {
_, err := detect(packit.DetectContext{
WorkingDir: workingDir,
})
Expect(err).To(MatchError(packit.Fail))
})
})

context("failure cases", func() {
context("the workspace directory cannot be accessed", func() {
it.Before(func() {
Expect(os.Chmod(workingDir, 0000)).To(Succeed())
})

it.After(func() {
Expect(os.Chmod(workingDir, os.ModePerm)).To(Succeed())
})

it("returns an error", func() {
_, err := detect(packit.DetectContext{
WorkingDir: workingDir,
})
Expect(err).To(MatchError(ContainSubstring("failed to stat yarn.lock:")))
})
})
})
}
12 changes: 12 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
module github.com/paketo-buildpacks/yarn-start

go 1.14

require (
github.com/BurntSushi/toml v0.3.1
github.com/onsi/gomega v1.10.1
github.com/paketo-buildpacks/occam v0.0.17
github.com/paketo-buildpacks/packit v0.2.6
github.com/sclevine/spec v1.4.0
golang.org/x/net v0.0.0-20200707034311-ab3426394381 // indirect
)
Loading

0 comments on commit 0b0a6ab

Please sign in to comment.