1// SPDX-License-Identifier: MIT
2
3package executor
4
5import (
6 "strings"
7 "testing"
8)
9
10const (
11 cacheTestURL = "http://127.0.0.1:9089/"
12 cacheTestToken = "eyJqIjoiMSJ9.c2lnbmF0dXJl"
13)
14
15func withCache(c *Config) { c.CacheURL, c.CacheToken = cacheTestURL, cacheTestToken }
16
17const envAction = `name: e
18description: d
19runs:
20 using: node20
21 main: main.sh
22`
23
24const envScript = "echo \"url=[$ACTIONS_CACHE_URL] rurl=[$ACTIONS_RUNTIME_URL] token=[$ACTIONS_RUNTIME_TOKEN] v2=[${ACTIONS_CACHE_SERVICE_V2-unset}] results=[${ACTIONS_RESULTS_URL-unset}]\"\n"
25
26// NodeScriptActionHandler.cs:55-72: a node action gets the runtime variables. The
27// URL is the base the toolkit appends "_apis/artifactcache/…" to (it ends with a
28// slash), ACTIONS_CACHE_SERVICE_V2 is never set, and the token is masked in the
29// log.
30func TestNodeActionGetsCacheEnv(t *testing.T) {
31 rec, res := actionRun(t, files{".github/actions/e/action.yml": envAction, ".github/actions/e/main.sh": envScript},
32 " - uses: ./.github/actions/e\n", withCache)
33 if res.Conclusion != ConclusionSuccess {
34 t.Fatalf("%+v\n%s", res, logOf(rec.steps[1]))
35 }
36 got := logOf(rec.step(t, "Run ./.github/actions/e"))
37 want := "url=[" + cacheTestURL + "] rurl=[" + cacheTestURL + "] token=[***] v2=[unset] results=[unset]"
38 if !strings.Contains(got, want) {
39 t.Errorf("want %q in\n%s", want, got)
40 }
41 if strings.Contains(got, cacheTestToken) {
42 t.Errorf("the token is in the log:\n%s", got)
43 }
44}
45
46// A run: step is not an action handler: it gets none of it (the official runner
47// sets these for actions only), and a job without a cache service sets nothing.
48func TestCacheEnvOnlyForActions(t *testing.T) {
49 rec, res := actionRun(t, files{}, " - run: echo \"[$ACTIONS_CACHE_URL][$ACTIONS_RUNTIME_TOKEN]\"\n", withCache)
50 if res.Conclusion != ConclusionSuccess {
51 t.Fatalf("%+v", res)
52 }
53 if got := logOf(rec.step(t, "Run echo \"[$ACTIONS_CACHE_URL][$ACTIONS_RUNTIME_TOKEN]\"")); !strings.HasSuffix(strings.TrimRight(got, "\n"), "\n[][]") {
54 t.Errorf("run step env:\n%s", got)
55 }
56 rec, res = actionRun(t, files{".github/actions/e/action.yml": envAction, ".github/actions/e/main.sh": envScript},
57 " - uses: ./.github/actions/e\n", nil)
58 if res.Conclusion != ConclusionSuccess {
59 t.Fatalf("%+v", res)
60 }
61 if got := logOf(rec.step(t, "Run ./.github/actions/e")); !strings.Contains(got, "url=[] rurl=[] token=[]") {
62 t.Errorf("no cache service, no variables:\n%s", got)
63 }
64}
65
66// ContainerActionHandler.cs:219-236: a docker action gets them too, passed by
67// name to "docker run" like the other variables.
68func TestDockerActionGetsCacheEnv(t *testing.T) {
69 d, lf := fakeDocker(t, 0)
70 rec, res := actionRun(t, files{}, " - uses: docker://alpine:3.20\n", func(c *Config) {
71 c.Actions.DockerPath = d
72 withCache(c)
73 })
74 if res.Conclusion != ConclusionSuccess {
75 t.Fatalf("%+v %v", res, rec.names())
76 }
77 cs := calls(t, lf)
78 if len(cs) != 2 {
79 t.Fatalf("calls %v", cs)
80 }
81 args := "\n" + strings.Join(cs[1], "\n") + "\n"
82 for _, n := range []string{"ACTIONS_CACHE_URL", "ACTIONS_RUNTIME_URL", "ACTIONS_RUNTIME_TOKEN"} {
83 if !strings.Contains(args, "\n-e\n"+n+"\n") {
84 t.Errorf("docker run lacks -e %s:\n%s", n, args)
85 }
86 }
87 if strings.Contains(args, "ACTIONS_CACHE_SERVICE_V2") || strings.Contains(args, cacheTestToken) {
88 t.Errorf("service v2 or the token value on the command line:\n%s", args)
89 }
90 if run := logOf(rec.steps[2]); strings.Contains(run, cacheTestToken) {
91 t.Errorf("the token is in the log:\n%s", run)
92 }
93}