Skip to content

Commit e5d6323

Browse files
committed
chore: convert github actions workflow + testdata into go tests
1 parent ef399a8 commit e5d6323

40 files changed

Lines changed: 522 additions & 237 deletions

.github/workflows/ci.yml

Lines changed: 0 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -39,63 +39,3 @@ jobs:
3939
go build -o internal/bin/shim ./internal/cmd/shim
4040
- name: Run go test
4141
run: go test -race -tags docker,dockerd,shim ./...
42-
integration:
43-
runs-on: ubuntu-latest
44-
steps:
45-
- uses: actions/checkout@v6
46-
- uses: jdx/mise-action@v4
47-
with:
48-
install_args: dagger
49-
- name: Run make forge
50-
run: make LOCALBIN=$RUNNER_TEMP
51-
- name: Set path
52-
run: echo $RUNNER_TEMP >> $GITHUB_PATH
53-
- name: Test forge.sock
54-
run: |
55-
forge --fix-dind cloudbuild gcr.io/cloud-builders/docker build testdata/actions/dockerfile
56-
# See https://cloud.google.com/build/docs/configuring-builds/run-bash-scripts.
57-
- name: Run forge cloudbuild --script noshebang
58-
run: |
59-
forge cloudbuild alpine --script testdata/cloudbuild/scripts/sh
60-
- name: Run forge cloudbuild --script bash
61-
run: |
62-
forge cloudbuild bash --script testdata/cloudbuild/scripts/bash
63-
- name: Run forge cloudbuild --script node
64-
run: |
65-
forge cloudbuild node:20 --script testdata/cloudbuild/scripts/node
66-
# See https://cloud.google.com/build/docs/building/build-containers.
67-
- name: Run forge cloudbuild docker
68-
run: |
69-
forge cloudbuild gcr.io/cloud-builders/docker build testdata/actions/dockerfile
70-
- name: Run forge use remote
71-
run: forge use frantjc/forge/testdata/actions/docker@${{ github.sha }}
72-
env:
73-
GITHUB_TOKEN: ${{ github.token }}
74-
- name: Run forge use local
75-
run: forge --no-dind use ./testdata/actions/node
76-
env:
77-
GITHUB_TOKEN: ${{ github.token }}
78-
- name: Run forge use dotdot
79-
run: |
80-
forge use frantjc/forge/testdata/actions/dotdot@${{ github.sha }}
81-
- name: Run forge use dockerfile
82-
run: forge use ./testdata/actions/dockerfile
83-
env:
84-
GITHUB_TOKEN: ${{ github.token }}
85-
- name: Run forge use .
86-
run: |
87-
cd ./testdata/actions/node
88-
forge use .
89-
env:
90-
GITHUB_TOKEN: ${{ github.token }}
91-
- name: Run forge use dind
92-
run: forge use frantjc/forge/testdata/actions/dind@${{ github.sha }}
93-
env:
94-
GITHUB_TOKEN: ${{ github.token }}
95-
- name: Run forge check resource
96-
run: forge --no-dind check mock -v version=v0.0.0
97-
- name: Run forge get resource
98-
run: forge get mock -v version=v0.0.0
99-
- name: Run forge put resource
100-
run: forge put mock -v version=v0.0.0 -p version=v0.0.0
101-
- run: forge cache --clean

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,3 +15,5 @@ version
1515
# mkdocs
1616
site/
1717
gh-pages/
18+
19+
.env

