Skip to content

Commit

Permalink
Adding acceptance tests for nodejs Stack (#35)
Browse files Browse the repository at this point in the history
* moving acceptance tests under integration directory

* creating an integration.json file and adding buildpacks

* updating go packages

* refactoring test.sh script to creating a local registry

* refactoring metadata acceptance tests

* feat: adding integration tests to ensure stacks work properly

* aligning tools.sh

* aligning test.sh

* reducing buildpakcs requried for building an app

* adding syft install on tools.sh

* removing comments

* refactor: applying review suggestions

* fix: sync create-one with create.sh from github-config repo

* adding dependabot.yml file for updating go module dependencies

* refactor: metadata test code reusability

* adding rest of the buildpacks and using npm to start the app

* renaming the env variable and also a small refactor on the functions

* feat: adding more acceptance tests

* adding utils file for sharing code among files

* major refactor

* refactor fetching node major varsions on integration.json

* removing sub-buildpacks and adding nodejs buildpack instead

* using stacks structure for code resusability in the future

* a bit of refactory of better code reusability in the future

* Moving setting and cleaning local registry to tools.sh file

* refactor: moving cleanup in to test.sh in order not to block github config updates on tools.sh

* adding java 21 on acceptance tests

* fixing issue with overriding build output

* fixing wrong naming

* increasing the time build limit

* revoving dependabot.yml file as is irrelevant
  • Loading branch information
pacostas committed Feb 27, 2024
1 parent 2fec557 commit 16cf374
Show file tree
Hide file tree
Showing 18 changed files with 2,837 additions and 1,160 deletions.
16 changes: 13 additions & 3 deletions .github/workflows/create-release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,7 @@ jobs:
search_depth: 1
repo: ${{ github.repository }}
output_path: "/github/workspace/${{ env.UBI_RUN_JAVA_11_SHA256_FILENAME }}"
token: ${{ secrets.PAKETO_BOT_GITHUB_TOKEN }}
token: ${{ secrets.PAKETO_BOT_GITHUB_TOKEN }}

- name: Find and Download Previous run Java 17 sha256 image hash code
id: fetch_previous_run_java_17_sha256_image_hash_code
Expand Down Expand Up @@ -840,7 +840,7 @@ jobs:
"path": "build-java-17/run.oci.sha256",
"name": ($repo + "-" + $tag + "-" + "run-java-17.oci.sha256"),
"content_type": "application/gzip"
},
},
{
"path": "build-java-21/run.oci",
"name": ($repo + "-" + $tag + "-" + "run-java-21.oci"),
Expand All @@ -850,7 +850,17 @@ jobs:
"path": "build-java-21/run.oci.sha256",
"name": ($repo + "-" + $tag + "-" + "run-java-21.oci.sha256"),
"content_type": "application/gzip"
},
},
{
"path": "build-java-21/run.oci",
"name": ($repo + "-" + $tag + "-" + "run-java-21.oci"),
"content_type": "application/gzip"
},
{
"path": "build-java-21/run.oci.sha256",
"name": ($repo + "-" + $tag + "-" + "run-java-21.oci.sha256"),
"content_type": "application/gzip"
},
{
"path": "build-nodejs-16/run.oci",
"name": ($repo + "-" + $tag + "-" + "run-nodejs-16.oci"),
Expand Down
284 changes: 122 additions & 162 deletions buildpack_integration_test.go
Original file line number Diff line number Diff line change
@@ -1,199 +1,159 @@
package acceptance_test

import (
"bytes"
"encoding/json"
"fmt"
"os"
"path/filepath"
"testing"

"github.com/google/uuid"
structs "github.com/paketo-community/ubi-base-stack/internal/structs"
utils "github.com/paketo-community/ubi-base-stack/internal/utils"
"github.com/sclevine/spec"

. "github.com/onsi/gomega"

"github.com/paketo-buildpacks/occam"
. "github.com/paketo-buildpacks/occam/matchers"
"github.com/paketo-buildpacks/packit/v2/pexec"
)

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

buildPlanBuildpack string
goDistBuildpack string
err error

builderConfigFilepath string

pack occam.Pack
docker occam.Docker
source string
name string
builder string
pack occam.Pack
docker occam.Docker
source string
name string

image occam.Image
container occam.Container

buildImageID string
runImageID string
runImageUrl string
builderImageUrl string
)

