Skip to content

Commit 82faa71

Browse files
committed
feat: gate CI config behind feature flag
Add FUNC_ENABLE_CI_CONFIG environment variable that must be set to 'true' to use the 'func config ci' command. This allows controlled enablement of the CI configuration feature during development and testing. Test improvements: - Add feature flag requirement test - Refactor test helpers (defaultOpts, assertion functions) - Update all tests to explicitly enable feature flag Issue SRVOCF-744 Signed-off-by: Stanislav Jakuschevskij <sjakusch@redhat.com>
1 parent 45cbfe9 commit 82faa71

File tree

3 files changed

+87
-70
lines changed

3 files changed

+87
-70
lines changed

cmd/ci/config.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -160,6 +160,8 @@ func (b *ciConfigBuilder) Build() CIConfig {
160160
}
161161

162162
const (
163+
ConfigCIFeatureFlag = "FUNC_ENABLE_CI_CONFIG"
164+
163165
GithubOption = "github"
164166
DefaultGithub = false
165167

cmd/config_ci.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
package cmd
22

33
import (
4+
"fmt"
5+
"os"
6+
47
"github.com/spf13/cobra"
58

69
"knative.dev/func/cmd/ci"
@@ -97,6 +100,9 @@ func runConfigCIGithub(
97100
cmd *cobra.Command,
98101
fnLoaderSaver common.FunctionLoaderSaver,
99102
) error {
103+
if os.Getenv(ci.ConfigCIFeatureFlag) != "true" {
104+
return fmt.Errorf("Set %s to 'true' to use this feature", ci.ConfigCIFeatureFlag)
105+
}
100106

101107
// TODO(twoGiants): viper propagation broken => can't test with flags --use-registry-login
102108
// or --workflow-name => flags aren't propagated to viper

cmd/config_ci_test.go

Lines changed: 79 additions & 70 deletions
Original file line numberDiff line numberDiff line change
@@ -16,107 +16,88 @@ import (
1616
fnTest "knative.dev/func/pkg/testing"
1717
)
1818

19+
func TestNewConfigCICmd_RequiresFeatureFlag(t *testing.T) {
20+
result := runConfigCiGithubCmd(t, opts{enableFeature: false})
21+
22+
assert.Error(t, result.executeErr, "Set FUNC_ENABLE_CI_CONFIG to 'true' to use this feature")
23+
}
24+
1925
func TestNewConfigCICmd_CISubcommandAndGithubOptionExist(t *testing.T) {
2026
// leave 'ci --github' to make this test explicitly use this subcommand
21-
options := opts{withFuncInTempDir: true, args: []string{"ci", "--github"}}
27+
opts := opts{withFuncInTempDir: true, enableFeature: true, args: []string{"ci", "--github"}}
2228

23-
result := runConfigCiGithubCmd(t, options)
29+
result := runConfigCiGithubCmd(t, opts)
2430

2531
assert.NilError(t, result.executeErr)
2632
}
2733

2834
func TestNewConfigCICmd_FailsWhenNotInitialized(t *testing.T) {
2935
expectedErrMsg := fn.NewErrNotInitialized(fnTest.Cwd()).Error()
3036

31-
result := runConfigCiGithubCmd(t, opts{})
37+
result := runConfigCiGithubCmd(t, opts{enableFeature: true})
3238

3339
assert.Error(t, result.executeErr, expectedErrMsg)
3440
}
3541

3642
func TestNewConfigCICmd_SuccessWhenInitialized(t *testing.T) {
37-
options := opts{withFuncInTempDir: true}
38-
39-
result := runConfigCiGithubCmd(t, options)
43+
result := runConfigCiGithubCmd(t, defaultOpts())
4044

4145
assert.NilError(t, result.executeErr)
4246
}
4347

4448
func TestNewConfigCICmd_CreatesGithubWorkflowDirectory(t *testing.T) {
45-
options := opts{withFuncInTempDir: true}
46-
47-
result := runConfigCiGithubCmd(t, options)
49+
result := runConfigCiGithubCmd(t, defaultOpts())
4850

4951
assert.NilError(t, result.executeErr)
5052
_, err := os.Stat(result.ciConfig.FnGithubWorkflowDir(result.f.Root))
5153
assert.NilError(t, err)
5254
}
5355

5456
func TestNewConfigCICmd_GeneratesWorkflowFile(t *testing.T) {
55-
options := opts{withFuncInTempDir: true}
56-
57-
result := runConfigCiGithubCmd(t, options)
57+
result := runConfigCiGithubCmd(t, defaultOpts())
5858

5959
assert.NilError(t, result.executeErr)
6060
assertWorkflowFileExists(t, result)
6161
}
6262

6363
func TestNewConfigCICmd_WorkflowYAMLHasCorrectStructure(t *testing.T) {
64-
// GIVEN
65-
options := opts{
66-
withFuncInTempDir: true,
67-
}
68-
69-
// WHEN
70-
result := runConfigCiGithubCmd(t, options)
64+
result := runConfigCiGithubCmd(t, defaultOpts())
7165

72-
// THEN
7366
assert.NilError(t, result.executeErr)
7467
assertWorkflowFileExists(t, result)
7568
assert.NilError(t, result.gwLoadErr)
76-
assertFullWorkflow(t, result.gwYamlString)
69+
assertDefaultWorkflow(t, result.gwYamlString)
7770
}
7871

7972
func TestNewConfigCICmd_WorkflowYAMLHasCustomValues(t *testing.T) {
8073
// GIVEN
81-
options := opts{
82-
withFuncInTempDir: true,
83-
args: []string{
84-
"ci",
85-
"--github",
86-
"--self-hosted-runner",
87-
"--workflow-name=Custom Deploy",
88-
"--kubeconfig-secret-name=DEV_CLUSTER_KUBECONFIG",
89-
"--registry-login-url-variable-name=DEV_REGISTRY_LOGIN_URL",
90-
"--registry-user-variable-name=DEV_REGISTRY_USER",
91-
"--registry-pass-secret-name=DEV_REGISTRY_PASS",
92-
"--branch=master",
93-
},
94-
}
74+
opts := defaultOpts()
75+
opts.args = append(opts.args,
76+
"--self-hosted-runner",
77+
"--workflow-name=Custom Deploy",
78+
"--kubeconfig-secret-name=DEV_CLUSTER_KUBECONFIG",
79+
"--registry-login-url-variable-name=DEV_REGISTRY_LOGIN_URL",
80+
"--registry-user-variable-name=DEV_REGISTRY_USER",
81+
"--registry-pass-secret-name=DEV_REGISTRY_PASS",
82+
"--branch=master",
83+
)
9584

9685
// WHEN
97-
result := runConfigCiGithubCmd(t, options)
86+
result := runConfigCiGithubCmd(t, opts)
9887

9988
// THEN
10089
assert.NilError(t, result.executeErr)
10190
assertWorkflowFileExists(t, result)
102-
assert.Assert(t, yamlContains(result.gwYamlString, "Custom Deploy"))
103-
assert.Assert(t, yamlContains(result.gwYamlString, "self-hosted"))
104-
assert.Assert(t, yamlContains(result.gwYamlString, "DEV_CLUSTER_KUBECONFIG"))
105-
assert.Assert(t, yamlContains(result.gwYamlString, "DEV_REGISTRY_LOGIN_URL"))
106-
assert.Assert(t, yamlContains(result.gwYamlString, "DEV_REGISTRY_USER"))
107-
assert.Assert(t, yamlContains(result.gwYamlString, "DEV_REGISTRY_PASS"))
108-
assert.Assert(t, yamlContains(result.gwYamlString, "- master"))
91+
assertCustomWorkflow(t, result.gwYamlString)
10992
}
11093

11194
func TestNewConfigCICmd_WorkflowHasNoRegistryLogin(t *testing.T) {
11295
// GIVEN
113-
options := opts{
114-
withFuncInTempDir: true,
115-
args: []string{"ci", "--github", "--use-registry-login=false"},
116-
}
96+
opts := defaultOpts()
97+
opts.args = append(opts.args, "--use-registry-login=false")
11798

11899
// WHEN
119-
result := runConfigCiGithubCmd(t, options)
100+
result := runConfigCiGithubCmd(t, opts)
120101

121102
// THEN
122103
assert.NilError(t, result.executeErr)
@@ -128,13 +109,11 @@ func TestNewConfigCICmd_WorkflowHasNoRegistryLogin(t *testing.T) {
128109

129110
func TestNewConfigCICmd_RemoteBuildAndDeployWorkflow(t *testing.T) {
130111
// GIVEN
131-
options := opts{
132-
withFuncInTempDir: true,
133-
args: []string{"ci", "--github", "--remote"},
134-
}
112+
opts := defaultOpts()
113+
opts.args = append(opts.args, "--remote")
135114

136115
// WHEN
137-
result := runConfigCiGithubCmd(t, options)
116+
result := runConfigCiGithubCmd(t, opts)
138117

139118
// THEN
140119
assert.NilError(t, result.executeErr)
@@ -145,33 +124,37 @@ func TestNewConfigCICmd_RemoteBuildAndDeployWorkflow(t *testing.T) {
145124

146125
func TestNewConfigCICmd_HasWorkflowDispatchAndCacheInDebugMode(t *testing.T) {
147126
// GIVEN
148-
options := opts{
149-
withFuncInTempDir: true,
150-
args: []string{"ci", "--github", "--debug"},
151-
}
127+
opts := defaultOpts()
128+
opts.args = append(opts.args, "--debug")
152129

153130
// WHEN
154-
result := runConfigCiGithubCmd(t, options)
131+
result := runConfigCiGithubCmd(t, opts)
155132

156133
// THEN
157134
assert.NilError(t, result.executeErr)
158135
assertWorkflowFileExists(t, result)
159-
assert.Assert(t, yamlContains(result.gwYamlString, "workflow_dispatch"))
160-
assert.Assert(t, yamlContains(result.gwYamlString, "Restore func cli from cache"))
161-
assert.Assert(t, yamlContains(result.gwYamlString, "func-cli-cache"))
162-
assert.Assert(t, yamlContains(result.gwYamlString, "actions/cache@v4"))
163-
assert.Assert(t, yamlContains(result.gwYamlString, "path: func"))
164-
assert.Assert(t, yamlContains(result.gwYamlString, "key: func-cli-knative-v1.19.1"))
165-
assert.Assert(t, yamlContains(result.gwYamlString, "if: ${{ steps.func-cli-cache.outputs.cache-hit != 'true' }}"))
166-
assert.Assert(t, yamlContains(result.gwYamlString, "Add func to GITHUB_PATH"))
167-
assert.Assert(t, yamlContains(result.gwYamlString, `echo "$GITHUB_WORKSPACE" >> $GITHUB_PATH`))
136+
assertDebugWorkflow(t, result.gwYamlString)
168137
}
169138

170139
// START: Testing Framework
171140
// ------------------------
172141
type opts struct {
173142
withFuncInTempDir bool
174-
args []string // default: ci --github
143+
enableFeature bool
144+
args []string
145+
}
146+
147+
// defaultOpts provides the most used options for tests
148+
//
149+
// - withFuncInTempDir: true,
150+
// - enableFeature: true,
151+
// - args: []string{"ci", "--github"},
152+
func defaultOpts() opts {
153+
return opts{
154+
withFuncInTempDir: true,
155+
enableFeature: true,
156+
args: []string{"ci", "--github"},
157+
}
175158
}
176159

177160
type result struct {
@@ -195,6 +178,10 @@ func runConfigCiGithubCmd(
195178
f = cmdTest.CreateFuncInTempDir(t, "github-ci-func")
196179
}
197180

181+
if opts.enableFeature {
182+
t.Setenv(ci.ConfigCIFeatureFlag, "true")
183+
}
184+
198185
args := opts.args
199186
if len(opts.args) == 0 {
200187
args = []string{"ci", "--github"}
@@ -243,15 +230,15 @@ func assertWorkflowFileExists(t *testing.T, result result) {
243230
assert.Assert(t, exists, filepath+" does not exist")
244231
}
245232

246-
// assertFullWorkflow asserts all the Github workflow value for correct values
233+
// assertDefaultWorkflow asserts all the Github workflow value for correct values
247234
// including the default values which can be changed:
248235
// - runs-on: ubuntu-latest
249236
// - kubeconfig: ${{ secrets.KUBECONFIG }}
250237
// - registry: ${{ vars.REGISTRY_LOGIN_URL }}")
251238
// - username: ${{ vars.REGISTRY_USERNAME }}
252239
// - password: ${{ secrets.REGISTRY_PASSWORD }}
253240
// - run: func deploy --registry=${{ vars.REGISTRY_LOGIN_URL }}/${{ vars.REGISTRY_USERNAME }} -v
254-
func assertFullWorkflow(t *testing.T, actualGw string) {
241+
func assertDefaultWorkflow(t *testing.T, actualGw string) {
255242
t.Helper()
256243

257244
assert.Assert(t, yamlContains(actualGw, "Func Deploy"))
@@ -284,6 +271,28 @@ func assertFullWorkflow(t *testing.T, actualGw string) {
284271
assert.Assert(t, yamlContains(actualGw, "func deploy --registry=${{ vars.REGISTRY_LOGIN_URL }}/${{ vars.REGISTRY_USERNAME }} -v"))
285272
}
286273

274+
func assertCustomWorkflow(t *testing.T, actualGw string) {
275+
assert.Assert(t, yamlContains(actualGw, "Custom Deploy"))
276+
assert.Assert(t, yamlContains(actualGw, "self-hosted"))
277+
assert.Assert(t, yamlContains(actualGw, "DEV_CLUSTER_KUBECONFIG"))
278+
assert.Assert(t, yamlContains(actualGw, "DEV_REGISTRY_LOGIN_URL"))
279+
assert.Assert(t, yamlContains(actualGw, "DEV_REGISTRY_USER"))
280+
assert.Assert(t, yamlContains(actualGw, "DEV_REGISTRY_PASS"))
281+
assert.Assert(t, yamlContains(actualGw, "- master"))
282+
}
283+
284+
func assertDebugWorkflow(t *testing.T, actualGw string) {
285+
assert.Assert(t, yamlContains(actualGw, "workflow_dispatch"))
286+
assert.Assert(t, yamlContains(actualGw, "Restore func cli from cache"))
287+
assert.Assert(t, yamlContains(actualGw, "func-cli-cache"))
288+
assert.Assert(t, yamlContains(actualGw, "actions/cache@v4"))
289+
assert.Assert(t, yamlContains(actualGw, "path: func"))
290+
assert.Assert(t, yamlContains(actualGw, "key: func-cli-knative-v1.19.1"))
291+
assert.Assert(t, yamlContains(actualGw, "if: ${{ steps.func-cli-cache.outputs.cache-hit != 'true' }}"))
292+
assert.Assert(t, yamlContains(actualGw, "Add func to GITHUB_PATH"))
293+
assert.Assert(t, yamlContains(actualGw, `echo "$GITHUB_WORKSPACE" >> $GITHUB_PATH`))
294+
}
295+
287296
func yamlContains(yaml, substr string) cmp.Comparison {
288297
return func() cmp.Result {
289298
if strings.Contains(yaml, substr) {

0 commit comments

Comments
 (0)