action_dockerfile_test.go

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
//go:build shim && dockerd
2+
3+
package forge_test
4+
5+
import (
6+
"os"
7+
"path/filepath"
8+
"testing"
9+
10+
"github.com/frantjc/forge"
11+
"github.com/frantjc/forge/githubactions"
12+
"github.com/stretchr/testify/require"
13+
)
14+
15+
func TestActionRunDockerfile(t *testing.T) {
16+
cr := Runtime(t)
17+
18+
uses := Uses(t, &githubactions.Metadata{
19+
Name: "test-dockerfile",
20+
Runs: &githubactions.MetadataRuns{
21+
Using: githubactions.RunsUsingDocker,
22+
Image: "Dockerfile",
23+
},
24+
})
25+
require.NoError(t, os.WriteFile(filepath.Join(uses, "Dockerfile"), []byte(`FROM public.ecr.aws/docker/library/alpine
26+
CMD ["/bin/sh", "-c", "exit 0"]
27+
`), 0o644))
28+
29+
action := &forge.Action{Uses: uses}
30+
31+
require.NoError(t, action.Run(t.Context(), cr, forge.WithStreams(Streams(t)), forge.WithMountShim()))
32+
}
33+
34+
func TestActionRunDockerfileWithArgs(t *testing.T) {
35+
cr := Runtime(t)
36+
37+
uses := Uses(t, &githubactions.Metadata{
38+
Name: "test-dockerfile-args",
39+
Runs: &githubactions.MetadataRuns{
40+
Using: githubactions.RunsUsingDocker,
41+
Image: "Dockerfile",
42+
Entrypoint: "/bin/sh",
43+
Args: []string{"-c", "exit 0"},
44+
},
45+
})
46+
require.NoError(t, os.WriteFile(filepath.Join(uses, "Dockerfile"), []byte(`FROM public.ecr.aws/docker/library/alpine
47+
`), 0o644))
48+
49+
action := &forge.Action{Uses: uses}
50+
51+
require.NoError(t, action.Run(t.Context(), cr, forge.WithStreams(Streams(t)), forge.WithMountShim()))
52+
}
53+
54+
func TestActionRunDockerfileWithUnusualName(t *testing.T) {
55+
cr := Runtime(t)
56+
57+
uses := Uses(t, &githubactions.Metadata{
58+
Name: "test-dockerfile-args",
59+
Runs: &githubactions.MetadataRuns{
60+
Using: githubactions.RunsUsingDocker,
61+
Image: "test.Dockerfile",
62+
Entrypoint: "/bin/sh",
63+
Args: []string{"-c", "exit 0"},
64+
},
65+
})
66+
require.NoError(t, os.WriteFile(filepath.Join(uses, "test.Dockerfile"), []byte(`FROM public.ecr.aws/docker/library/alpine
67+
`), 0o644))
68+
69+
action := &forge.Action{Uses: uses}
70+
71+
require.NoError(t, action.Run(t.Context(), cr, forge.WithStreams(Streams(t)), forge.WithMountShim()))
72+
}

action_test.go

