Skip to content

Commit 636c8a3

Browse files
feat: specify matrix on command line (#1675)
* added matrix option * select the correct subset of matrix configuration after producing all the matrix configuration * add tests * update readme * lint fix * remove matrix from readme --------- Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com>
1 parent 09de42f commit 636c8a3

File tree

5 files changed

+144
-35
lines changed

5 files changed

+144
-35
lines changed

cmd/input.go

+1
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ type Input struct {
4747
remoteName string
4848
replaceGheActionWithGithubCom []string
4949
replaceGheActionTokenWithGithubCom string
50+
matrix []string
5051
}
5152

5253
func (i *Input) resolve(path string) string {

cmd/root.go

+23
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,7 @@ func Execute(ctx context.Context, version string) {
6666
rootCmd.Flags().BoolVar(&input.autoRemove, "rm", false, "automatically remove container(s)/volume(s) after a workflow(s) failure")
6767
rootCmd.Flags().StringArrayVarP(&input.replaceGheActionWithGithubCom, "replace-ghe-action-with-github.lhy31512.workers.dev", "", []string{}, "If you are using GitHub Enterprise Server and allow specified actions from GitHub (github.com), you can set actions on this. (e.g. --replace-ghe-action-with-github.lhy31512.workers.dev =github/super-linter)")
6868
rootCmd.Flags().StringVar(&input.replaceGheActionTokenWithGithubCom, "replace-ghe-action-token-with-github.lhy31512.workers.dev", "", "If you are using replace-ghe-action-with-github.lhy31512.workers.dev and you want to use private actions on GitHub, you have to set personal access token")
69+
rootCmd.Flags().StringArrayVarP(&input.matrix, "matrix", "", []string{}, "specify which matrix configuration to include (e.g. --matrix java:13")
6970
rootCmd.PersistentFlags().StringVarP(&input.actor, "actor", "a", "nektos/act", "user that triggered the event")
7071
rootCmd.PersistentFlags().StringVarP(&input.workflowsPath, "workflows", "W", "./.github/workflows/", "path to workflow file(s)")
7172
rootCmd.PersistentFlags().BoolVarP(&input.noWorkflowRecurse, "no-recurse", "", false, "Flag to disable running workflows from subdirectories of specified path in '--workflows'/'-W' flag")
@@ -295,6 +296,24 @@ func readEnvs(path string, envs map[string]string) bool {
295296
return false
296297
}
297298

299+
func parseMatrix(matrix []string) map[string]map[string]bool {
300+
// each matrix entry should be of the form - string:string
301+
r := regexp.MustCompile(":")
302+
matrixes := make(map[string]map[string]bool)
303+
for _, m := range matrix {
304+
matrix := r.Split(m, 2)
305+
if len(matrix) < 2 {
306+
log.Fatalf("Invalid matrix format. Failed to parse %s", m)
307+
} else {
308+
if _, ok := matrixes[matrix[0]]; !ok {
309+
matrixes[matrix[0]] = make(map[string]bool)
310+
}
311+
matrixes[matrix[0]][matrix[1]] = true
312+
}
313+
}
314+
return matrixes
315+
}
316+
298317
//nolint:gocyclo
299318
func newRunCommand(ctx context.Context, input *Input) func(*cobra.Command, []string) error {
300319
return func(cmd *cobra.Command, args []string) error {
@@ -329,6 +348,9 @@ func newRunCommand(ctx context.Context, input *Input) func(*cobra.Command, []str
329348
secrets := newSecrets(input.secrets)
330349
_ = readEnvs(input.Secretfile(), secrets)
331350

351+
matrixes := parseMatrix(input.matrix)
352+
log.Debugf("Evaluated matrix inclusions: %v", matrixes)
353+
332354
planner, err := model.NewWorkflowPlanner(input.WorkflowsPath(), input.noWorkflowRecurse)
333355
if err != nil {
334356
return err
@@ -508,6 +530,7 @@ func newRunCommand(ctx context.Context, input *Input) func(*cobra.Command, []str
508530
RemoteName: input.remoteName,
509531
ReplaceGheActionWithGithubCom: input.replaceGheActionWithGithubCom,
510532
ReplaceGheActionTokenWithGithubCom: input.replaceGheActionTokenWithGithubCom,
533+
Matrix: matrixes,
511534
}
512535
r, err := runner.New(config)
513536
if err != nil {

pkg/runner/runner.go

+58-35
Original file line numberDiff line numberDiff line change
@@ -20,40 +20,41 @@ type Runner interface {
2020

2121
// Config contains the config for a new runner
2222
type Config struct {
23-
Actor string // the user that triggered the event
24-
Workdir string // path to working directory
25-
BindWorkdir bool // bind the workdir to the job container
26-
EventName string // name of event to run
27-
EventPath string // path to JSON file to use for event.json in containers
28-
DefaultBranch string // name of the main branch for this repository
29-
ReuseContainers bool // reuse containers to maintain state
30-
ForcePull bool // force pulling of the image, even if already present
31-
ForceRebuild bool // force rebuilding local docker image action
32-
LogOutput bool // log the output from docker run
33-
JSONLogger bool // use json or text logger
34-
Env map[string]string // env for containers
35-
Inputs map[string]string // manually passed action inputs
36-
Secrets map[string]string // list of secrets
37-
Token string // GitHub token
38-
InsecureSecrets bool // switch hiding output when printing to terminal
39-
Platforms map[string]string // list of platforms
40-
Privileged bool // use privileged mode
41-
UsernsMode string // user namespace to use
42-
ContainerArchitecture string // Desired OS/architecture platform for running containers
43-
ContainerDaemonSocket string // Path to Docker daemon socket
44-
ContainerOptions string // Options for the job container
45-
UseGitIgnore bool // controls if paths in .gitignore should not be copied into container, default true
46-
GitHubInstance string // GitHub instance to use, default "github.com"
47-
ContainerCapAdd []string // list of kernel capabilities to add to the containers
48-
ContainerCapDrop []string // list of kernel capabilities to remove from the containers
49-
AutoRemove bool // controls if the container is automatically removed upon workflow completion
50-
ArtifactServerPath string // the path where the artifact server stores uploads
51-
ArtifactServerAddr string // the address the artifact server binds to
52-
ArtifactServerPort string // the port the artifact server binds to
53-
NoSkipCheckout bool // do not skip actions/checkout
54-
RemoteName string // remote name in local git repo config
55-
ReplaceGheActionWithGithubCom []string // Use actions from GitHub Enterprise instance to GitHub
56-
ReplaceGheActionTokenWithGithubCom string // Token of private action repo on GitHub.
23+
Actor string // the user that triggered the event
24+
Workdir string // path to working directory
25+
BindWorkdir bool // bind the workdir to the job container
26+
EventName string // name of event to run
27+
EventPath string // path to JSON file to use for event.json in containers
28+
DefaultBranch string // name of the main branch for this repository
29+
ReuseContainers bool // reuse containers to maintain state
30+
ForcePull bool // force pulling of the image, even if already present
31+
ForceRebuild bool // force rebuilding local docker image action
32+
LogOutput bool // log the output from docker run
33+
JSONLogger bool // use json or text logger
34+
Env map[string]string // env for containers
35+
Inputs map[string]string // manually passed action inputs
36+
Secrets map[string]string // list of secrets
37+
Token string // GitHub token
38+
InsecureSecrets bool // switch hiding output when printing to terminal
39+
Platforms map[string]string // list of platforms
40+
Privileged bool // use privileged mode
41+
UsernsMode string // user namespace to use
42+
ContainerArchitecture string // Desired OS/architecture platform for running containers
43+
ContainerDaemonSocket string // Path to Docker daemon socket
44+
ContainerOptions string // Options for the job container
45+
UseGitIgnore bool // controls if paths in .gitignore should not be copied into container, default true
46+
GitHubInstance string // GitHub instance to use, default "github.com"
47+
ContainerCapAdd []string // list of kernel capabilities to add to the containers
48+
ContainerCapDrop []string // list of kernel capabilities to remove from the containers
49+
AutoRemove bool // controls if the container is automatically removed upon workflow completion
50+
ArtifactServerPath string // the path where the artifact server stores uploads
51+
ArtifactServerAddr string // the address the artifact server binds to
52+
ArtifactServerPort string // the port the artifact server binds to
53+
NoSkipCheckout bool // do not skip actions/checkout
54+
RemoteName string // remote name in local git repo config
55+
ReplaceGheActionWithGithubCom []string // Use actions from GitHub Enterprise instance to GitHub
56+
ReplaceGheActionTokenWithGithubCom string // Token of private action repo on GitHub.
57+
Matrix map[string]map[string]bool // Matrix config to run
5758
}
5859

5960
type caller struct {
@@ -116,7 +117,10 @@ func (runner *runnerImpl) NewPlanExecutor(plan *model.Plan) common.Executor {
116117
log.Errorf("Error while evaluating matrix: %v", err)
117118
}
118119
}
119-
matrixes := job.GetMatrixes()
120+
121+
matrixes := selectMatrixes(job.GetMatrixes(), runner.config.Matrix)
122+
log.Debugf("Final matrix after applying user inclusions '%v'", matrixes)
123+
120124
maxParallel := 4
121125
if job.Strategy != nil {
122126
maxParallel = job.Strategy.MaxParallel
@@ -171,6 +175,25 @@ func handleFailure(plan *model.Plan) common.Executor {
171175
}
172176
}
173177

178+
func selectMatrixes(originalMatrixes []map[string]interface{}, targetMatrixValues map[string]map[string]bool) []map[string]interface{} {
179+
matrixes := make([]map[string]interface{}, 0)
180+
for _, original := range originalMatrixes {
181+
flag := true
182+
for key, val := range original {
183+
if allowedVals, ok := targetMatrixValues[key]; ok {
184+
valToString := fmt.Sprintf("%v", val)
185+
if _, ok := allowedVals[valToString]; !ok {
186+
flag = false
187+
}
188+
}
189+
}
190+
if flag {
191+
matrixes = append(matrixes, original)
192+
}
193+
}
194+
return matrixes
195+
}
196+
174197
func (runner *runnerImpl) newRunContext(ctx context.Context, run *model.Run, matrix map[string]interface{}) *RunContext {
175198
rc := &RunContext{
176199
Config: runner.config,

pkg/runner/runner_test.go

+28
Original file line numberDiff line numberDiff line change
@@ -186,6 +186,7 @@ func (j *TestJobFileInfo) runTest(ctx context.Context, t *testing.T, cfg *Config
186186
Inputs: cfg.Inputs,
187187
GitHubInstance: "github.com",
188188
ContainerArchitecture: cfg.ContainerArchitecture,
189+
Matrix: cfg.Matrix,
189190
}
190191

191192
runner, err := New(runnerConfig)
@@ -584,3 +585,30 @@ func TestRunEventPullRequest(t *testing.T) {
584585

585586
tjfi.runTest(context.Background(), t, &Config{EventPath: filepath.Join(workdir, workflowPath, "event.json")})
586587
}
588+
589+
func TestRunMatrixWithUserDefinedInclusions(t *testing.T) {
590+
if testing.Short() {
591+
t.Skip("skipping integration test")
592+
}
593+
workflowPath := "matrix-with-user-inclusions"
594+
595+
tjfi := TestJobFileInfo{
596+
workdir: workdir,
597+
workflowPath: workflowPath,
598+
eventName: "push",
599+
errorMessage: "",
600+
platforms: platforms,
601+
}
602+
603+
matrix := map[string]map[string]bool{
604+
"node": {
605+
"8": true,
606+
"8.x": true,
607+
},
608+
"os": {
609+
"ubuntu-18.04": true,
610+
},
611+
}
612+
613+
tjfi.runTest(context.Background(), t, &Config{Matrix: matrix})
614+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
name: matrix-with-user-inclusions
2+
on: push
3+
4+
jobs:
5+
build:
6+
name: PHP ${{ matrix.os }} ${{ matrix.node}}
7+
runs-on: ubuntu-latest
8+
steps:
9+
- run: |
10+
echo ${NODE_VERSION} | grep 8
11+
echo ${OS_VERSION} | grep ubuntu-18.04
12+
env:
13+
NODE_VERSION: ${{ matrix.node }}
14+
OS_VERSION: ${{ matrix.os }}
15+
strategy:
16+
matrix:
17+
os: [ubuntu-18.04, macos-latest]
18+
node: [4, 6, 8, 10]
19+
exclude:
20+
- os: macos-latest
21+
node: 4
22+
include:
23+
- os: ubuntu-16.04
24+
node: 10
25+
26+
test:
27+
runs-on: ubuntu-latest
28+
strategy:
29+
matrix:
30+
node: [8.x, 10.x, 12.x, 13.x]
31+
steps:
32+
- run: echo ${NODE_VERSION} | grep 8.x
33+
env:
34+
NODE_VERSION: ${{ matrix.node }}

0 commit comments

Comments
 (0)