it.Before(func() {
pack = occam.NewPack().WithVerbose()
docker = occam.NewDocker()

var err error
name, err = occam.RandomName()
Expect(err).NotTo(HaveOccurred())

buildpackStore := occam.NewBuildpackStore()

buildPlanBuildpack, err = buildpackStore.Get.
Execute("github.com/paketo-community/build-plan")
Expect(err).NotTo(HaveOccurred())

goDistBuildpack, err = buildpackStore.Get.
WithVersion("1.2.3").
Execute("github.com/paketo-buildpacks/go-dist")
Expect(err).NotTo(HaveOccurred())

source, err = occam.Source(filepath.Join("integration", "testdata", "simple_app"))
Expect(err).NotTo(HaveOccurred())

builderConfigFile, err := os.CreateTemp("", "builder.toml")
Expect(err).NotTo(HaveOccurred())
builderConfigFilepath = builderConfigFile.Name()

_, err = fmt.Fprintf(builderConfigFile, `
[stack]
build-image = "%s:latest"
id = "io.buildpacks.stacks.ubi8"
run-image = "%s:latest"
`,
stack.BuildImageID,
stack.RunImageID,
)
Expect(err).NotTo(HaveOccurred())

Expect(archiveToDaemon(stack.BuildArchive, stack.BuildImageID)).To(Succeed())
Expect(archiveToDaemon(stack.RunArchive, stack.RunImageID)).To(Succeed())

builder = fmt.Sprintf("builder-%s", uuid.NewString())
logs, err := createBuilder(builderConfigFilepath, builder)
Expect(err).NotTo(HaveOccurred(), logs)
})

