-
Notifications
You must be signed in to change notification settings - Fork 43
chore: add Makefile and local registry cache #138
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
514db8b
40071cb
0f7178b
5978e62
cecd41b
75eb96d
db5fac8
67ef2f0
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -48,4 +48,4 @@ jobs: | |
go-version: "~1.21" | ||
|
||
- name: Test | ||
run: go test ./... | ||
run: make test |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1 +1,2 @@ | ||
scripts/envbuilder-* | ||
.registry-cache |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,42 @@ | ||
GOARCH := $(shell go env GOARCH) | ||
PWD=$(shell pwd) | ||
|
||
develop: | ||
./scripts/develop.sh | ||
|
||
build: scripts/envbuilder-$(GOARCH) | ||
./scripts/build.sh | ||
|
||
.PHONY: test | ||
test: test-registry test-images | ||
go test -count=1 ./... | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Count will disable go caching, let's remove it as I imagine anyone developing the project would prefer caching on? |
||
|
||
# Starts a local Docker registry on port 5000 with a local disk cache. | ||
.PHONY: test-registry | ||
test-registry: .registry-cache | ||
if ! curl -fsSL http://localhost:5000/v2/_catalog > /dev/null 2>&1; then \ | ||
docker rm -f envbuilder-registry && \ | ||
docker run -d -p 5000:5000 --name envbuilder-registry --volume $(PWD)/.registry-cache:/var/lib/registry registry:2; \ | ||
fi | ||
|
||
# Pulls images referenced in integration tests and pushes them to the local cache. | ||
.PHONY: test-images | ||
test-images: .registry-cache .registry-cache/docker/registry/v2/repositories/envbuilder-test-alpine .registry-cache/docker/registry/v2/repositories/envbuilder-test-ubuntu .registry-cache/docker/registry/v2/repositories/envbuilder-test-codercom-code-server | ||
|
||
.registry-cache: | ||
mkdir -p .registry-cache && chmod -R ag+w .registry-cache | ||
|
||
.registry-cache/docker/registry/v2/repositories/envbuilder-test-alpine: | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. These should perhaps depend on the |
||
docker pull alpine:latest | ||
docker tag alpine:latest localhost:5000/envbuilder-test-alpine:latest | ||
docker push localhost:5000/envbuilder-test-alpine:latest | ||
|
||
.registry-cache/docker/registry/v2/repositories/envbuilder-test-ubuntu: | ||
docker pull ubuntu:latest | ||
docker tag ubuntu:latest localhost:5000/envbuilder-test-ubuntu:latest | ||
docker push localhost:5000/envbuilder-test-ubuntu:latest | ||
|
||
.registry-cache/docker/registry/v2/repositories/envbuilder-test-codercom-code-server: | ||
docker pull codercom/code-server:latest | ||
docker tag codercom/code-server:latest localhost:5000/envbuilder-test-codercom-code-server:latest | ||
docker push localhost:5000/envbuilder-test-codercom-code-server:latest |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -43,13 +43,15 @@ import ( | |
|
||
const ( | ||
testContainerLabel = "envbox-integration-test" | ||
testImageAlpine = "localhost:5000/envbuilder-test-alpine:latest" | ||
testImageUbuntu = "localhost:5000/envbuilder-test-ubuntu:latest" | ||
) | ||
|
||
func TestFailsGitAuth(t *testing.T) { | ||
t.Parallel() | ||
url := createGitServer(t, gitServerOptions{ | ||
files: map[string]string{ | ||
"Dockerfile": "FROM alpine:latest", | ||
"Dockerfile": "FROM " + testImageAlpine, | ||
}, | ||
username: "kyle", | ||
password: "testing", | ||
|
@@ -64,7 +66,7 @@ func TestSucceedsGitAuth(t *testing.T) { | |
t.Parallel() | ||
url := createGitServer(t, gitServerOptions{ | ||
files: map[string]string{ | ||
"Dockerfile": "FROM alpine:latest", | ||
"Dockerfile": "FROM " + testImageAlpine, | ||
}, | ||
username: "kyle", | ||
password: "testing", | ||
|
@@ -142,7 +144,7 @@ func TestBuildFromDevcontainerWithFeatures(t *testing.T) { | |
} | ||
} | ||
}`, | ||
".devcontainer/Dockerfile": "FROM ubuntu", | ||
".devcontainer/Dockerfile": "FROM " + testImageUbuntu, | ||
".devcontainer/feature3/devcontainer-feature.json": string(feature3Spec), | ||
".devcontainer/feature3/install.sh": "echo $GRAPE > /test3output", | ||
}, | ||
|
@@ -166,7 +168,7 @@ func TestBuildFromDockerfile(t *testing.T) { | |
// Ensures that a Git repository with a Dockerfile is cloned and built. | ||
url := createGitServer(t, gitServerOptions{ | ||
files: map[string]string{ | ||
"Dockerfile": "FROM alpine:latest", | ||
"Dockerfile": "FROM " + testImageAlpine, | ||
}, | ||
}) | ||
ctr, err := runEnvbuilder(t, options{env: []string{ | ||
|
@@ -183,7 +185,7 @@ func TestBuildPrintBuildOutput(t *testing.T) { | |
// Ensures that a Git repository with a Dockerfile is cloned and built. | ||
url := createGitServer(t, gitServerOptions{ | ||
files: map[string]string{ | ||
"Dockerfile": "FROM alpine:latest\nRUN echo hello", | ||
"Dockerfile": "FROM " + testImageAlpine + "\nRUN echo hello", | ||
}, | ||
}) | ||
ctr, err := runEnvbuilder(t, options{env: []string{ | ||
|
@@ -211,7 +213,7 @@ func TestBuildIgnoreVarRunSecrets(t *testing.T) { | |
// Ensures that a Git repository with a Dockerfile is cloned and built. | ||
url := createGitServer(t, gitServerOptions{ | ||
files: map[string]string{ | ||
"Dockerfile": "FROM alpine:latest", | ||
"Dockerfile": "FROM " + testImageAlpine, | ||
}, | ||
}) | ||
dir := t.TempDir() | ||
|
@@ -234,7 +236,7 @@ func TestBuildWithSetupScript(t *testing.T) { | |
// Ensures that a Git repository with a Dockerfile is cloned and built. | ||
url := createGitServer(t, gitServerOptions{ | ||
files: map[string]string{ | ||
"Dockerfile": "FROM alpine:latest", | ||
"Dockerfile": "FROM " + testImageAlpine, | ||
}, | ||
}) | ||
ctr, err := runEnvbuilder(t, options{env: []string{ | ||
|
@@ -260,7 +262,7 @@ func TestBuildFromDevcontainerInCustomPath(t *testing.T) { | |
"dockerfile": "Dockerfile" | ||
}, | ||
}`, | ||
".devcontainer/custom/Dockerfile": "FROM ubuntu", | ||
".devcontainer/custom/Dockerfile": "FROM " + testImageUbuntu, | ||
}, | ||
}) | ||
ctr, err := runEnvbuilder(t, options{env: []string{ | ||
|
@@ -285,7 +287,7 @@ func TestBuildFromDevcontainerInSubfolder(t *testing.T) { | |
"dockerfile": "Dockerfile" | ||
}, | ||
}`, | ||
".devcontainer/subfolder/Dockerfile": "FROM ubuntu", | ||
".devcontainer/subfolder/Dockerfile": "FROM " + testImageUbuntu, | ||
}, | ||
}) | ||
ctr, err := runEnvbuilder(t, options{env: []string{ | ||
|
@@ -308,7 +310,7 @@ func TestBuildFromDevcontainerInRoot(t *testing.T) { | |
"dockerfile": "Dockerfile" | ||
}, | ||
}`, | ||
"Dockerfile": "FROM ubuntu", | ||
"Dockerfile": "FROM " + testImageUbuntu, | ||
}, | ||
}) | ||
ctr, err := runEnvbuilder(t, options{env: []string{ | ||
|
@@ -323,7 +325,7 @@ func TestBuildFromDevcontainerInRoot(t *testing.T) { | |
func TestBuildCustomCertificates(t *testing.T) { | ||
srv := httptest.NewTLSServer(createGitHandler(t, gitServerOptions{ | ||
files: map[string]string{ | ||
"Dockerfile": "FROM alpine:latest", | ||
"Dockerfile": "FROM " + testImageAlpine, | ||
}, | ||
})) | ||
ctr, err := runEnvbuilder(t, options{env: []string{ | ||
|
@@ -344,7 +346,7 @@ func TestBuildStopStartCached(t *testing.T) { | |
// Ensures that a Git repository with a Dockerfile is cloned and built. | ||
url := createGitServer(t, gitServerOptions{ | ||
files: map[string]string{ | ||
"Dockerfile": "FROM alpine:latest", | ||
"Dockerfile": "FROM " + testImageAlpine, | ||
}, | ||
}) | ||
ctr, err := runEnvbuilder(t, options{env: []string{ | ||
|
@@ -407,7 +409,7 @@ func TestBuildFailsFallback(t *testing.T) { | |
// Ensures that a Git repository with a Dockerfile is cloned and built. | ||
url := createGitServer(t, gitServerOptions{ | ||
files: map[string]string{ | ||
"Dockerfile": `FROM alpine | ||
"Dockerfile": `FROM ` + testImageAlpine + ` | ||
RUN exit 1`, | ||
}, | ||
}) | ||
|
@@ -439,7 +441,7 @@ RUN exit 1`, | |
}) | ||
ctr, err := runEnvbuilder(t, options{env: []string{ | ||
"GIT_URL=" + url, | ||
"FALLBACK_IMAGE=alpine:latest", | ||
"FALLBACK_IMAGE=" + testImageAlpine, | ||
}}) | ||
require.NoError(t, err) | ||
|
||
|
@@ -458,7 +460,7 @@ func TestExitBuildOnFailure(t *testing.T) { | |
_, err := runEnvbuilder(t, options{env: []string{ | ||
"GIT_URL=" + url, | ||
"DOCKERFILE_PATH=Dockerfile", | ||
"FALLBACK_IMAGE=alpine", | ||
"FALLBACK_IMAGE=" + testImageAlpine, | ||
// Ensures that the fallback doesn't work when an image is specified. | ||
"EXIT_ON_BUILD_FAILURE=true", | ||
}}) | ||
|
@@ -486,7 +488,7 @@ func TestContainerEnv(t *testing.T) { | |
"REMOTE_BAR": "${FROM_CONTAINER_ENV}" | ||
} | ||
}`, | ||
".devcontainer/Dockerfile": "FROM alpine:latest\nENV FROM_DOCKERFILE=foo", | ||
".devcontainer/Dockerfile": "FROM " + testImageAlpine + "\nENV FROM_DOCKERFILE=foo", | ||
}, | ||
}) | ||
ctr, err := runEnvbuilder(t, options{env: []string{ | ||
|
@@ -523,7 +525,7 @@ func TestLifecycleScripts(t *testing.T) { | |
"parallel2": ["sh", "-c", "echo parallel2 > /tmp/parallel2"] | ||
} | ||
}`, | ||
".devcontainer/Dockerfile": "FROM alpine:latest\nUSER nobody", | ||
".devcontainer/Dockerfile": "FROM " + testImageAlpine + "\nUSER nobody", | ||
}, | ||
}) | ||
ctr, err := runEnvbuilder(t, options{env: []string{ | ||
|
@@ -559,7 +561,7 @@ func TestPostStartScript(t *testing.T) { | |
".devcontainer/init.sh": `#!/bin/sh | ||
/tmp/post-start.sh | ||
sleep infinity`, | ||
".devcontainer/Dockerfile": `FROM alpine:latest | ||
".devcontainer/Dockerfile": `FROM ` + testImageAlpine + ` | ||
COPY init.sh /bin | ||
RUN chmod +x /bin/init.sh | ||
USER nobody`, | ||
|
@@ -586,7 +588,9 @@ func TestPrivateRegistry(t *testing.T) { | |
t.Parallel() | ||
t.Run("NoAuth", func(t *testing.T) { | ||
t.Parallel() | ||
image := setupPassthroughRegistry(t, "library/alpine", ®istryAuth{ | ||
// Even if something goes wrong with auth, | ||
// the pull will fail as "scratch" is a reserved name. | ||
image := setupPassthroughRegistry(t, "scratch", ®istryAuth{ | ||
Username: "user", | ||
Password: "test", | ||
}) | ||
|
@@ -605,7 +609,7 @@ func TestPrivateRegistry(t *testing.T) { | |
}) | ||
t.Run("Auth", func(t *testing.T) { | ||
t.Parallel() | ||
image := setupPassthroughRegistry(t, "library/alpine", ®istryAuth{ | ||
image := setupPassthroughRegistry(t, "envbuilder-test-alpine:latest", ®istryAuth{ | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is it intentional to use hard-coded name here, compared to e.g. |
||
Username: "user", | ||
Password: "test", | ||
}) | ||
|
@@ -635,7 +639,9 @@ func TestPrivateRegistry(t *testing.T) { | |
}) | ||
t.Run("InvalidAuth", func(t *testing.T) { | ||
t.Parallel() | ||
image := setupPassthroughRegistry(t, "library/alpine", ®istryAuth{ | ||
// Even if something goes wrong with auth, | ||
// the pull will fail as "scratch" is a reserved name. | ||
image := setupPassthroughRegistry(t, "scratch", ®istryAuth{ | ||
Username: "user", | ||
Password: "banana", | ||
}) | ||
|
@@ -672,22 +678,22 @@ type registryAuth struct { | |
|
||
func setupPassthroughRegistry(t *testing.T, image string, auth *registryAuth) string { | ||
t.Helper() | ||
dockerURL, err := url.Parse("https://registry-1.docker.io") | ||
dockerURL, err := url.Parse("http://localhost:5000") | ||
require.NoError(t, err) | ||
proxy := httputil.NewSingleHostReverseProxy(dockerURL) | ||
|
||
// The Docker registry uses short-lived JWTs to authenticate | ||
// anonymously to pull images. To test our MITM auth, we need to | ||
// generate a JWT for the proxy to use. | ||
registry, err := name.NewRegistry("registry-1.docker.io") | ||
registry, err := name.NewRegistry("localhost:5000") | ||
require.NoError(t, err) | ||
proxy.Transport, err = transport.NewWithContext(context.Background(), registry, authn.Anonymous, http.DefaultTransport, []string{}) | ||
require.NoError(t, err) | ||
|
||
srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { | ||
r.Host = "registry-1.docker.io" | ||
r.URL.Host = "registry-1.docker.io" | ||
r.URL.Scheme = "https" | ||
r.Host = "localhost:5000" | ||
r.URL.Host = "localhost:5000" | ||
r.URL.Scheme = "http" | ||
|
||
if auth != nil { | ||
user, pass, ok := r.BasicAuth() | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These seem like they should be phony atm?