Skip to content

Commit

Permalink
Substitute category (deprecate) with tag (#667)
Browse files Browse the repository at this point in the history
Users have reported that `tags` are self-explanatory, whereas
`categories` are not.

1. In the stable CLI interface, let's move off `category` without
interrupting folks.
2. In `beta`, there will only be a `tag`.
  • Loading branch information
sourishkrout authored Sep 16, 2024
1 parent a64a67b commit 77ace52
Show file tree
Hide file tree
Showing 23 changed files with 229 additions and 164 deletions.
14 changes: 7 additions & 7 deletions examples/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -98,16 +98,16 @@ username = admin
password = admin
```

## Categories
## Tags

```sh {"category":"a","id":"01HF7BT3HD84GWTQB8ZT8D9SVW","name":"a"}
echo "Category A"
```sh {"tag":"a","id":"01HF7BT3HD84GWTQB8ZT8D9SVW","name":"a"}
echo "Tag A"
```

```sh {"category":"a,b","id":"01HF7BT3HD84GWTQB8ZVF8JVKF","name":"b"}
echo "Category A,B"
```sh {"tag":"a,b","id":"01HF7BT3HD84GWTQB8ZVF8JVKF","name":"b"}
echo "Tag A,B"
```

```sh {"category":"a,b,c","id":"01HF7BT3HD84GWTQB8ZY0GBA06","name":"c"}
echo "Category A,B,C"
```sh {"tag":"a,b,c","id":"01HF7BT3HD84GWTQB8ZY0GBA06","name":"c"}
echo "Tag A,B,C"
```
18 changes: 9 additions & 9 deletions internal/cmd/beta/beta_cmd.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,10 @@ import (
)

type commonFlags struct {
categories []string
filename string
insecure bool
silent bool
tags []string
filename string
insecure bool
silent bool
}

func BetaCmd() *cobra.Command {
Expand All @@ -42,12 +42,12 @@ All commands use the runme.yaml configuration file.`,
cfg.ProjectFilename = cFlags.filename
}

// Add a filter to run only tasks from the specified categories.
if len(cFlags.categories) > 0 {
// Add a filter to run only tasks from the specified tags.
if len(cFlags.tags) > 0 {
cfg.ProjectFilters = append(cfg.ProjectFilters, &config.Filter{
Type: config.FilterTypeBlock,
Condition: `len(intersection(categories, extra.categories)) > 0`,
Extra: map[string]interface{}{"categories": cFlags.categories},
Condition: `len(intersection(tags, extra.tags)) > 0`,
Extra: map[string]interface{}{"tags": cFlags.tags},
})
}

Expand All @@ -68,7 +68,7 @@ All commands use the runme.yaml configuration file.`,
// Use them sparingly and only for the cases when it does not make sense
// to alter the configuration file.
pFlags := cmd.PersistentFlags()
pFlags.StringSliceVar(&cFlags.categories, "category", nil, "Run blocks only from listed categories.")
pFlags.StringSliceVar(&cFlags.tags, "tag", nil, "Run blocks only from listed tags.")
pFlags.StringVar(&cFlags.filename, "filename", "", "Name of the Markdown file to run blocks from.")
pFlags.BoolVar(&cFlags.insecure, "insecure", false, "Explicitly allow delicate operations to prevent misuse")
pFlags.BoolVar(&cFlags.silent, "silent", false, "Silent mode. Do not print error messages.")
Expand Down
6 changes: 3 additions & 3 deletions internal/cmd/beta/list_cmd.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,12 +27,12 @@ func listCmd(*commonFlags) *cobra.Command {
Long: `List commands by optionally providing their names delimited by space.
The names are interpreted as glob patterns.
The --category option additionally filters the list of tasks to execute by category.`,
The --tag option additionally filters the list of tasks to execute by tag.`,
Example: `List all blocks starting with the "generate-" prefix:
runme beta list "generate-*"
List all blocks from the "setup" and "teardown" categories:
runme beta list --category=setup,teardown
List all blocks from the "setup" and "teardown" tags:
runme beta list --tag=setup,teardown
`,
RunE: func(cmd *cobra.Command, args []string) error {
return autoconfig.InvokeForCommand(
Expand Down
4 changes: 2 additions & 2 deletions internal/cmd/beta/print_cmd.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,8 @@ The names are interpreted as glob patterns.`,
Example: `Print content of commands starting with the "generate-" prefix:
runme beta print "generate-*"
Print content of commands from the "setup" and "teardown" categories:
runme beta print --category=setup,teardown
Print content of commands from the "setup" and "teardown" tags:
runme beta print --tag=setup,teardown
`,
RunE: func(cmd *cobra.Command, args []string) error {
return autoconfig.InvokeForCommand(
Expand Down
6 changes: 3 additions & 3 deletions internal/cmd/beta/run_cmd.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,12 +24,12 @@ The names are interpreted as glob patterns.
In the case of multiple commands, they are executed one-by-one in the order they appear in the document.
The --category option additionally filters the list of tasks to execute by category.`,
The --tag option additionally filters the list of tasks to execute by tag.`,
Example: `Run all blocks starting with the "generate-" prefix:
runme beta run "generate-*"
Run all blocks from the "setup" and "teardown" categories:
runme beta run --category=setup,teardown
Run all blocks from the "setup" and "teardown" tags:
runme beta run --tag=setup,teardown
`,
RunE: func(cmd *cobra.Command, args []string) error {
return autoconfig.InvokeForCommand(
Expand Down
59 changes: 38 additions & 21 deletions internal/cmd/run.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ func runCmd() *cobra.Command {
replaceScripts []string
serverAddr string
cmdCategories []string
cmdTags []string
getRunnerOpts func() ([]client.RunnerOption, error)
runIndex int
)
Expand All @@ -57,7 +58,11 @@ func runCmd() *cobra.Command {
RunE: func(cmd *cobra.Command, args []string) error {
runWithIndex := fFileMode && runIndex >= 0

runMany := runAll || (len(cmdCategories) > 0 && len(args) == 0)
if len(cmdCategories) > 0 {
cmdTags = append(cmdTags, cmdCategories...)
}

runMany := runAll || (len(cmdTags) > 0 && len(args) == 0)
if !runMany && len(args) == 0 && !runWithIndex {
return errors.New("must provide at least one command to run")
}
Expand Down Expand Up @@ -87,35 +92,35 @@ func runCmd() *cobra.Command {
block := task.CodeBlock

// Check if to run all and if the block should be excluded
if runAll && len(cmdCategories) == 0 && block.ExcludeFromRunAll() {
if runAll && len(cmdTags) == 0 && block.ExcludeFromRunAll() {
// Skip the task if it should be excluded from run all
continue
}

// Check if categories are specified and if the block should be excluded
if len(cmdCategories) > 0 && block.ExcludeFromRunAll() {
if len(cmdTags) > 0 && block.ExcludeFromRunAll() {
// Skip the task if it should be excluded based on categories
continue
}

// Check if the block matches any of the specified categories
if len(cmdCategories) > 0 {
blockCategories := block.Categories()
// Check if the block matches any of the specified tags
if len(cmdTags) > 0 {
blockTags := block.Tags()
fm := block.Document().Frontmatter()
fmCategories := resolveFrontmatterCategories(fm)
fmTags := resolveFrontmatterTags(fm)
match := false
if len(fmCategories) > 0 && containsCategories(fmCategories, cmdCategories) {
if len(blockCategories) == 0 {
if len(fmTags) > 0 && containsTags(fmTags, cmdTags) {
if len(blockTags) == 0 {
match = true
} else {
match = containsCategories(fmCategories, blockCategories)
match = containsTags(fmTags, blockTags)
}
} else if containsCategories(blockCategories, cmdCategories) {
} else if containsTags(blockTags, cmdTags) {
match = true
}

if !match {
// Skip the task if it doesn't match any specified category
// Skip the task if it doesn't match any specified tags
continue
}
}
Expand Down Expand Up @@ -150,7 +155,7 @@ func runCmd() *cobra.Command {
}

if len(runTasks) == 0 {
return errors.New("No tasks to execute with the category provided")
return errors.New("No tasks to execute with the tag provided")
}

ctx, cancel := ctxWithSigCancel(cmd.Context())
Expand Down Expand Up @@ -205,7 +210,7 @@ func runCmd() *cobra.Command {
}

if runMany {
err := confirmExecution(cmd, len(runTasks), parallel, cmdCategories)
err := confirmExecution(cmd, len(runTasks), parallel, cmdTags)
if err != nil {
return err
}
Expand Down Expand Up @@ -233,8 +238,8 @@ func runCmd() *cobra.Command {
if runMany && parallel {
scriptRunText = "Running"
blockNames = []string{blockColor.Sprint("all tasks")}
if len(cmdCategories) > 0 {
blockNames = []string{blockColor.Sprintf("tasks for categories %s", cmdCategories)}
if len(cmdTags) > 0 {
blockNames = []string{blockColor.Sprintf("tasks for tag %s", cmdTags)}
}
}

Expand Down Expand Up @@ -314,7 +319,9 @@ func runCmd() *cobra.Command {
cmd.Flags().BoolVarP(&runAll, "all", "a", false, "Run all commands.")
cmd.Flags().BoolVar(&skipPrompts, "skip-prompts", false, "Skip prompting for variables.")
cmd.Flags().StringArrayVarP(&cmdCategories, "category", "c", nil, "Run from a specific category.")
cmd.Flags().StringArrayVarP(&cmdTags, "tag", "t", nil, "Run from a specific tag.")
cmd.Flags().IntVarP(&runIndex, "index", "i", -1, "Index of command to run, 0-based. (Ignored in project mode)")
_ = cmd.Flags().MarkDeprecated("category", "use --tag instead")
cmd.PreRun = func(cmd *cobra.Command, args []string) {
skipPromptsExplicitly = cmd.Flags().Changed("skip-prompts")
}
Expand Down Expand Up @@ -619,14 +626,24 @@ func confirmExecution(cmd *cobra.Command, numTasks int, parallel bool, categorie
return nil
}

func resolveFrontmatterCategories(fm *document.Frontmatter) []string {
if fm != nil && fm.Category != "" {
return []string{fm.Category}
func resolveFrontmatterTags(fm *document.Frontmatter) []string {
if fm == nil {
return []string{}
}

tags := []string{}
if fm.Tag != "" {
tags = append(tags, fm.Tag)
}
return []string{}

if fm.Category != "" {
tags = append(tags, fm.Category)
}

return tags
}

func containsCategories(s1 []string, s2 []string) bool {
func containsTags(s1 []string, s2 []string) bool {
for _, element := range s2 {
if strings.Contains(strings.Join(s1, ","), element) {
return true
Expand Down
2 changes: 1 addition & 1 deletion internal/config/autoconfig/autoconfig.go
Original file line number Diff line number Diff line change
Expand Up @@ -171,7 +171,7 @@ func getProjectFilters(c *config.Config) ([]project.Filter, error) {
filters = append(filters, project.Filter(func(t project.Task) (bool, error) {
env := config.FilterBlockEnv{
Background: t.CodeBlock.Background(),
Categories: t.CodeBlock.Categories(),
Tags: t.CodeBlock.Tags(),
// TODO(adamb): implement this in the code block.
// CloseTerminalOnSuccess: t.CodeBlock.CloseTerminalOnSuccess(),
Cwd: t.CodeBlock.Cwd(),
Expand Down
2 changes: 1 addition & 1 deletion internal/config/config_filter.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ type FilterDocumentEnv struct {
// Without it, all variables start with capitalized letters.
type FilterBlockEnv struct {
Background bool `expr:"background"`
Categories []string `expr:"categories"`
Tags []string `expr:"tags"`
CloseTerminalOnSuccess bool `expr:"close_terminal_on_success"`
Cwd string `expr:"cwd"`
ExcludeFromRunAll bool `expr:"exclude_from_run_all"`
Expand Down
6 changes: 3 additions & 3 deletions internal/config/config_filter_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,10 +40,10 @@ func TestConfigFilter(t *testing.T) {
{
name: "intersection function in block env",
typ: FilterTypeBlock,
extra: map[string]interface{}{"categories": []string{"test"}},
condition: "len(intersection(categories, extra.categories)) > 0",
extra: map[string]interface{}{"tags": []string{"test"}},
condition: "len(intersection(tags, extra.tags)) > 0",
env: FilterBlockEnv{
Categories: []string{"test", "test1", "test2"},
Tags: []string{"test", "test1", "test2"},
},
expectedResult: true,
},
Expand Down
4 changes: 2 additions & 2 deletions main_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,9 +40,9 @@ func TestRunmeFlags(t *testing.T) {
})
}

func TestRunmeCategories(t *testing.T) {
func TestRunmeTags(t *testing.T) {
testscript.Run(t, testscript.Params{
Dir: "testdata/categories",
Dir: "testdata/tags",
ContinueOnError: true,
})
}
Expand Down
Loading

0 comments on commit 77ace52

Please sign in to comment.