it.After(func() {
Expect(docker.Container.Remove.Execute(container.ID)).To(Succeed())
Expect(docker.Image.Remove.Execute(image.ID)).To(Succeed())
Expect(docker.Volume.Remove.Execute(occam.CacheVolumeNames(name))).To(Succeed())

lifecycleVersion, err := getLifecycleVersion(builder)
Expect(err).NotTo(HaveOccurred())

Expect(docker.Image.Remove.Execute(builder)).To(Succeed())
Expect(os.RemoveAll(builderConfigFilepath)).To(Succeed())

Expect(docker.Image.Remove.Execute(stack.BuildImageID)).To(Succeed())
Expect(docker.Image.Remove.Execute(stack.RunImageID)).To(Succeed())

Expect(docker.Image.Remove.Execute(fmt.Sprintf("buildpacksio/lifecycle:%s", lifecycleVersion))).To(Succeed())

Expect(os.RemoveAll(source)).To(Succeed())
context("When building an app using default stack", func() {

it.After(func() {
Expect(docker.Container.Remove.Execute(container.ID)).To(Succeed())
Expect(docker.Image.Remove.Execute(image.ID)).To(Succeed())
Expect(docker.Volume.Remove.Execute(occam.CacheVolumeNames(name))).To(Succeed())
err = utils.RemoveImages(docker, []string{buildImageID, runImageID, runImageUrl, builderImageUrl})
Expect(err).NotTo(HaveOccurred())
Expect(os.RemoveAll(source)).To(Succeed())
})

it.Before(func() {
name, err = occam.RandomName()
Expect(err).NotTo(HaveOccurred())

source, err = occam.Source(filepath.Join("integration", "testdata", "simple_app"))
Expect(err).NotTo(HaveOccurred())
})

it("should successfully build a go app", func() {
buildImageID, _, runImageID, runImageUrl, builderImageUrl, err = utils.GenerateBuilder(filepath.Join(root, "build"), RegistryUrl)
Expect(err).NotTo(HaveOccurred())

image, _, err = pack.WithNoColor().Build.
WithBuildpacks(
settings.Buildpacks.GoDist.Online,
settings.Buildpacks.BuildPlan.Online,
).
WithEnv(map[string]string{
"BP_LOG_LEVEL": "DEBUG",
}).
WithPullPolicy("if-not-present").
WithBuilder(builderImageUrl).
Execute(name, source)
Expect(err).NotTo(HaveOccurred())

container, err = docker.Container.Run.
WithDirect().
WithCommand("go").
WithCommandArgs([]string{"run", "main.go"}).
WithEnv(map[string]string{"PORT": "8080"}).
WithPublish("8080").
WithPublishAll().
Execute(image.ID)
Expect(err).NotTo(HaveOccurred())

Eventually(container).Should(BeAvailable())
Eventually(container).Should(Serve(MatchRegexp(`go1.*`)).OnPort(8080))

})
})

it("builds an app with a buildpack", func() {

var err error
var logs fmt.Stringer
image, logs, err = pack.WithNoColor().Build.
WithBuildpacks(
goDistBuildpack,
buildPlanBuildpack,
).
WithEnv(map[string]string{
"BP_LOG_LEVEL": "DEBUG",
}).
WithPullPolicy("if-not-present").
WithBuilder(builder).
Execute(name, source)
Expect(err).ToNot(HaveOccurred(), logs.String)

container, err = docker.Container.Run.
WithDirect().
WithCommand("go").
WithCommandArgs([]string{"run", "main.go"}).
WithEnv(map[string]string{"PORT": "8080"}).
WithPublish("8080").
WithPublishAll().
Execute(image.ID)
Expect(err).NotTo(HaveOccurred())

Eventually(container).Should(BeAvailable())
Eventually(container).Should(Serve(MatchRegexp(`go1.*`)).OnPort(8080))
context("When building an app using nodejs stacks", func() {

it.After(func() {
Expect(docker.Container.Remove.Execute(container.ID)).To(Succeed())
Expect(docker.Image.Remove.Execute(image.ID)).To(Succeed())
Expect(docker.Volume.Remove.Execute(occam.CacheVolumeNames(name))).To(Succeed())
err = utils.RemoveImages(docker, []string{buildImageID, runImageID, runImageUrl, builderImageUrl})
Expect(err).NotTo(HaveOccurred())
Expect(os.RemoveAll(source)).To(Succeed())
})

it.Before(func() {
name, err = occam.RandomName()
Expect(err).NotTo(HaveOccurred())

source, err = occam.Source(filepath.Join("integration", "testdata", "simple_app"))
Expect(err).NotTo(HaveOccurred())
})

var stacks []structs.Stack

for _, nodeMajorVersion := range settings.Config.NodeMajorVersions {
stacks = append(stacks, structs.NewStack(nodeMajorVersion, "nodejs", root))
}

for _, stack := range stacks {
// Create a copy of the stack to get the value and instead of the pointer
stack := stack
it(fmt.Sprintf("it should successfully build a nodejs app with node version %d", stack.MajorVersion), func() {
buildImageID, _, runImageID, runImageUrl, builderImageUrl, err = utils.GenerateBuilder(stack.AbsPath, RegistryUrl)
Expect(err).NotTo(HaveOccurred())

image, _, err = pack.WithNoColor().Build.
WithBuildpacks(
settings.Buildpacks.GoDist.Online,
settings.Buildpacks.BuildPlan.Online,
).
WithEnv(map[string]string{
"BP_LOG_LEVEL": "DEBUG",
}).
WithPullPolicy("if-not-present").
WithBuilder(builderImageUrl).
Execute(name, source)
Expect(err).NotTo(HaveOccurred())

container, err = docker.Container.Run.
WithDirect().
WithCommand("go").
WithCommandArgs([]string{"run", "main.go"}).
WithEnv(map[string]string{"PORT": "8080"}).
WithPublish("8080").
WithPublishAll().
Execute(image.ID)
Expect(err).NotTo(HaveOccurred())

Eventually(container).Should(BeAvailable())
Eventually(container).Should(Serve(MatchRegexp(`go1.*`)).OnPort(8080))
Eventually(container).Should(Serve(MatchRegexp(fmt.Sprintf(`v%d.*`, stack.MajorVersion))).OnPort(8080).WithEndpoint("/node/version"))
})
}
})
}

func archiveToDaemon(path, id string) error {
skopeo := pexec.NewExecutable("skopeo")

return skopeo.Execute(pexec.Execution{
Args: []string{
"copy",
fmt.Sprintf("oci-archive://%s", path),
fmt.Sprintf("docker-daemon:%s:latest", id),
},
})
}

func createBuilder(config string, name string) (string, error) {
buf := bytes.NewBuffer(nil)

pack := pexec.NewExecutable("pack")
err := pack.Execute(pexec.Execution{
Stdout: buf,
Stderr: buf,
Args: []string{
"builder",
"create",
name,
fmt.Sprintf("--config=%s", config),
},
})
return buf.String(), err
}

type Builder struct {
LocalInfo struct {
Lifecycle struct {
Version string `json:"version"`
} `json:"lifecycle"`
} `json:"local_info"`
}

func getLifecycleVersion(builderID string) (string, error) {
buf := bytes.NewBuffer(nil)
pack := pexec.NewExecutable("pack")
err := pack.Execute(pexec.Execution{
Stdout: buf,
Stderr: buf,
Args: []string{
"builder",
"inspect",
builderID,
"-o",
"json",
},
})

if err != nil {
return "", err
}

var builder Builder
err = json.Unmarshal([]byte(buf.String()), &builder)
if err != nil {
return "", err
}
return builder.LocalInfo.Lifecycle.Version, nil
}
Loading

0 comments on commit 16cf374

Please sign in to comment.