diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 0000000..dd4beec --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,8 @@ +--- +version: 2 +updates: +- package-ecosystem: gomod + directory: "/" + schedule: + interval: daily + open-pull-requests-limit: 10 diff --git a/.github/workflows/create-release.yml b/.github/workflows/create-release.yml new file mode 100644 index 0000000..46643ef --- /dev/null +++ b/.github/workflows/create-release.yml @@ -0,0 +1,86 @@ +name: Create Release + +on: + push: + branches: + - master + +jobs: + unit: + name: Unit Tests + runs-on: ubuntu-latest + steps: + - name: Setup Go + uses: actions/setup-go@v1 + with: + go-version: 1.14 + - name: Checkout + uses: actions/checkout@v2 + - name: Run Unit Tests + run: ./scripts/unit.sh + + integration: + name: Integration Tests + runs-on: ubuntu-latest + needs: unit + steps: + - name: Setup Go + uses: actions/setup-go@v1 + with: + go-version: 1.14 + - name: Checkout + uses: actions/checkout@v2 + - run: git fetch --depth=1 origin +refs/tags/*:refs/tags/* || true + - name: Run Integration Tests + run: ./scripts/integration.sh + env: + GIT_TOKEN: ${{ github.token }} + + release: + name: Release + runs-on: ubuntu-latest + needs: integration + steps: + - name: Checkout + uses: actions/checkout@v2 + - run: git fetch --depth=1 origin +refs/tags/*:refs/tags/* || true + - name: Tag + id: tag + uses: paketo-buildpacks/github-config/actions/tag@master + - name: Package + run: PACKAGE_DIR=artifact ./scripts/package.sh --version "${{ steps.tag.outputs.tag }}" --archive + - name: Create Release Notes + id: create-release-notes + run: | + mkdir -p "${HOME}/bin" + export PATH="${PATH}:${HOME}/bin" + curl "https://github.com/paketo-buildpacks/packit/releases/download/v0.0.14/jam-linux" \ + --silent \ + --location \ + --output "${HOME}/bin/jam" + chmod +x "${HOME}/bin/jam" + RELEASE_BODY=$(jam summarize --buildpack "${PWD}/artifact.tgz" --format markdown) + # Coz of this messed up issue + # https://github.community/t5/GitHub-Actions/set-output-Truncates-Multiline-Strings/m-p/38372#M3322 + RELEASE_BODY="${RELEASE_BODY//'%'/'%25'}" + RELEASE_BODY="${RELEASE_BODY//$'\n'/'%0A'}" + RELEASE_BODY="${RELEASE_BODY//$'\r'/'%0D'}" + echo "::set-output name=release_body::$RELEASE_BODY" + - name: Create Release + uses: paketo-buildpacks/github-config/actions/release/create@master + with: + repo: ${{ github.repository }} + token: ${{ secrets.PAKETO_BOT_GITHUB_TOKEN }} + tag_name: v${{ steps.tag.outputs.tag }} + target_commitish: ${{ github.sha }} + name: v${{ steps.tag.outputs.tag }} + body: ${{ steps.create-release-notes.outputs.release_body }} + draft: false + assets: | + [ + { + "path": "artifact.tgz", + "name": "${{ github.event.repository.name }}-${{ steps.tag.outputs.tag }}.tgz", + "content_type": "application/gzip" + } + ] diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml new file mode 100644 index 0000000..646ea6b --- /dev/null +++ b/.github/workflows/lint.yml @@ -0,0 +1,20 @@ +name: Lint + +on: + push: + branches: + - master + pull_request: + branches: + - master + +jobs: + golangci: + name: lint + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + - name: golangci-lint + uses: golangci/golangci-lint-action@v1.2.1 + with: + version: v1.27 diff --git a/.github/workflows/receive-github-config-updates.yml b/.github/workflows/receive-github-config-updates.yml new file mode 100644 index 0000000..ecab415 --- /dev/null +++ b/.github/workflows/receive-github-config-updates.yml @@ -0,0 +1,35 @@ +name: Sync + +on: + repository_dispatch: + types: working-dir-update + +jobs: + build: + name: Sync + runs-on: ubuntu-latest + steps: + + # checkout paketo github-config as src-repo + - name: Checkout paketo github-config repo + uses: actions/checkout@v2 + with: + repository: paketo-buildpacks/github-config + path: config-repo + + # checkout this repo + - name: Checkout + uses: actions/checkout@v2 + with: + path: current-repo + + - name: Run the sync action + uses: paketo-buildpacks/github-config/actions/sync@master + env: + GITHUB_TOKEN: ${{ secrets.PAKETO_BOT_GITHUB_TOKEN }} + with: + config-repo: config-repo + current-repo: current-repo + config-path: "/implementation" + ssh-private-key: ${{ secrets.PAKETO_BOT_SSH_KEY }} + id: do-sync diff --git a/.github/workflows/send-dependency-update.yml b/.github/workflows/send-dependency-update.yml new file mode 100644 index 0000000..4a95af7 --- /dev/null +++ b/.github/workflows/send-dependency-update.yml @@ -0,0 +1,44 @@ +# This workflow triggers on a published release event. +# Requires the following secrets: +# - LANGUAGE_FAMILY_REPO -> the full name of the repo to send the dispatch to (eg. paketo-buildpacks/nodejs) +# - PAKETO_BOT_GITHUB_TOKEN -> a token with permissions to send the dispatch to the language family repo + +name: Send Dependency Update Dispatch + +on: + release: + types: [published] + +jobs: + + dispatch: + runs-on: ubuntu-latest + name: Send Dispatch + steps: + + # Parses the release event JSON and fetches the details that make up a dependency update. + # Dependency update details are provided as outputs. + - name: Parse Release Dependency + id: dependency + uses: paketo-buildpacks/github-config/actions/dependency/parse@master + + # Generic repository dispatch sender. + - name: Send Repository Dispatch + uses: paketo-buildpacks/github-config/actions/dispatch@master + with: + repos: ${{ secrets.LANGUAGE_FAMILY_REPO }} + token: ${{ secrets.PAKETO_BOT_GITHUB_TOKEN }} + event: dependency-update + payload: | + { + "strategy": "replace", + "dependency": { + "id": "${{ steps.dependency.outputs.id }}", + "sha256": "${{ steps.dependency.outputs.sha256 }}", + "source": "${{ steps.dependency.outputs.source }}", + "source_sha256": "${{ steps.dependency.outputs.source_sha256 }}", + "stacks": ${{ steps.dependency.outputs.stacks }}, + "uri": "${{ steps.dependency.outputs.uri }}", + "version": "${{ steps.dependency.outputs.version }}" + } + } diff --git a/.github/workflows/test-pull-request.yml b/.github/workflows/test-pull-request.yml new file mode 100644 index 0000000..93c1d02 --- /dev/null +++ b/.github/workflows/test-pull-request.yml @@ -0,0 +1,37 @@ +name: Test Pull Request + +on: + pull_request: + branches: + - master + +jobs: + unit: + name: Unit Tests + runs-on: ubuntu-latest + steps: + - name: Setup Go + uses: actions/setup-go@v1 + with: + go-version: 1.14 + - name: Checkout + uses: actions/checkout@v2 + - name: Run Unit Tests + run: ./scripts/unit.sh + + integration: + name: Integration Tests + runs-on: ubuntu-latest + needs: unit + steps: + - name: Setup Go + uses: actions/setup-go@v1 + with: + go-version: 1.14 + - name: Checkout + uses: actions/checkout@v2 + - run: git fetch --depth=1 origin +refs/tags/*:refs/tags/* || true + - name: Run Integration Tests + run: ./scripts/integration.sh + env: + GIT_TOKEN: ${{ github.token }} diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..69b8101 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +/.bin diff --git a/.mergify/config.yml b/.mergify/config.yml new file mode 100644 index 0000000..2d47423 --- /dev/null +++ b/.mergify/config.yml @@ -0,0 +1,12 @@ +pull_request_rules: + - name: Auto merge pull requests from github-actions bot + conditions: + - author=github-actions[bot] + # TODO: Fill in these conditions when they are finalized + # - status-success=Unit Tests + # - status-success=Integration Tests + actions: + merge: + strict: true + method: rebase + delete_head_branch: {} diff --git a/.packit b/.packit new file mode 100644 index 0000000..e69de29 diff --git a/build.go b/build.go new file mode 100644 index 0000000..b5c2fc5 --- /dev/null +++ b/build.go @@ -0,0 +1,58 @@ +package depensure + +import ( + "fmt" + "io/ioutil" + "os" + "time" + + "github.com/paketo-buildpacks/packit" + "github.com/paketo-buildpacks/packit/chronos" +) + +//go:generate faux --interface BuildProcess --output fakes/build_process.go +type BuildProcess interface { + Execute(workspace, goPath, gocachedir string) (err error) +} + +func Build( + buildProcess BuildProcess, + logger LogEmitter, + clock chronos.Clock, +) packit.BuildFunc { + + return func(context packit.BuildContext) (packit.BuildResult, error) { + logger.Title("%s %s", context.BuildpackInfo.Name, context.BuildpackInfo.Version) + logger.Process("Executing build process") + + depcachedirLayer, err := context.Layers.Get("depcachedir", packit.CacheLayer) + if err != nil { + return packit.BuildResult{}, err + } + + gopath, err := ioutil.TempDir("", "gopath") + if err != nil { + return packit.BuildResult{}, fmt.Errorf("failed to create GOPATH directory: %w", err) + } + + duration, err := clock.Measure(func() error { + return buildProcess.Execute(context.WorkingDir, gopath, depcachedirLayer.Path) + }) + + if err != nil { + return packit.BuildResult{}, err + } + + err = os.RemoveAll(gopath) + if err != nil { + return packit.BuildResult{}, fmt.Errorf("failed to delete GOPATH directory: %w", err) + } + + logger.Action("Completed in %s", duration.Round(time.Millisecond)) + logger.Break() + + return packit.BuildResult{ + Layers: []packit.Layer{depcachedirLayer}, + }, nil + } +} diff --git a/build_test.go b/build_test.go new file mode 100644 index 0000000..ebffbad --- /dev/null +++ b/build_test.go @@ -0,0 +1,148 @@ +package depensure_test + +import ( + "bytes" + "errors" + "io/ioutil" + "os" + "path/filepath" + "testing" + "time" + + depensure "github.com/paketo-buildpacks/dep-ensure" + "github.com/paketo-buildpacks/dep-ensure/fakes" + "github.com/paketo-buildpacks/packit" + "github.com/paketo-buildpacks/packit/chronos" + "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 + buildProcess *fakes.BuildProcess + logs *bytes.Buffer + timeStamp time.Time + clock chronos.Clock + 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()) + + timeStamp = time.Now() + clock = chronos.NewClock(func() time.Time { + return timeStamp + }) + + buildProcess = &fakes.BuildProcess{} + logs = bytes.NewBuffer(nil) + build = depensure.Build( + buildProcess, + depensure.NewLogEmitter(logs), + clock, + ) + }) + + 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", + }, + Layers: packit.Layers{Path: layersDir}, + }) + Expect(err).NotTo(HaveOccurred()) + + Expect(result).To(Equal(packit.BuildResult{ + Layers: []packit.Layer{ + { + Name: "depcachedir", + Path: filepath.Join(layersDir, "depcachedir"), + SharedEnv: packit.Environment{}, + BuildEnv: packit.Environment{}, + LaunchEnv: packit.Environment{}, + Build: false, + Launch: false, + Cache: true, + }, + }, + Processes: nil, + })) + + Expect(buildProcess.ExecuteCall.CallCount).To(Equal(1)) + Expect(buildProcess.ExecuteCall.Receives.Workspace).To(Equal(workingDir)) + Expect(buildProcess.ExecuteCall.Returns.Err).To(BeNil()) + Expect(logs.String()).To(ContainSubstring("Some Buildpack some-version")) + Expect(logs.String()).To(ContainSubstring("Executing build process")) + Expect(logs.String()).To(ContainSubstring("Completed in ")) + }) + + context("failure cases", func() { + context("when the get for the depcachedir fails", func() { + it.Before(func() { + Expect(os.Chmod(layersDir, 0000)).To(Succeed()) + }) + + it.After(func() { + Expect(os.Chmod(layersDir, os.ModePerm)).To(Succeed()) + }) + + it("returns an error", func() { + _, err := build(packit.BuildContext{ + WorkingDir: workingDir, + CNBPath: cnbDir, + Stack: "some-stack", + BuildpackInfo: packit.BuildpackInfo{ + Name: "Some Buildpack", + Version: "some-version", + }, + Layers: packit.Layers{Path: layersDir}, + }) + Expect(err).To(MatchError(ContainSubstring("permission denied"))) + }) + }) + + context("when the build process fails", func() { + it.Before(func() { + buildProcess.ExecuteCall.Returns.Err = errors.New("failed to execute build process") + }) + + it("returns an error", func() { + _, err := build(packit.BuildContext{ + WorkingDir: workingDir, + CNBPath: cnbDir, + Stack: "some-stack", + BuildpackInfo: packit.BuildpackInfo{ + Name: "Some Buildpack", + Version: "some-version", + }, + Layers: packit.Layers{Path: layersDir}, + }) + Expect(err).To(MatchError("failed to execute build process")) + }) + }) + }) +} diff --git a/buildpack.toml b/buildpack.toml new file mode 100644 index 0000000..9bccb8d --- /dev/null +++ b/buildpack.toml @@ -0,0 +1,18 @@ +api = "0.2" + +[buildpack] + id = "paketo-buildpacks/dep-ensure" + name = "Dep Ensure Buildpack" + +[metadata] + include_files = [ "bin/build", "bin/detect", "bin/run", "buildpack.toml" ] + pre_package = "./scripts/build.sh" + +[[stacks]] + id = "io.buildpacks.stacks.bionic" + +[[stacks]] + id = "io.paketo.stacks.tiny" + +[[stacks]] + id = "org.cloudfoundry.stacks.cflinuxfs3" diff --git a/dep_ensure_process.go b/dep_ensure_process.go new file mode 100644 index 0000000..1785cb5 --- /dev/null +++ b/dep_ensure_process.go @@ -0,0 +1,76 @@ +package depensure + +import ( + // "github.com/paketo-buildpacks/packit/chronos" + "bytes" + "fmt" + "os" + "path/filepath" + + "github.com/paketo-buildpacks/packit/fs" + "github.com/paketo-buildpacks/packit/pexec" +) + +//go:generate faux --interface Executable --output fakes/executable.go +type Executable interface { + Execute(pexec.Execution) (err error) +} + +type DepEnsureProcess struct { + executable Executable + logs LogEmitter +} + +func NewDepEnsureProcess(executable Executable, logs LogEmitter) DepEnsureProcess { + return DepEnsureProcess{ + executable: executable, + logs: logs, + } +} + +func (p DepEnsureProcess) Execute(workspace, gopath, depcachedir string) error { + var err error + tmpAppPath := filepath.Join(gopath, "src", "app") + err = os.MkdirAll(tmpAppPath, os.ModePerm) + if err != nil { + return fmt.Errorf("failed to create GOPATH app dir: %w", err) + } + + err = fs.Copy(workspace, tmpAppPath) + if err != nil { + return fmt.Errorf("failed to copy application source onto GOPATH: %w", err) + } + + p.logs.Subprocess("Running 'dep ensure'") + + buffer := bytes.NewBuffer(nil) + err = p.executable.Execute(pexec.Execution{ + Args: []string{"ensure"}, + Dir: tmpAppPath, + Stdout: buffer, + Stderr: buffer, + Env: append(os.Environ(), fmt.Sprintf("GOPATH=%s", gopath), fmt.Sprintf("DEPCACHEDIR=%s", depcachedir)), + }) + + if err != nil { + p.logs.Detail(buffer.String()) + return fmt.Errorf("'dep ensure' command failed: %w", err) + } + + err = os.RemoveAll(filepath.Join(workspace, "vendor")) + if err != nil { + return fmt.Errorf("failed to remove vendor from application source: %w", err) + } + + err = fs.Copy(filepath.Join(tmpAppPath, "vendor"), filepath.Join(workspace, "vendor")) + if err != nil { + return fmt.Errorf("failed to copy vendor back to application source: %w", err) + } + + err = fs.Copy(filepath.Join(tmpAppPath, "Gopkg.lock"), filepath.Join(workspace, "Gopkg.lock")) + if err != nil { + return fmt.Errorf("failed to copy Gopkg.lock back to application source: %w", err) + } + + return err +} diff --git a/dep_ensure_process_test.go b/dep_ensure_process_test.go new file mode 100644 index 0000000..1fad4a9 --- /dev/null +++ b/dep_ensure_process_test.go @@ -0,0 +1,150 @@ +package depensure_test + +import ( + "bytes" + "errors" + "fmt" + "io/ioutil" + "os" + "path/filepath" + "testing" + + depensure "github.com/paketo-buildpacks/dep-ensure" + "github.com/paketo-buildpacks/dep-ensure/fakes" + "github.com/paketo-buildpacks/packit/pexec" + "github.com/sclevine/spec" + + . "github.com/onsi/gomega" +) + +func testDepEnsureProcess(t *testing.T, context spec.G, it spec.S) { + var ( + Expect = NewWithT(t).Expect + + workspace string + gopath string + depcachedir string + executable *fakes.Executable + buffer *bytes.Buffer + commandOutput *bytes.Buffer + + process depensure.DepEnsureProcess + ) + + it.Before(func() { + var err error + + workspace, err = ioutil.TempDir("", "workspace") + Expect(err).NotTo(HaveOccurred()) + + gopath, err = ioutil.TempDir("", "gopath") + Expect(err).NotTo(HaveOccurred()) + + depcachedir, err = ioutil.TempDir("", "depcachedir") + Expect(err).NotTo(HaveOccurred()) + + err = ioutil.WriteFile(filepath.Join(workspace, "test.go"), nil, os.ModePerm) + Expect(err).NotTo(HaveOccurred()) + + err = os.MkdirAll(filepath.Join(workspace, "dir1", "dir2"), os.ModePerm) + Expect(err).NotTo(HaveOccurred()) + + err = ioutil.WriteFile(filepath.Join(workspace, "dir1", "dir2", "somefile.go"), nil, os.ModePerm) + Expect(err).NotTo(HaveOccurred()) + + executable = &fakes.Executable{} + executable.ExecuteCall.Stub = func(execution pexec.Execution) error { + err = os.MkdirAll(filepath.Join(gopath, "src", "app", "vendor", "somedir"), os.ModePerm) + if err != nil { + return err + } + + if err := ioutil.WriteFile(filepath.Join(gopath, "src", "app", "Gopkg.lock"), nil, 0755); err != nil { + return err + } + + return nil + } + + buffer = bytes.NewBuffer(nil) + commandOutput = bytes.NewBuffer(nil) + + process = depensure.NewDepEnsureProcess(executable, depensure.NewLogEmitter(buffer)) + }) + + it.After(func() { + Expect(os.RemoveAll(workspace)).To(Succeed()) + Expect(os.RemoveAll(gopath)).To(Succeed()) + }) + + context("Execute", func() { + it("succeeds", func() { + Expect(process.Execute(workspace, gopath, depcachedir)).To(Succeed()) + Expect(executable.ExecuteCall.Receives.Execution).To(Equal(pexec.Execution{ + Args: []string{"ensure"}, + Dir: filepath.Join(gopath, "src", "app"), + Stdout: commandOutput, + Stderr: commandOutput, + Env: append(os.Environ(), fmt.Sprintf("GOPATH=%s", gopath), fmt.Sprintf("DEPCACHEDIR=%s", depcachedir)), + })) + + Expect(filepath.Join(gopath, "src", "app", "test.go")).To(BeAnExistingFile()) + + // make sure the file moves do not mess with src files + Expect(filepath.Join(workspace, "dir1", "dir2", "somefile.go")).To(BeAnExistingFile()) + Expect(filepath.Join(workspace, "Gopkg.lock")).To(BeAnExistingFile()) + Expect(filepath.Join(workspace, "vendor", "somedir")).To(BeADirectory()) + + Expect(buffer.String()).To(ContainSubstring(" Running 'dep ensure'")) + }) + + context("failure cases", func() { + context("when unable to write to the tmp gopath dir", func() { + it.Before(func() { + Expect(os.Chmod(gopath, 0000)).To(Succeed()) + }) + + it.After(func() { + Expect(os.Chmod(gopath, 0777)).To(Succeed()) + }) + + it("returns an error", func() { + err := process.Execute(workspace, gopath, depcachedir) + Expect(err).To(MatchError(ContainSubstring("permission denied"))) + }) + }) + + context("when unable to write vendor to workspace dir", func() { + it.Before(func() { + Expect(os.Chmod(workspace, 0555)).To(Succeed()) + }) + + it.After(func() { + Expect(os.Chmod(workspace, 0777)).To(Succeed()) + }) + + it("returns an error", func() { + err := process.Execute(workspace, gopath, depcachedir) + Expect(err).To(MatchError(ContainSubstring("failed to copy vendor"))) + }) + }) + + context("when the executable fails", func() { + it.Before(func() { + executable.ExecuteCall.Stub = func(execution pexec.Execution) error { + fmt.Fprintln(execution.Stdout, "dep ensure error on stdout") + fmt.Fprintln(execution.Stderr, "dep ensure error on stderr") + return errors.New("failed to execute") + } + }) + + it("returns an error", func() { + err := process.Execute(workspace, gopath, depcachedir) + Expect(buffer.String()).To(ContainSubstring("dep ensure error on stdout\n")) + Expect(buffer.String()).To(ContainSubstring("dep ensure error on stderr\n")) + Expect(err).To(MatchError("'dep ensure' command failed: failed to execute")) + }) + }) + }) + }) +} diff --git a/detect.go b/detect.go new file mode 100644 index 0000000..e4b3066 --- /dev/null +++ b/detect.go @@ -0,0 +1,34 @@ +package depensure + +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, "Gopkg.toml")) + if err != nil { + if os.IsNotExist(err) { + return packit.DetectResult{}, packit.Fail + } + return packit.DetectResult{}, fmt.Errorf("Failed to stat Gopkg.toml : %w", err) + } + + return packit.DetectResult{ + Plan: packit.BuildPlan{ + Requires: []packit.BuildPlanRequirement{ + { + Name: "dep", + Metadata: map[string]interface{}{ + "build": true, + }, + }, + }, + }, + }, nil + } +} diff --git a/detect_test.go b/detect_test.go new file mode 100644 index 0000000..9a4fc03 --- /dev/null +++ b/detect_test.go @@ -0,0 +1,68 @@ +package depensure_test + +import ( + "io/ioutil" + "os" + "path/filepath" + "testing" + + depensure "github.com/paketo-buildpacks/dep-ensure" + "github.com/paketo-buildpacks/packit" + "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()) + + Expect(ioutil.WriteFile(filepath.Join(workingDir, "Gopkg.toml"), nil, 0644)).To(Succeed()) + + detect = depensure.Detect() + }) + + it.After(func() { + Expect(os.RemoveAll(workingDir)).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: "dep", + Metadata: map[string]interface{}{ + "build": true, + }, + }, + }, + })) + }) + + context("when there is no Gopkg.toml in the working directory", func() { + it.Before(func() { + Expect(os.Remove(filepath.Join(workingDir, "Gopkg.toml"))).To(Succeed()) + }) + + it("fails detection", func() { + _, err := detect(packit.DetectContext{ + WorkingDir: workingDir, + }) + Expect(err).To(MatchError(packit.Fail)) + }) + }) +} diff --git a/fakes/build_process.go b/fakes/build_process.go new file mode 100644 index 0000000..acc3436 --- /dev/null +++ b/fakes/build_process.go @@ -0,0 +1,32 @@ +package fakes + +import "sync" + +type BuildProcess struct { + ExecuteCall struct { + sync.Mutex + CallCount int + Receives struct { + Workspace string + GoPath string + Gocachedir string + } + Returns struct { + Err error + } + Stub func(string, string, string) error + } +} + +func (f *BuildProcess) Execute(param1 string, param2 string, param3 string) error { + f.ExecuteCall.Lock() + defer f.ExecuteCall.Unlock() + f.ExecuteCall.CallCount++ + f.ExecuteCall.Receives.Workspace = param1 + f.ExecuteCall.Receives.GoPath = param2 + f.ExecuteCall.Receives.Gocachedir = param3 + if f.ExecuteCall.Stub != nil { + return f.ExecuteCall.Stub(param1, param2, param3) + } + return f.ExecuteCall.Returns.Err +} diff --git a/fakes/executable.go b/fakes/executable.go new file mode 100644 index 0000000..e5c3a37 --- /dev/null +++ b/fakes/executable.go @@ -0,0 +1,32 @@ +package fakes + +import ( + "sync" + + "github.com/paketo-buildpacks/packit/pexec" +) + +type Executable struct { + ExecuteCall struct { + sync.Mutex + CallCount int + Receives struct { + Execution pexec.Execution + } + Returns struct { + Err error + } + Stub func(pexec.Execution) error + } +} + +func (f *Executable) Execute(param1 pexec.Execution) error { + f.ExecuteCall.Lock() + defer f.ExecuteCall.Unlock() + f.ExecuteCall.CallCount++ + f.ExecuteCall.Receives.Execution = param1 + if f.ExecuteCall.Stub != nil { + return f.ExecuteCall.Stub(param1) + } + return f.ExecuteCall.Returns.Err +} diff --git a/go.mod b/go.mod new file mode 100644 index 0000000..63b1701 --- /dev/null +++ b/go.mod @@ -0,0 +1,11 @@ +module github.com/paketo-buildpacks/dep-ensure + +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.16 + github.com/paketo-buildpacks/packit v0.2.0 + github.com/sclevine/spec v1.4.0 +) diff --git a/go.sum b/go.sum new file mode 100644 index 0000000..f6546cd --- /dev/null +++ b/go.sum @@ -0,0 +1,168 @@ +cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= +github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ= +github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= +github.com/ForestEckhardt/freezer v0.0.0-20200630185456-a126adb8de1b h1:5ah4g+sbKU2LvMIOeR0+a4PIzrXRxJTqjZwXOdOdQsA= +github.com/ForestEckhardt/freezer v0.0.0-20200630185456-a126adb8de1b/go.mod h1:Tp5MaiHIfM9TOqTFYlqHsittmOnFGsUcUVDX+AtbNrI= +github.com/Masterminds/semver v1.5.0 h1:H65muMkzWKEuNDnfl9d70GUjFniHKHRbFPGBuZ3QEww= +github.com/Masterminds/semver v1.5.0/go.mod h1:MB6lktGJrhw8PrUyiEoblNEGEQ+RzHPF078ddwwvV3Y= +github.com/VividCortex/ewma v1.1.1 h1:MnEK4VOv6n0RSY4vtRe3h11qjxL3+t0B8yOL8iMXdcM= +github.com/VividCortex/ewma v1.1.1/go.mod h1:2Tkkvm3sRDVXaiyucHiACn4cqf7DpdyLvmxzcbUokwA= +github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= +github.com/cheggaaa/pb/v3 v3.0.4 h1:QZEPYOj2ix6d5oEg63fbHmpolrnNiwjUsk+h74Yt4bM= +github.com/cheggaaa/pb/v3 v3.0.4/go.mod h1:7rgWxLrAUcFMkvJuv09+DYi7mMUYi8nO9iOWcvGJPfw= +github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= +github.com/cloudfoundry/packit v0.0.4/go.mod h1:9xu1MT6SrenSB4oFOXtruMapQ+vdfGXLzBZDnPjhYrM= +github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= +github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= +github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= +github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= +github.com/fatih/color v1.9.0 h1:8xPHl4/q1VyqGIPif1F+1V3Y3lSmrq01EabUW3CoW5s= +github.com/fatih/color v1.9.0/go.mod h1:eQcE1qtQxscV5RaZvpXrrb8Drkc3/DdQ+uUYCNjL+zU= +github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= +github.com/fsnotify/fsnotify v1.4.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWoS4= +github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= +github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= +github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= +github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= +github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= +github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs= +github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w= +github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= +github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8= +github.com/golang/protobuf v1.4.2 h1:+Z5KGCizgyZCbGh1KZqA0fcLLkwbsjIzS4aV2v7wJX0= +github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= +github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= +github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= +github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= +github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.0 h1:/QaMHBdZ26BB3SSst0Iwl10Epc+xhTquomWX0oZEB6w= +github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= +github.com/kr/pretty v0.2.0/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= +github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= +github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= +github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= +github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= +github.com/mattn/go-colorable v0.1.2/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= +github.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= +github.com/mattn/go-colorable v0.1.7 h1:bQGKb3vps/j0E9GfJQ03JyhRuxsvdAanXlT9BTw3mdw= +github.com/mattn/go-colorable v0.1.7/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= +github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= +github.com/mattn/go-isatty v0.0.10/go.mod h1:qgIWMr58cqv1PHHyhnkY9lrL7etaEgOFcMEpPG5Rm84= +github.com/mattn/go-isatty v0.0.11/go.mod h1:PhnuNfih5lzO57/f3n+odYbM4JtupLOxQOAqxQCu2WE= +github.com/mattn/go-isatty v0.0.12 h1:wuysRhFDzyxgEmMf5xjvJ2M9dZoWAXNNr5LSBS7uHXY= +github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= +github.com/mattn/go-runewidth v0.0.7/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= +github.com/mattn/go-runewidth v0.0.8/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= +github.com/mattn/go-runewidth v0.0.9 h1:Lm995f3rfxdpd6TSmuVCHVb/QhupuXlYr8sCI/QdE+0= +github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= +github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs= +github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= +github.com/nxadm/tail v1.4.4 h1:DQuhQpB1tVlglWS2hLQ5OV6B5r8aGxSrPc5Qo6uTN78= +github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= +github.com/oklog/ulid v1.3.1 h1:EGfNDEx6MqHz8B3uNV6QAib1UR2Lm97sHi3ocA6ESJ4= +github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U= +github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= +github.com/onsi/ginkgo v1.11.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= +github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk= +github.com/onsi/ginkgo v1.13.0 h1:M76yO2HkZASFjXL0HSoZJ1AYEmQxNJmY41Jx1zNUq1Y= +github.com/onsi/ginkgo v1.13.0/go.mod h1:+REjRxOmWfHCjfv9TTWB1jD1Frx4XydAD3zm1lskyM0= +github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= +github.com/onsi/gomega v1.9.0/go.mod h1:Ho0h+IUsWyvy1OpqCwxlQ/21gkhVunqlU8fDGcoTdcA= +github.com/onsi/gomega v1.10.1 h1:o0+MgICZLuZ7xjH7Vx6zS/zcu93/BEp1VwkIW1mEXCE= +github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= +github.com/paketo-buildpacks/occam v0.0.16 h1:RnEizv5F5O5LL1VeOiOh8WkNosybbEPOMys6730yopw= +github.com/paketo-buildpacks/occam v0.0.16/go.mod h1:i3WI2yc5Nji45iNpW+IiiEy3f2BvbIfbLi24VKVOK0I= +github.com/paketo-buildpacks/packit v0.1.0 h1:4kmSfE9+ZuudfbCaT58vX0DtLNPU4QXmV9lIiGgxWZo= +github.com/paketo-buildpacks/packit v0.1.0/go.mod h1:b40wtWWAcgB47+vYGDD9KKhzOtBjI8KPqGxwGvV+XNs= +github.com/paketo-buildpacks/packit v0.2.0 h1:l4sFKYlmKENRNMAKATt437+Ar9WD+bM42ZckKW59rMY= +github.com/paketo-buildpacks/packit v0.2.0/go.mod h1:b40wtWWAcgB47+vYGDD9KKhzOtBjI8KPqGxwGvV+XNs= +github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= +github.com/sclevine/agouti v3.0.0+incompatible/go.mod h1:b4WX9W9L1sfQKXeJf1mUTLZKJ48R1S7H23Ji7oFO5Bw= +github.com/sclevine/spec v1.4.0 h1:z/Q9idDcay5m5irkZ28M7PtQM4aOISzOpj4bUPkDee8= +github.com/sclevine/spec v1.4.0/go.mod h1:LvpgJaFyvQzRvc1kaDs0bulYwzC70PbiYjC4QnFHkOM= +github.com/ulikunitz/xz v0.5.7 h1:YvTNdFzX6+W5m9msiYg/zpkSURPPtOlzbqYjrFn7Yt4= +github.com/ulikunitz/xz v0.5.7/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oWt/14= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= +golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= +golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= +golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200625001655-4c5254603344 h1:vGXIOMxbNfDTk/aXCmfdLgkrSV+Z2tcbze+pEc3v5W4= +golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= +golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= +golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191008105621-543471e840be/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191128015809-6d18c012aee9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200124204421-9fbb57f87de9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200519105757-fe76b779f299/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200625212154-ddb9806d33ae h1:Ih9Yo4hSPImZOpfGuA4bR/ORKTAbhZo2AbWNRCnevdo= +golang.org/x/sys v0.0.0-20200625212154-ddb9806d33ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= +golang.org/x/text v0.3.3 h1:cokOdA+Jmi5PJGXLlLllQSgYigAEfHXJAERHVMaCc2k= +golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= +golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= +golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4= +golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= +google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= +google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= +google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= +google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= +google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= +google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= +google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= +google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= +google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= +google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= +google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE= +google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo= +google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +google.golang.org/protobuf v1.25.0 h1:Ejskq+SyPohKW+1uil0JJMtmHCgJPJ/qWTxr8qp+R4c= +google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f h1:BLraFXnmrev5lT+xlilqcH8XK9/i0At2xKjWk4p6zsU= +gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= +gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ= +gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= +gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.3.0 h1:clyUAQHOM3G0M3f5vQj7LuJrETvjVot3Z5el9nffUtU= +gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= diff --git a/init_test.go b/init_test.go new file mode 100644 index 0000000..06e99a4 --- /dev/null +++ b/init_test.go @@ -0,0 +1,16 @@ +package depensure_test + +import ( + "testing" + + "github.com/sclevine/spec" + "github.com/sclevine/spec/report" +) + +func TestUnitGoBuild(t *testing.T) { + suite := spec.New("dep-ensure", spec.Report(report.Terminal{})) + suite("Build", testBuild) + suite("Detect", testDetect) + suite("DepEnsureProcess", testDepEnsureProcess) + suite.Run(t) +} diff --git a/integration.json b/integration.json new file mode 100644 index 0000000..507f9fd --- /dev/null +++ b/integration.json @@ -0,0 +1,3 @@ +{ + "dep": "./testdata/tmp-dep-cnb" +} diff --git a/integration/default_test.go b/integration/default_test.go new file mode 100644 index 0000000..0dc84cc --- /dev/null +++ b/integration/default_test.go @@ -0,0 +1,85 @@ +package integration_test + +import ( + "fmt" + "os" + "path/filepath" + "testing" + + "github.com/paketo-buildpacks/occam" + "github.com/sclevine/spec" + + . "github.com/onsi/gomega" + . "github.com/paketo-buildpacks/occam/matchers" +) + +func testDefault(t *testing.T, context spec.G, it spec.S) { + var ( + Expect = NewWithT(t).Expect + + pack occam.Pack + docker occam.Docker + ) + + it.Before(func() { + pack = occam.NewPack().WithVerbose().WithNoColor() + docker = occam.NewDocker() + }) + + context("when building a simple dep app", func() { + var ( + image occam.Image + container occam.Container + + name string + source string + ) + + it.Before(func() { + var err error + name, err = occam.RandomName() + Expect(err).NotTo(HaveOccurred()) + }) + + it.After(func() { + Expect(docker.Container.Remove.Execute(container.ID)).To(Succeed()) + Expect(docker.Volume.Remove.Execute(occam.CacheVolumeNames(name))).To(Succeed()) + Expect(docker.Image.Remove.Execute(image.ID)).To(Succeed()) + Expect(os.RemoveAll(source)).To(Succeed()) + }) + + it("builds successfully", func() { + var err error + source, err = occam.Source(filepath.Join("testdata", "default")) + Expect(err).NotTo(HaveOccurred()) + + var logs fmt.Stringer + image, logs, err = pack.Build. + WithNoPull(). + WithBuildpacks( + settings.Buildpacks.Dep.Online, + settings.Buildpacks.DepEnsure.Online, + ). + Execute(name, source) + Expect(err).ToNot(HaveOccurred(), logs.String) + + Expect(logs).To(ContainLines( + MatchRegexp(fmt.Sprintf(`%s \d+\.\d+\.\d+`, settings.Buildpack.Name)), + " Executing build process", + " Running 'dep ensure'", + MatchRegexp(` Completed in ([0-9]*(\.[0-9]*)?[a-z]+)+`), + )) + + container, err = docker.Container.Run. + WithCommand("ls -alR /workspace"). + Execute(image.ID) + Expect(err).NotTo(HaveOccurred()) + + logs, err = docker.Container.Logs.Execute(container.ID) + Expect(err).NotTo(HaveOccurred()) + + Expect(logs).To(ContainSubstring("Gopkg.lock")) + Expect(logs).To(ContainSubstring("vendor/github.com/ZiCog/shiny-thing")) + }) + }) +} diff --git a/integration/init_test.go b/integration/init_test.go new file mode 100644 index 0000000..d910844 --- /dev/null +++ b/integration/init_test.go @@ -0,0 +1,77 @@ +package integration_test + +import ( + "encoding/json" + "os" + "path/filepath" + "testing" + "time" + + "github.com/BurntSushi/toml" + "github.com/paketo-buildpacks/occam" + "github.com/sclevine/spec" + "github.com/sclevine/spec/report" + + . "github.com/onsi/gomega" +) + +var settings struct { + Buildpacks struct { + Dep struct { + Online string + } + DepEnsure struct { + Online string + Offline string + } + } + Buildpack struct { + ID string + Name string + } + Config struct { + Dep string `json:"dep"` + } +} + +func TestIntegration(t *testing.T) { + Expect := NewWithT(t).Expect + + file, err := os.Open("../integration.json") + Expect(err).NotTo(HaveOccurred()) + + Expect(json.NewDecoder(file).Decode(&settings.Config)).To(Succeed()) + Expect(file.Close()).To(Succeed()) + + file, err = os.Open("../buildpack.toml") + Expect(err).NotTo(HaveOccurred()) + + _, err = toml.DecodeReader(file, &settings) + Expect(err).NotTo(HaveOccurred()) + Expect(file.Close()).To(Succeed()) + + root, err := filepath.Abs("./..") + Expect(err).ToNot(HaveOccurred()) + + buildpackStore := occam.NewBuildpackStore() + + settings.Buildpacks.DepEnsure.Online, err = buildpackStore.Get. + WithVersion("1.2.3"). + Execute(root) + Expect(err).ToNot(HaveOccurred()) + + settings.Buildpacks.DepEnsure.Offline, err = buildpackStore.Get. + WithVersion("1.2.3"). + WithOfflineDependencies(). + Execute(root) + Expect(err).ToNot(HaveOccurred()) + + // todo: when dep is rewritten, point to real dep cnb in integration.json + settings.Buildpacks.Dep.Online = settings.Config.Dep + + SetDefaultEventuallyTimeout(10 * time.Second) + + suite := spec.New("Integration", spec.Report(report.Terminal{}), spec.Parallel()) + suite("Default", testDefault) + suite.Run(t) +} diff --git a/integration/testdata/default/Gopkg.toml b/integration/testdata/default/Gopkg.toml new file mode 100644 index 0000000..bae3bfa --- /dev/null +++ b/integration/testdata/default/Gopkg.toml @@ -0,0 +1,7 @@ +[[constraint]] + branch = "master" + name = "github.com/ZiCog/shiny-thing" + +[prune] + go-tests = true + unused-packages = true diff --git a/integration/testdata/default/main.go b/integration/testdata/default/main.go new file mode 100644 index 0000000..49028c1 --- /dev/null +++ b/integration/testdata/default/main.go @@ -0,0 +1,7 @@ +package main + +import "github.com/ZiCog/shiny-thing/foo" + +func main() { + foo.Do() +} diff --git a/integration/testdata/tmp-dep-cnb/bin/build b/integration/testdata/tmp-dep-cnb/bin/build new file mode 100755 index 0000000..b588176 --- /dev/null +++ b/integration/testdata/tmp-dep-cnb/bin/build @@ -0,0 +1,13 @@ +#!/usr/bin/env bash +set -eu +layersarg=1 +mkdir -p "${!layersarg}/mylayer" +pushd "${!layersarg}/mylayer" + curl -L https://buildpacks.cloudfoundry.org/dependencies/dep/dep-v0.5.4-linux-x64-cflinuxfs3-79b3ab9e.tgz -o dep.tgz + tar -xvf dep.tgz + mkdir -p env.build + echo "${!layersarg}/bin" + echo -n "${!layersarg}/bin" > "env.build/PATH.prepend" + echo -n ":" > "env.build/PATH.delim" +popd +echo -n "build = true" > "${!layersarg}/mylayer.toml" diff --git a/integration/testdata/tmp-dep-cnb/bin/detect b/integration/testdata/tmp-dep-cnb/bin/detect new file mode 100755 index 0000000..81be0eb --- /dev/null +++ b/integration/testdata/tmp-dep-cnb/bin/detect @@ -0,0 +1,4 @@ +#!/usr/bin/env bash +buildplan=2 +echo '[[provides]] +name = "dep"' > ${!buildplan} diff --git a/integration/testdata/tmp-dep-cnb/buildpack.toml b/integration/testdata/tmp-dep-cnb/buildpack.toml new file mode 100644 index 0000000..1d4e58d --- /dev/null +++ b/integration/testdata/tmp-dep-cnb/buildpack.toml @@ -0,0 +1,16 @@ +api = "0.2" + +[buildpack] + id = "arjun024/tmp-dep-cnb" + name = "" + version = "1.0.0" + +[metadata] + include_files = ["bin/build", "bin/detect", "buildpack.toml"] + +[[stacks]] + id = "io.buildpacks.stacks.bionic" + +[[stacks]] + id = "org.cloudfoundry.stacks.cflinuxfs3" + diff --git a/log_emitter.go b/log_emitter.go new file mode 100644 index 0000000..d8e784f --- /dev/null +++ b/log_emitter.go @@ -0,0 +1,17 @@ +package depensure + +import ( + "io" + + "github.com/paketo-buildpacks/packit/scribe" +) + +type LogEmitter struct { + scribe.Logger +} + +func NewLogEmitter(output io.Writer) LogEmitter { + return LogEmitter{ + Logger: scribe.NewLogger(output), + } +} diff --git a/run/main.go b/run/main.go new file mode 100644 index 0000000..6a2e6ad --- /dev/null +++ b/run/main.go @@ -0,0 +1,22 @@ +package main + +import ( + "os" + + depensure "github.com/paketo-buildpacks/dep-ensure" + "github.com/paketo-buildpacks/packit" + "github.com/paketo-buildpacks/packit/chronos" + "github.com/paketo-buildpacks/packit/pexec" +) + +func main() { + logEmitter := depensure.NewLogEmitter(os.Stdout) + packit.Run( + depensure.Detect(), + depensure.Build( + depensure.NewDepEnsureProcess(pexec.NewExecutable("dep"), logEmitter), + logEmitter, + chronos.DefaultClock, + ), + ) +} diff --git a/scripts/.util/git.sh b/scripts/.util/git.sh new file mode 100644 index 0000000..928b0c7 --- /dev/null +++ b/scripts/.util/git.sh @@ -0,0 +1,21 @@ +#!/usr/bin/env bash + +set -eu +set -o pipefail + +# shellcheck source=./print.sh +source "$(dirname "${BASH_SOURCE[0]}")/print.sh" + +function util::git::token::fetch() { + if [[ -z "${GIT_TOKEN:-""}" ]]; then + util::print::title "Fetching GIT_TOKEN" + + GIT_TOKEN="$( + lpass show Shared-CF\ Buildpacks/concourse-private.yml \ + | grep buildpacks-github-token \ + | cut -d ' ' -f 2 + )" + fi + + printf "%s" "${GIT_TOKEN}" +} diff --git a/scripts/.util/print.sh b/scripts/.util/print.sh new file mode 100644 index 0000000..92264a7 --- /dev/null +++ b/scripts/.util/print.sh @@ -0,0 +1,50 @@ +#!/usr/bin/env bash + +set -eu +set -o pipefail + +function util::print::title() { + local blue reset message + blue="\033[0;34m" + reset="\033[0;39m" + message="${1}" + + echo -e "\n${blue}${message}${reset}" >&2 +} + +function util::print::info() { + local message + message="${1}" + + echo -e "${message}" >&2 +} + +function util::print::error() { + local message red reset + message="${1}" + red="\033[0;31m" + reset="\033[0;39m" + + echo -e "${red}${message}${reset}" >&2 + exit 1 +} + +function util::print::success() { + local message green reset + message="${1}" + green="\033[0;32m" + reset="\033[0;39m" + + echo -e "${green}${message}${reset}" >&2 + exit 0 +} + +function util::print::warn() { + local message yellow reset + message="${1}" + yellow="\033[0;33m" + reset="\033[0;39m" + + echo -e "${yellow}${message}${reset}" >&2 + exit 0 +} diff --git a/scripts/.util/tools.sh b/scripts/.util/tools.sh new file mode 100644 index 0000000..68b1e9d --- /dev/null +++ b/scripts/.util/tools.sh @@ -0,0 +1,135 @@ +#!/usr/bin/env bash + +set -eu +set -o pipefail + +# shellcheck source=./print.sh +source "$(dirname "${BASH_SOURCE[0]}")/print.sh" + +# shellcheck source=./git.sh +source "$(dirname "${BASH_SOURCE[0]}")/git.sh" + +function util::tools::path::export() { + local dir + dir="${1}" + + if ! echo "${PATH}" | grep -q "${dir}"; then + PATH="${dir}:$PATH" + export PATH + fi +} + +function util::tools::jam::install () { + local dir + while [[ "${#}" != 0 ]]; do + case "${1}" in + --directory) + dir="${2}" + shift 2 + ;; + + *) + util::print::error "unknown argument \"${1}\"" + esac + done + + local os + case "$(uname)" in + "Darwin") + os="darwin" + ;; + + "Linux") + os="linux" + ;; + + *) + echo "Unknown OS \"$(uname)\"" + exit 1 + esac + + mkdir -p "${dir}" + util::tools::path::export "${dir}" + + if [[ ! -f "${dir}/jam" ]]; then + local version + version="v0.0.14" + + util::print::title "Installing jam ${version}" + curl "https://github.com/paketo-buildpacks/packit/releases/download/${version}/jam-${os}" \ + --silent \ + --location \ + --output "${dir}/jam" + chmod +x "${dir}/jam" + fi +} + +function util::tools::pack::install() { + local dir + while [[ "${#}" != 0 ]]; do + case "${1}" in + --directory) + dir="${2}" + shift 2 + ;; + + *) + util::print::error "unknown argument \"${1}\"" + esac + done + + mkdir -p "${dir}" + util::tools::path::export "${dir}" + + local os + case "$(uname)" in + "Darwin") + os="macos" + ;; + + "Linux") + os="linux" + ;; + + *) + echo "Unknown OS \"$(uname)\"" + exit 1 + esac + + if [[ ! -f "${dir}/pack" ]]; then + local version + version="v0.10.0" + + util::print::title "Installing pack ${version}" + curl "https://github.com/buildpacks/pack/releases/download/${version}/pack-v0.10.0-${os}.tgz" \ + --silent \ + --location \ + --output /tmp/pack.tgz + tar xzf /tmp/pack.tgz -C "${dir}" + chmod +x "${dir}/pack" + rm /tmp/pack.tgz + fi +} + +function util::tools::packager::install () { + local dir + while [[ "${#}" != 0 ]]; do + case "${1}" in + --directory) + dir="${2}" + shift 2 + ;; + + *) + util::print::error "unknown argument \"${1}\"" + esac + done + + mkdir -p "${dir}" + util::tools::path::export "${dir}" + + if [[ ! -f "${dir}/packager" ]]; then + util::print::title "Installing packager" + GOBIN="${dir}" go get github.com/cloudfoundry/libcfbuildpack/packager + fi +} diff --git a/scripts/build.sh b/scripts/build.sh new file mode 100755 index 0000000..4cdf1b1 --- /dev/null +++ b/scripts/build.sh @@ -0,0 +1,73 @@ +#!/usr/bin/env bash +set -eu +set -o pipefail + +readonly PROGDIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +readonly BUILDPACKDIR="$(cd "${PROGDIR}/.." && pwd)" + +function main() { + mkdir -p "${BUILDPACKDIR}/bin" + + if [[ -f "${BUILDPACKDIR}/run/main.go" ]]; then + pushd "${BUILDPACKDIR}/bin" > /dev/null || return + printf "%s" "Building run..." + + GOOS=linux \ + go build \ + -ldflags="-s -w" \ + -o "run" \ + "${BUILDPACKDIR}/run" + + echo "Success!" + + for name in detect build; do + printf "%s" "Linking ${name}..." + + ln -sf "run" "${name}" + + echo "Success!" + done + popd > /dev/null || return + fi + + if [[ -f "${BUILDPACKDIR}/main.go" ]]; then + pushd "${BUILDPACKDIR}/bin" > /dev/null || return + printf "%s" "Building run..." + + GOOS=linux \ + go build \ + -ldflags="-s -w" \ + -o "run" \ + "${BUILDPACKDIR}" + + echo "Success!" + + for name in detect build; do + printf "%s" "Linking ${name}..." + + ln -sf "run" "${name}" + + echo "Success!" + done + popd > /dev/null || return + fi + + if [[ -d "${BUILDPACKDIR}/cmd" ]]; then + local name + for src in "${BUILDPACKDIR}"/cmd/*; do + name="$(basename "${src}")" + + printf "%s" "Building ${name}..." + + GOOS="linux" \ + go build \ + -ldflags="-s -w" \ + -o "${BUILDPACKDIR}/bin/${name}" \ + "${src}/main.go" + + echo "Success!" + done + fi +} + +main "${@:-}" diff --git a/scripts/integration.sh b/scripts/integration.sh new file mode 100755 index 0000000..b739749 --- /dev/null +++ b/scripts/integration.sh @@ -0,0 +1,76 @@ +#!/usr/bin/env bash +set -eu +set -o pipefail + +readonly PROGDIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +readonly BUILDPACKDIR="$(cd "${PROGDIR}/.." && pwd)" + +# shellcheck source=.util/tools.sh +source "${PROGDIR}/.util/tools.sh" + +# shellcheck source=.util/print.sh +source "${PROGDIR}/.util/print.sh" + +# shellcheck source=.util/git.sh +source "${PROGDIR}/.util/git.sh" + +function main() { + if [[ ! -d "${BUILDPACKDIR}/integration" ]]; then + util::print::warn "** WARNING No Integration tests **" + fi + + tools::install + images::pull + token::fetch + tests::run +} + +function tools::install() { + util::tools::pack::install \ + --directory "${BUILDPACKDIR}/.bin" + + if [[ -f "${BUILDPACKDIR}/.packit" ]]; then + util::tools::jam::install \ + --directory "${BUILDPACKDIR}/.bin" + + else + util::tools::packager::install \ + --directory "${BUILDPACKDIR}/.bin" + fi +} + +function images::pull() { + util::print::title "Pulling build image..." + docker pull "${CNB_BUILD_IMAGE:=gcr.io/paketo-buildpacks/build:full-cnb-cf}" + + util::print::title "Pulling run image..." + docker pull "${CNB_RUN_IMAGE:=gcr.io/paketo-buildpacks/run:full-cnb-cf}" + + util::print::title "Pulling cflinuxfs3 builder image..." + docker pull "${CNB_BUILDER_IMAGE:=gcr.io/paketo-buildpacks/builder:cflinuxfs3}" + + export CNB_BUILD_IMAGE + export CNB_RUN_IMAGE + export CNB_BUILDER_IMAGE + + util::print::title "Setting default pack builder image..." + pack set-default-builder "${CNB_BUILDER_IMAGE}" +} + +function token::fetch() { + GIT_TOKEN="$(util::git::token::fetch)" + export GIT_TOKEN +} + +function tests::run() { + util::print::title "Run Buildpack Runtime Integration Tests" + pushd "${BUILDPACKDIR}" > /dev/null + if GOMAXPROCS="${GOMAXPROCS:-4}" go test -count=1 -timeout 0 ./integration/... -v -run Integration; then + util::print::success "** GO Test Succeeded **" + else + util::print::error "** GO Test Failed **" + fi + popd > /dev/null +} + +main "${@:-}" diff --git a/scripts/package.sh b/scripts/package.sh new file mode 100755 index 0000000..aaa47bb --- /dev/null +++ b/scripts/package.sh @@ -0,0 +1,114 @@ +#!/usr/bin/env bash +set -eu +set -o pipefail + +readonly PROGDIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +readonly BUILDPACKDIR="$(cd "${PROGDIR}/.." && pwd)" + +# shellcheck source=.util/tools.sh +source "${PWD}/scripts/.util/tools.sh" + +# shellcheck source=.util/print.sh +source "${PWD}/scripts/.util/print.sh" + +if ! command -v realpath > /dev/null; then + function realpath() { + [[ "${1}" = /* ]] && echo "${1}" || echo "${PWD}/${1#./}" + } +fi + +function main() { + local full_path args version cached archive offline + PACKAGE_DIR=${PACKAGE_DIR:-"${BUILDPACKDIR}/$(basename ${BUILDPACKDIR})_$(openssl rand -hex 4)"} + + full_path="$(realpath "${PACKAGE_DIR}")" + + while [[ "${#}" != 0 ]]; do + case "${1}" in + --archive|-a) + archive="true" + shift 1 + ;; + + --cached|-c) + cached="true" + offline="true" + shift 1 + ;; + + --version|-v) + version="${2}" + shift 2 + ;; + + "") + # skip if the argument is empty + shift 1 + ;; + + *) + util::print::error "unknown argument \"${1}\"" + esac + done + + if [[ -f "${BUILDPACKDIR}/.packit" ]]; then + #use jam + util::tools::jam::install --directory "${BUILDPACKDIR}/.bin" + if [[ -z "${version:-}" ]]; then #version not provided, use latest git tag + git_tag=$(git describe --tags "$(git rev-list --tags --max-count=1)" || echo "v0.0.0") + version=${git_tag:1} + fi + + extra_args="" + + if [[ -n "${offline:-}" ]]; then + PACKAGE_DIR="${PACKAGE_DIR}-cached" + extra_args+="--offline" + fi + + if [[ "${PACKAGE_DIR}" != "*.tgz" ]]; then + PACKAGE_DIR="${PACKAGE_DIR}.tgz" + fi + + + .bin/jam pack \ + --buildpack "$(pwd)/buildpack.toml" \ + --version "${version}" \ + --output "${PACKAGE_DIR}" \ + ${extra_args} + + else + # use old packager + util::tools::packager::install --directory "${BUILDPACKDIR}/.bin" + + args="${BUILDPACKDIR}/.bin/packager" + if [[ -n "${cached:-}" ]]; then + full_path="${full_path}-cached" + else + args="${args} --uncached" + fi + + if [[ -n "${archive:-}" ]]; then + args="${args} -archive" + fi + + if [[ -z "${version:-}" ]]; then + version="$(cd "${BUILDPACKDIR}" && git describe --tags "$(git rev-list --tags --max-count=1)" || echo "v0.0.0")" + fi + + args="${args} -version ${version}" + + pushd "${BUILDPACKDIR}" > /dev/null + eval "${args}" "${full_path}" + popd > /dev/null + + if [[ -n "${BP_REWRITE_HOST:-}" ]]; then + sed -i '' -e "s|^uri = \"https:\/\/buildpacks\.cloudfoundry\.org\(.*\)\"$|uri = \"http://${BP_REWRITE_HOST}\1\"|g" "${full_path}/buildpack.toml" + fi + fi + + + +} + +main "${@:-}" diff --git a/scripts/unit.sh b/scripts/unit.sh new file mode 100755 index 0000000..38f362d --- /dev/null +++ b/scripts/unit.sh @@ -0,0 +1,23 @@ +#!/usr/bin/env bash +set -eu +set -o pipefail + +readonly PROGDIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +readonly BUILDPACKDIR="$(cd "${PROGDIR}/.." && pwd)" + +# shellcheck source=.util/print.sh +source "${PROGDIR}/.util/print.sh" + +function main() { + util::print::title "Run Buildpack Unit Tests" + + pushd "${BUILDPACKDIR}" > /dev/null + if go test ./... -v -run Unit; then + util::print::success "** GO Test Succeeded **" + else + util::print::error "** GO Test Failed **" + fi + popd > /dev/null +} + +main "${@:-}"