Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
48 changes: 48 additions & 0 deletions cmd/ci/config.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
package ci

import (
"path/filepath"

"github.com/ory/viper"
)

const (
ConfigCIFeatureFlag = "FUNC_ENABLE_CI_CONFIG"

DefaultGithubWorkflowDir = ".github/workflows"
DefaultGithubWorkflowFilename = "func-deploy.yaml"

PathOption = "path"

WorkflowNameOption = "workflow-name"
DefaultWorkflowName = "Func Deploy"
)

// CIConfig readonly CI configuration
type CIConfig struct {
githubWorkflowDir,
githubWorkflowFilename,
path,
workflowName string
}

func NewCiGithubConfig() CIConfig {
return CIConfig{
githubWorkflowDir: DefaultGithubWorkflowDir,
githubWorkflowFilename: DefaultGithubWorkflowFilename,
path: viper.GetString(PathOption),
workflowName: viper.GetString(WorkflowNameOption),
}
}

func (cc *CIConfig) FnGithubWorkflowDir(fnRoot string) string {
return filepath.Join(fnRoot, cc.githubWorkflowDir)
}

func (cc *CIConfig) FnGithubWorkflowFilepath(fnRoot string) string {
return filepath.Join(cc.FnGithubWorkflowDir(fnRoot), cc.githubWorkflowFilename)
}

func (cc *CIConfig) Path() string {
return cc.path
}
1 change: 1 addition & 0 deletions cmd/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ or from the directory specified with --path.
cmd.AddCommand(NewConfigLabelsCmd(loadSaver))
cmd.AddCommand(NewConfigEnvsCmd(loadSaver))
cmd.AddCommand(NewConfigVolumesCmd())
cmd.AddCommand(NewConfigCICmd(loadSaver))

return cmd
}
Expand Down
56 changes: 56 additions & 0 deletions cmd/config_ci.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
package cmd

import (
"fmt"
"os"

"github.com/spf13/cobra"

"knative.dev/func/cmd/ci"
"knative.dev/func/cmd/common"
)

func NewConfigCICmd(loaderSaver common.FunctionLoaderSaver) *cobra.Command {
cmd := &cobra.Command{
Use: "ci",
Short: "Generate a Github Workflow for function deployment",
PreRunE: bindEnv(
ci.PathOption,
ci.WorkflowNameOption,
),
RunE: func(cmd *cobra.Command, args []string) (err error) {
return runConfigCIGithub(cmd, loaderSaver)
},
}

addPathFlag(cmd)
cmd.Flags().String(
ci.WorkflowNameOption,
ci.DefaultWorkflowName,
"Use a custom workflow name",
)

return cmd
}

func runConfigCIGithub(
cmd *cobra.Command,
fnLoaderSaver common.FunctionLoaderSaver,
) error {
if os.Getenv(ci.ConfigCIFeatureFlag) != "true" {
return fmt.Errorf("set %s to 'true' to use this feature", ci.ConfigCIFeatureFlag)
}

cfg := ci.NewCiGithubConfig()

f, err := fnLoaderSaver.Load(cfg.Path())
if err != nil {
return err
}

fmt.Fprintln(cmd.OutOrStdout(), "--------------------------- Function Github Workflow Generation ---------------------------")
fmt.Fprintf(cmd.OutOrStdout(), "Func name: %s\n", f.Name)
fmt.Fprintf(cmd.OutOrStdout(), "Func runtime: %s\n", f.Runtime)

return fmt.Errorf("not implemented")
}
126 changes: 126 additions & 0 deletions cmd/config_ci_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
package cmd_test

import (
"fmt"
"testing"

"gotest.tools/v3/assert"
fnCmd "knative.dev/func/cmd"
"knative.dev/func/cmd/ci"
"knative.dev/func/cmd/common"
cmdTest "knative.dev/func/cmd/testing"
fn "knative.dev/func/pkg/functions"
fnTest "knative.dev/func/pkg/testing"
)

func TestNewConfigCICmd_RequiresFeatureFlag(t *testing.T) {
expectedErrMsg := fmt.Sprintf("set %s to 'true' to use this feature", ci.ConfigCIFeatureFlag)

result := runConfigCiCmd(t, opts{enableFeature: false})

assert.Error(t, result.executeErr, expectedErrMsg)
}