Lines changed: 237 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,237 @@
1+
//go:build shim && (docker || dockerd)
2+
3+
package forge_test
4+
5+
import (
6+
"os"
7+
"path/filepath"
8+
"strings"
9+
"testing"
10+
11+
"github.com/frantjc/forge"
12+
"github.com/frantjc/forge/githubactions"
13+
"github.com/stretchr/testify/require"
14+
"sigs.k8s.io/yaml"
15+
)
16+
17+
func Uses(t *testing.T, metadata *githubactions.Metadata) string {
18+
t.Helper()
19+
require.GreaterOrEqual(t, len(githubactions.ActionYAMLFilenames), 1)
20+
b, err := yaml.Marshal(metadata)
21+
require.NoError(t, err)
22+
dir := t.TempDir()
23+
require.NoError(t, os.WriteFile(filepath.Join(dir, githubactions.ActionYAMLFilenames[0]), b, 0o644))
24+
return dir
25+
}
26+
27+
func TestActionRunDocker(t *testing.T) {
28+
cr := Runtime(t)
29+
30+
uses := Uses(t, &githubactions.Metadata{
31+
Name: "test-docker",
32+
Runs: &githubactions.MetadataRuns{
33+
Using: githubactions.RunsUsingDocker,
34+
Image: "docker://public.ecr.aws/docker/library/alpine",
35+
Entrypoint: "/bin/sh",
36+
Args: []string{"-c", "exit 0"},
37+
},
38+
})
39+
40+
action := &forge.Action{Uses: uses}
41+
42+
require.NoError(t, action.Run(t.Context(), cr, forge.WithStreams(Streams(t)), forge.WithMountShim()))
43+
}
44+
45+
func TestActionRunDockerNonzeroExitCode(t *testing.T) {
46+
cr := Runtime(t)
47+
48+
uses := Uses(t, &githubactions.Metadata{
49+
Name: "test-docker-fail",
50+
Runs: &githubactions.MetadataRuns{
51+
Using: githubactions.RunsUsingDocker,
52+
Image: "docker://public.ecr.aws/docker/library/alpine",
53+
Entrypoint: "/bin/sh",
54+
Args: []string{"-c", "exit 1"},
55+
},
56+
})
57+
58+
action := &forge.Action{Uses: uses}
59+
60+
require.Error(t, action.Run(t.Context(), cr, forge.WithStreams(Streams(t)), forge.WithMountShim()))
61+
}
62+
63+
func TestActionRunDockerWithEnv(t *testing.T) {
64+
cr := Runtime(t)
65+
66+
uses := Uses(t, &githubactions.Metadata{
67+
Name: "test-docker-env",
68+
Runs: &githubactions.MetadataRuns{
69+
Using: githubactions.RunsUsingDocker,
70+
Image: "docker://public.ecr.aws/docker/library/alpine",
71+
Entrypoint: "/bin/sh",
72+
Args: []string{"-c", `[ "$MY_VAR" = "hello" ]`},
73+
Env: map[string]string{"MY_VAR": "hello"},
74+
},
75+
})
76+
77+
action := &forge.Action{Uses: uses}
78+
79+
require.NoError(t, action.Run(t.Context(), cr, forge.WithStreams(Streams(t)), forge.WithMountShim()))
80+
}
81+
82+
func TestActionRunDockerWithUserEnv(t *testing.T) {
83+
cr := Runtime(t)
84+
85+
uses := Uses(t, &githubactions.Metadata{
86+
Name: "test-docker-env",
87+
Runs: &githubactions.MetadataRuns{
88+
Using: githubactions.RunsUsingDocker,
89+
Image: "docker://public.ecr.aws/docker/library/alpine",
90+
Entrypoint: "/bin/sh",
91+
Args: []string{"-c", `[ "$MY_VAR" = "hello" ]`},
92+
Env: map[string]string{"MY_VAR": "hello"},
93+
},
94+
})
95+
96+
action := &forge.Action{
97+
Uses: uses,
98+
Env: map[string]string{"MY_VAR": "hello"},
99+
}
100+
101+
require.NoError(t, action.Run(t.Context(), cr, forge.WithStreams(Streams(t)), forge.WithMountShim()))
102+
}
103+
104+
func TestActionRunDockerWithInputs(t *testing.T) {
105+
cr := Runtime(t)
106+
107+
uses := Uses(t, &githubactions.Metadata{
108+
Name: "test-docker-inputs",
109+
Inputs: map[string]githubactions.MetadataInput{
110+
"greeting": {Description: "greeting word", Required: true},
111+
},
112+
Runs: &githubactions.MetadataRuns{
113+
Using: githubactions.RunsUsingDocker,
114+
Image: "docker://public.ecr.aws/docker/library/alpine",
115+
Entrypoint: "/bin/sh",
116+
Args: []string{"-c", `[ "$INPUT_GREETING" = "hello" ]`},
117+
},
118+
})
119+
120+
action := &forge.Action{
121+
Uses: uses,
122+
With: map[string]string{"greeting": "hello"},
123+
}
124+
125+
require.NoError(t, action.Run(t.Context(), cr, forge.WithStreams(Streams(t)), forge.WithMountShim()))
126+
}
127+
128+
func TestActionRunTestdataNode(t *testing.T) {
129+
cr := Runtime(t)
130+
131+
uses := Uses(t, &githubactions.Metadata{
132+
Name: "node",
133+
Runs: &githubactions.MetadataRuns{
134+
Using: githubactions.RunsUsingNode20,
135+
Main: "main.js",
136+
Env: map[string]string{"HELLO": "world"},
137+
},
138+
})
139+
require.NoError(t, os.WriteFile(filepath.Join(uses, "main.js"), []byte(
140+
"if (process.env.HELLO !== 'world') { process.exit(1); }\n",
141+
), 0o644))
142+
143+
action := &forge.Action{Uses: uses}
144+
require.NoError(t, action.Run(t.Context(), cr, forge.WithStreams(Streams(t)), forge.WithMountShim()))
145+
}
146+
147+
func TestActionRunTestdataSaveState(t *testing.T) {
148+
cr := Runtime(t)
149+
150+
uses := Uses(t, &githubactions.Metadata{
151+
Name: "save-state",
152+
Runs: &githubactions.MetadataRuns{
153+
Using: githubactions.RunsUsingDocker,
154+
Image: "docker://public.ecr.aws/docker/library/alpine",
155+
Entrypoint: "/bin/sh",
156+
Args: []string{"-c", `printf 'general=kenobi\n' >> "$GITHUB_STATE"`},
157+
},
158+
})
159+
160+
gc := githubactions.NewGlobalContextFromEnv()
161+
action := &forge.Action{Uses: uses, GlobalContext: gc}
162+
require.NoError(t, action.Run(t.Context(), cr, forge.WithStreams(Streams(t)), forge.WithMountShim()))
163+
require.Equal(t, "kenobi", gc.EnvContext["STATE_general"])
164+
}
165+
166+
func TestActionRunTestdataSetEnv(t *testing.T) {
167+
cr := Runtime(t)
168+
169+
uses := Uses(t, &githubactions.Metadata{
170+
Name: "set-env",
171+
Runs: &githubactions.MetadataRuns{
172+
Using: githubactions.RunsUsingDocker,
173+
Image: "docker://public.ecr.aws/docker/library/alpine",
174+
Entrypoint: "/bin/sh",
175+
Args: []string{"-c", `printf 'GENERAL=kenobi\n' >> "$GITHUB_ENV"`},
176+
},
177+
})
178+
179+
gc := githubactions.NewGlobalContextFromEnv()
180+
action := &forge.Action{Uses: uses, GlobalContext: gc}
181+
require.NoError(t, action.Run(t.Context(), cr, forge.WithStreams(Streams(t)), forge.WithMountShim()))
182+
require.Equal(t, "kenobi", gc.EnvContext["GENERAL"])
183+
}
184+
185+
func TestActionRunTestdataSetOutput(t *testing.T) {
186+
cr := Runtime(t)
187+
188+
uses := Uses(t, &githubactions.Metadata{
189+
Name: "set-output",
190+
Runs: &githubactions.MetadataRuns{
191+
Using: githubactions.RunsUsingDocker,
192+
Image: "docker://public.ecr.aws/docker/library/alpine",
193+
Entrypoint: "/bin/sh",
194+
Args: []string{"-c", `printf 'general=kenobi\n' >> "$GITHUB_OUTPUT"`},
195+
},
196+
})
197+
198+
gc := githubactions.NewGlobalContextFromEnv()
199+
action := &forge.Action{ID: "test", Uses: uses, GlobalContext: gc}
200+
require.NoError(t, action.Run(t.Context(), cr, forge.WithStreams(Streams(t)), forge.WithMountShim()))
201+
require.Equal(t, "kenobi", gc.StepsContext["test"].Outputs["general"])
202+
}
203+
204+
func TestActionRunTestdataYmlVYaml(t *testing.T) {
205+
cr := Runtime(t)
206+
207+
require.Len(t, githubactions.ActionYAMLFilenames, 2)
208+
209+
expected := "yml"
210+
uses := Uses(t, &githubactions.Metadata{
211+
Name: "yml-v-yaml",
212+
Runs: &githubactions.MetadataRuns{
213+
Using: githubactions.RunsUsingDocker,
214+
Image: "docker://public.ecr.aws/docker/library/alpine",
215+
Entrypoint: "echo",
216+
Args: []string{expected},
217+
},
218+
})
219+
220+
b, err := yaml.Marshal(&githubactions.Metadata{
221+
Name: "yml-v-yaml",
222+
Runs: &githubactions.MetadataRuns{
223+
Using: githubactions.RunsUsingDocker,
224+
Image: "docker://public.ecr.aws/docker/library/alpine",
225+
Entrypoint: "echo",
226+
Args: []string{"yaml"},
227+
},
228+
})
229+
require.NoError(t, err)
230+
require.NoError(t, os.WriteFile(filepath.Join(uses, githubactions.ActionYAMLFilenames[1]), b, 0o644))
231+
232+
action := &forge.Action{Uses: uses}
233+
streams, stdout := StreamsCaptureStdout(t)
234+
require.NoError(t, action.Run(t.Context(), cr, forge.WithStreams(streams), forge.WithMountShim()))
235+
actual := strings.TrimSpace(stdout.String())
236+
require.Equal(t, expected, actual)
237+
}

cloudbuild.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -109,11 +109,11 @@ func stepToContainerConfigAndScript(step *cloudbuild.Step, home string, image Im
109109
}
110110

111111
if step.Script != "" {
112-
if step.Entrypoint != "" || len(step.Args) > 0 {
113-
return nil, "", fmt.Errorf("cannot specify args or entrypoint with script")
112+
if step.Entrypoint != "" {
113+
return nil, "", fmt.Errorf("cannot specify entrypoint with script")
114114
}
115115

116-
containerConfig.Entrypoint = []string{filepath.Join(opt.WorkingDir, ScriptName)}
116+
containerConfig.Entrypoint = append([]string{filepath.Join(opt.WorkingDir, ScriptName)}, step.Args...)
117117
} else {
118118
if lenArgs := len(step.Args); step.Entrypoint == "" || lenArgs == 0 {
119119
config, err := image.Config()

0 commit comments

Comments
 (0)