Skip to content

Commit e454113

Browse files
committed
feat: generate github workflow for remote build
- Add YAML structure types for workflow generation - Generate hard coded remote-build-and-deploy workflow with checkout, func cli setup, and deploy steps - Validate workflow structure and content in tests - Export NewCIConfig for external use Issue SRVOCF-744 Signed-off-by: Stanislav Jakuschevskij <sjakusch@redhat.com>
1 parent 2b2cc43 commit e454113

File tree

2 files changed

+110
-41
lines changed

2 files changed

+110
-41
lines changed

cmd/config_ci.go

Lines changed: 53 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -29,13 +29,13 @@ type CIConfig struct {
2929
}
3030

3131
func NewDefaultCIConfig() CIConfig {
32-
return newCIConfig(
32+
return NewCIConfig(
3333
".github/workflows",
34-
"local-build-remote-deploy.yaml",
34+
"remote-build-and-deploy.yaml",
3535
)
3636
}
3737

38-
func newCIConfig(workflowDir, workflowFile string) CIConfig {
38+
func NewCIConfig(workflowDir, workflowFile string) CIConfig {
3939
return CIConfig{
4040
workflowDir,
4141
workflowFile,
@@ -44,11 +44,37 @@ func newCIConfig(workflowDir, workflowFile string) CIConfig {
4444
}
4545
}
4646

47+
type GithubWorkflow struct {
48+
Name string `yaml:"name"`
49+
On WorkflowTriggers `yaml:"on"`
50+
Jobs map[string]Job `yaml:"jobs"`
51+
}
52+
53+
type WorkflowTriggers struct {
54+
Push *PushTrigger `yaml:"push,omitempty"`
55+
}
56+
57+
type PushTrigger struct {
58+
Branches []string `yaml:"branches,omitempty"`
59+
}
60+
61+
type Job struct {
62+
RunsOn string `yaml:"runs-on"`
63+
Steps []Step `yaml:"steps"`
64+
}
65+
66+
type Step struct {
67+
Name string `yaml:"name,omitempty"`
68+
Uses string `yaml:"uses,omitempty"`
69+
Run string `yaml:"run,omitempty"`
70+
With map[string]string `yaml:"with,omitempty"`
71+
}
72+
4773
func runConfigCIGithub(
48-
loaderSaver common.FunctionLoaderSaver,
74+
fnLoaderSaver common.FunctionLoaderSaver,
4975
ciConfig CIConfig,
5076
) error {
51-
f, err := initConfigCommand(loaderSaver)
77+
f, err := initConfigCommand(fnLoaderSaver)
5278
if err != nil {
5379
return err
5480
}
@@ -58,7 +84,28 @@ func runConfigCIGithub(
5884
return err
5985
}
6086

61-
workflowYamlContent := "hello world"
87+
workflowYamlContent := `name: Remote Build and Deploy
88+
89+
on:
90+
push:
91+
branches:
92+
- main
93+
94+
jobs:
95+
deploy:
96+
runs-on: ubuntu-latest
97+
steps:
98+
- name: Checkout code
99+
uses: actions/checkout@v4
100+
101+
- name: Install func cli
102+
uses: gauron99/knative-func-action@main
103+
with:
104+
version: knative-v1.19.1
105+
name: func
106+
107+
- name: Deploy function
108+
run: func deploy --remote`
62109
fnWorkflowYamlPath := filepath.Join(fnWorkflowDirPath, ciConfig.GithubWorkflowFile)
63110
if err := os.WriteFile(fnWorkflowYamlPath, []byte(workflowYamlContent), ciConfig.filePerm); err != nil {
64111
return err

cmd/config_ci_test.go

Lines changed: 57 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import (
55
"path/filepath"
66
"testing"
77

8-
"github.com/spf13/cobra"
8+
"gopkg.in/yaml.v3"
99
"gotest.tools/v3/assert"
1010
fnCmd "knative.dev/func/cmd"
1111
"knative.dev/func/cmd/common"
@@ -17,48 +17,63 @@ import (
1717
func TestNewConfigCICmd_CISubcommandAndGithubOptionExist(t *testing.T) {
1818
// leave 'ci --github' to make this test explicitly use this subcommand
1919
opts := opts{withFuncInTempDir: true, args: []string{"ci", "--github"}}
20-
cmd, _ := setupConfigCmd(t, opts)
20+
result := runConfigCiGithubCmd(t, opts)
2121

22-
executeSuccess(t, cmd)
22+
assert.NilError(t, result.err)
2323
}
2424

2525
func TestNewConfigCICmd_FailsWhenNotInitialized(t *testing.T) {
2626
expectedErrMsg := fn.NewErrNotInitialized(fnTest.Cwd()).Error()
27-
cmd, _ := setupConfigCmd(t, opts{})
2827

29-
err := cmd.Execute()
28+
result := runConfigCiGithubCmd(t, opts{})
3029

31-
assert.Error(t, err, expectedErrMsg)
30+
assert.Error(t, result.err, expectedErrMsg)
3231
}
3332

3433
func TestNewConfigCICmd_SuccessWhenInitialized(t *testing.T) {
35-
cmd, _ := setupConfigCmd(t, opts{withFuncInTempDir: true})
34+
result := runConfigCiGithubCmd(t, opts{withFuncInTempDir: true})
3635

37-
executeSuccess(t, cmd)
36+
assert.NilError(t, result.err)
3837
}
3938

4039
func TestNewConfigCICmd_CreatesGithubWorkflowDirectory(t *testing.T) {
41-
cmd, ta := setupConfigCmd(t, opts{withFuncInTempDir: true})
42-
expectedWorkflowPath := filepath.Join(ta.f.Root, ta.ciConfig.GithubWorkflowDir)
43-
44-
executeSuccess(t, cmd)
40+
result := runConfigCiGithubCmd(t, opts{withFuncInTempDir: true})
41+
assert.NilError(t, result.err)
4542

43+
expectedWorkflowPath := filepath.Join(result.f.Root, result.ciConfig.GithubWorkflowDir)
4644
_, err := os.Stat(expectedWorkflowPath)
4745
assert.NilError(t, err)
4846
}
4947

5048
func TestNewConfigCICmd_GeneratesLocalWorkflowFile(t *testing.T) {
51-
cmd, ta := setupConfigCmd(t, opts{withFuncInTempDir: true})
52-
expectedWorkflowPath := filepath.Join(ta.f.Root, ta.ciConfig.GithubWorkflowDir)
53-
expectedWorkflowFile := filepath.Join(expectedWorkflowPath, ta.ciConfig.GithubWorkflowFile)
49+
result := runConfigCiGithubCmd(t, opts{withFuncInTempDir: true})
50+
assert.NilError(t, result.err)
5451

55-
executeSuccess(t, cmd)
52+
_ = assertWorkflowFileExists(t, result)
53+
}
5654

57-
_, err := os.Stat(expectedWorkflowPath)
58-
assert.NilError(t, err)
55+
func TestNewConfigCICmd_WorkflowYAMLHasCorrectStructure(t *testing.T) {
56+
result := runConfigCiGithubCmd(t, opts{withFuncInTempDir: true})
57+
assert.NilError(t, result.err)
58+
59+
workflowFilepath := assertWorkflowFileExists(t, result)
5960

60-
_, err = os.Stat(expectedWorkflowFile)
61+
var expectedWorkflow fnCmd.GithubWorkflow
62+
workflowAsBytes, err := os.ReadFile(workflowFilepath)
6163
assert.NilError(t, err)
64+
err = yaml.Unmarshal(workflowAsBytes, &expectedWorkflow)
65+
assert.NilError(t, err)
66+
assert.Equal(t, expectedWorkflow.Name, "Remote Build and Deploy")
67+
assert.Equal(t, expectedWorkflow.On.Push.Branches[0], "main")
68+
assert.Equal(t, expectedWorkflow.Jobs["deploy"].RunsOn, "ubuntu-latest")
69+
assert.Equal(t, expectedWorkflow.Jobs["deploy"].Steps[0].Name, "Checkout code")
70+
assert.Equal(t, expectedWorkflow.Jobs["deploy"].Steps[0].Uses, "actions/checkout@v4")
71+
assert.Equal(t, expectedWorkflow.Jobs["deploy"].Steps[1].Name, "Install func cli")
72+
assert.Equal(t, expectedWorkflow.Jobs["deploy"].Steps[1].Uses, "gauron99/knative-func-action@main")
73+
assert.Equal(t, expectedWorkflow.Jobs["deploy"].Steps[1].With["version"], "knative-v1.19.1")
74+
assert.Equal(t, expectedWorkflow.Jobs["deploy"].Steps[1].With["name"], "func")
75+
assert.Equal(t, expectedWorkflow.Jobs["deploy"].Steps[2].Name, "Deploy function")
76+
assert.Equal(t, expectedWorkflow.Jobs["deploy"].Steps[2].Run, "func deploy --remote")
6277
}
6378

6479
// START: Testing Framework
@@ -68,44 +83,51 @@ type opts struct {
6883
args []string // default: ci --github
6984
}
7085

71-
type testArtifacts struct {
86+
type result struct {
7287
f fn.Function
7388
ciConfig fnCmd.CIConfig
89+
err error
7490
}
7591

76-
func setupConfigCmd(
92+
func runConfigCiGithubCmd(
7793
t *testing.T,
7894
opts opts,
79-
) (*cobra.Command, testArtifacts) {
95+
) result {
8096
t.Helper()
8197

82-
ta := testArtifacts{
83-
fn.Function{},
84-
fnCmd.NewDefaultCIConfig(),
85-
}
86-
98+
f := fn.Function{}
8799
if opts.withFuncInTempDir {
88-
ta.f = cmdTest.CreateFuncInTempDir(t, "github-ci-func")
100+
f = cmdTest.CreateFuncInTempDir(t, "github-ci-func")
89101
}
90102

91103
args := opts.args
92104
if len(opts.args) == 0 {
93105
args = []string{"ci", "--github"}
94106
}
95107

96-
result := fnCmd.NewConfigCmd(
108+
ciConfig := fnCmd.NewDefaultCIConfig()
109+
cmd := fnCmd.NewConfigCmd(
97110
common.DefaultLoaderSaver,
98111
fnCmd.NewClient,
99-
ta.ciConfig,
112+
ciConfig,
100113
)
101-
result.SetArgs(args)
114+
cmd.SetArgs(args)
115+
116+
err := cmd.Execute()
102117

103-
return result, ta
118+
return result{
119+
f,
120+
ciConfig,
121+
err,
122+
}
104123
}
105124

106-
func executeSuccess(t *testing.T, cmd *cobra.Command) {
125+
func assertWorkflowFileExists(t *testing.T, result result) string {
107126
t.Helper()
127+
filepath := filepath.Join(result.f.Root, result.ciConfig.GithubWorkflowDir, result.ciConfig.GithubWorkflowFile)
128+
exists, _ := fnTest.FileExists(t, filepath)
108129

109-
err := cmd.Execute()
110-
assert.NilError(t, err)
130+
assert.Assert(t, exists, filepath+" does not exist")
131+
132+
return filepath
111133
}

0 commit comments

Comments
 (0)