func TestNewConfigCICmd_CISubcommandExist(t *testing.T) {
// leave 'ci' to make this test explicitly use this subcommand
opts := opts{withFuncInTempDir: true, enableFeature: true, args: []string{"ci"}}

result := runConfigCiCmd(t, opts)

assert.Error(t, result.executeErr, "not implemented")
}

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

result := runConfigCiCmd(t, opts{withFuncInTempDir: false, enableFeature: true})

assert.Error(t, result.executeErr, expectedErrMsg)
}

func TestNewConfigCICmd_SuccessWhenInitialized(t *testing.T) {
result := runConfigCiCmd(t, defaultOpts())

assert.Error(t, result.executeErr, "not implemented")
}

func TestNewConfigCICmd_FailsToLoadFuncWithWrongPath(t *testing.T) {
opts := defaultOpts()
opts.args = append(opts.args, "--path=nofunc")
expectedErrMsg := "failed to create new function"

result := runConfigCiCmd(t, opts)

assert.ErrorContains(t, result.executeErr, expectedErrMsg)
}

func TestNewConfigCICmd_SuccessfulLoadWithCorrectPath(t *testing.T) {
tmpDir := t.TempDir()
opt := opts{withFuncInTempDir: false, enableFeature: true, args: []string{"ci", "--path=" + tmpDir}}
_, initErr := fn.New().Init(
fn.Function{Name: "github-ci-func", Runtime: "go", Root: tmpDir},
)

result := runConfigCiCmd(t, opt)

assert.NilError(t, initErr)
assert.Error(t, result.executeErr, "not implemented")
}

// START: Testing Framework
// ------------------------
type opts struct {
withFuncInTempDir bool
enableFeature bool
args []string
}

// defaultOpts provides the most used options for tests
// - withFuncInTempDir: true,
// - enableFeature: true,
// - args: []string{"ci"},
func defaultOpts() opts {
return opts{
withFuncInTempDir: true,
enableFeature: true,
args: []string{"ci"},
}
}

type result struct {
executeErr error
}

func runConfigCiCmd(
t *testing.T,
opts opts,
) result {
t.Helper()

// PRE-RUN PREP
if opts.withFuncInTempDir {
_ = cmdTest.CreateFuncInTempDir(t, "github-ci-func")
}

if opts.enableFeature {
t.Setenv(ci.ConfigCIFeatureFlag, "true")
}

args := opts.args
if len(opts.args) == 0 {
args = []string{"ci"}
}

cmd := fnCmd.NewConfigCmd(
common.DefaultLoaderSaver,
fnCmd.NewClient,
)
cmd.SetArgs(args)

// RUN
err := cmd.Execute()

return result{
err,
}
}
10 changes: 4 additions & 6 deletions cmd/testing/factory.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,16 +13,14 @@ import (
func CreateFuncInTempDir(t *testing.T, fnName string) fn.Function {
t.Helper()

var name string
name := fnName
if fnName == "" {
name = "go-func"
}

result, err := fn.New().Init(fn.Function{
Name: name,
Runtime: "go",
Root: fnTest.FromTempDirectory(t),
})
result, err := fn.New().Init(
fn.Function{Name: name, Runtime: "go", Root: fnTest.FromTempDirectory(t)},
)
assert.NilError(t, err)

return result
Expand Down
1 change: 1 addition & 0 deletions docs/reference/func_config.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ func config
### SEE ALSO

* [func](func.md) - func manages Knative Functions
* [func config ci](func_config_ci.md) - Generate a Github Workflow for function deployment
* [func config envs](func_config_envs.md) - List and manage configured environment variable for a function
* [func config git](func_config_git.md) - Manage Git configuration of a function
* [func config labels](func_config_labels.md) - List and manage configured labels for a function
Expand Down
20 changes: 20 additions & 0 deletions docs/reference/func_config_ci.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
## func config ci

Generate a Github Workflow for function deployment

```
func config ci
```

### Options

```
-h, --help help for ci
-p, --path string Path to the function. Default is current directory ($FUNC_PATH)
--workflow-name string Use a custom workflow name (default "Func Deploy")
```

### SEE ALSO

* [func config](func_config.md) - Configure a function

Loading