Allow to specify template when running dagger project init

Adds the ability to select a template which will create a new file
in the CWD with the template name. Templates present in the
"cmd/dagger/project/templates" directory are automatically embedded in the dagger
binary when building and then listed in the `dagger project init` help output.

Usage:

    dagger project init -t <template_name>

One idea that we had while pairing on this is to eventually try
improving this UX by extending the `dagger project` command by adding
sub-commands like `dagger project templates [list, new, output, ...]`.

Pair: gerhard

Signed-off-by: Marcos Lilljedahl <marcosnils@gmail.com>
This commit is contained in:
Marcos Lilljedahl 2022-04-08 12:54:40 -03:00
parent 464c7ad708
commit 868e96d06a
5 changed files with 119 additions and 3 deletions

View File

@ -33,8 +33,17 @@ var initCmd = &cobra.Command{
dir = args[0]
}
name := viper.GetString("name")
// TODO @gerhard suggested maybe eventually having a
// `dagger project template [list, new]`
t := viper.GetString("template")
if len(t) > 0 {
err := createTemplate(t)
if err != nil {
lg.Fatal().Err(err).Msg("failed to initialize template")
}
}
name := viper.GetString("name")
doneCh := common.TrackCommand(ctx, cmd)
err := pkg.CueModInit(ctx, dir, name)
<-doneCh
@ -46,6 +55,11 @@ var initCmd = &cobra.Command{
func init() {
initCmd.Flags().StringP("name", "n", "", "project name")
t, err := getTemplateNames()
if err != nil {
panic(err)
}
initCmd.Flags().StringP("template", "t", "", fmt.Sprintf("Template name %s", t))
if err := viper.BindPFlags(initCmd.Flags()); err != nil {
panic(err)
}

View File

@ -0,0 +1,50 @@
package project
import (
"embed"
"fmt"
"io"
"os"
"path/filepath"
"strings"
)
//go:embed templates/*.cue
var templateFS embed.FS
func createTemplate(name string) error {
filename := fmt.Sprintf("%s.cue", name)
f, err := templateFS.Open(fmt.Sprintf("templates/%s", filename))
if err != nil {
return err
}
defer f.Close()
fout, err := os.Create(filename)
if err != nil {
return err
}
defer fout.Close()
_, err = io.Copy(fout, f)
if err != nil {
return err
}
return nil
}
func getTemplateNames() ([]string, error) {
r := []string{}
e, err := templateFS.ReadDir("templates")
if err != nil {
return nil, err
}
for _, f := range e {
r = append(r, strings.TrimSuffix(f.Name(), filepath.Ext(f.Name())))
}
return r, nil
}

View File

@ -0,0 +1,28 @@
// The first time you run the hello
// action as `dagger do hello --log-format plain`,
// make sure to run `dagger project update` first,
// so that all required dependencies are available.
package hello
import (
"dagger.io/dagger"
"universe.dagger.io/bash"
"universe.dagger.io/alpine"
)
dagger.#Plan & {
actions: {
_alpine: alpine.#Build & {
packages: bash: _
}
// Hello world
hello: bash.#Run & {
input: _alpine.output
script: contents: "echo Hello World"
always: true
}
}
}

View File

@ -4,7 +4,7 @@
"test": "bats --jobs 4 --print-output-on-failure --verbose-run ."
},
"devDependencies": {
"bats": "https://github.com/bats-core/bats-core#master",
"bats": "https://github.com/bats-core/bats-core#v1.6.0",
"bats-assert": "https://github.com/bats-core/bats-assert",
"bats-support": "https://github.com/bats-core/bats-support"
}

View File

@ -8,7 +8,7 @@ setup() {
}
@test "project init and update and info" {
cd "$TEMPDIR" || exit
cd "$TEMPDIR" || exit 1
"$DAGGER" project init ./ --name "github.com/foo/bar"
test -d ./cue.mod/pkg
@ -39,3 +39,27 @@ setup() {
assert_failure
assert_output --partial "dagger project not found. Run \`dagger project init\`"
}
@test "project init with template" {
cd "$TEMPDIR" || exit 1
if test -f ./hello.cue
then
echo "./hello.cue should not exist"
exit 1
fi
run "$DAGGER" project init -t hello
assert_success
if test ! -f ./hello.cue
then
echo "./hello.cue file was not created by the template flag"
exit 1
fi
cd -
diff --unified "$TEMPDIR/hello.cue" "$TESTDIR/../cmd/dagger/cmd/project/templates/hello.cue"
}