Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[#89] Add groups of actions #90

Merged
merged 1 commit into from
Feb 5, 2024
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
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -8,3 +8,6 @@ out/
cover.out
progen
main

progen.yaml
progen.yml
83 changes: 78 additions & 5 deletions Readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ ___
| `-tvar`[<sup>**ⓘ**</sup>](#tvar) | []string | `[ ]` | [text/template](https://pkg.go.dev/text/template) variables <br/>(override config variables tree) |
| `-missingkey` | []string | `error` | set `missingkey`[text/template.Option](https://pkg.go.dev/text/template#Template.Option) execution option |
| `-skip`[<sup>**ⓘ**</sup>](#skip_actions) | []string | `[ ]` | skip any `action` tag <br/>(regular expression) |
| `-gp`[<sup>**ⓘ**</sup>](#groups_of_actions) | []string | `[ ]` | set of the action's groups to execution |
| `-version` | bool | `false` | print version |
| `-help` | bool | `false` | show flags |

Expand All @@ -58,6 +59,11 @@ ___
| settings.http.headers | map[string]string | ✅ | http client base request `Headers` |
| settings.http.query_params | map[string]string | ✅ | http client base request `Query Parameters` |
| | | | |
| settings.groups[<sup>**ⓘ**</sup>](#groups_of_actions) | | ✅ | groups of actions |
| settings.groups.name | string | ✅ | group's name |
| settings.groups.actions | []string | ✅ | actions names |
| settings.groups.manual | bool | ✅ | determines that the group starts automatically (default `false`) |
| | | | |
| dirs`<unique_suffix>`[<sup>**ⓘ**</sup>](#Generate) | []string | ✅ | list of directories to create |
| | | | |
| <a name="files_actio_desk"><a/>files`<unique_suffix>`[<sup>**ⓘ**</sup>](#Files) | | ✅ | list file's `path` and `data` |
Expand Down Expand Up @@ -191,6 +197,7 @@ cmd:
args: [ -l ]
- exec: tree
```

```console
% progen -v
2023-01-22 13:03:58 INFO current working direcotry: /Users/user_1/GoProjects/service
Expand Down Expand Up @@ -232,6 +239,7 @@ out:

9 directories, 2 files
```

#### Custom template functions

| Function | args | Description |
Expand All @@ -245,7 +253,7 @@ out:
| `slice.New` | N `any` elements | Create new slice from any numbers of elements <br/>(`{ $element := slice.New "a" 1 "b" }}`) |
| `slice.Append` | slice,<br/> N `any` elements | Add element to exists slice <br/>(`{{ $element := slice.Append $element "b"}}`) |

Custom template's functions added as custom arguments to the template
Custom template's functions added as custom arguments to the template
[function map](https://pkg.go.dev/text/template#hdr-Functions).

---
Expand Down Expand Up @@ -436,12 +444,12 @@ cmd2:
```

```console
% progen -v -dr -f progen.yml -skip=^dirs$$ -skip=cmd.+
% progen -v -dr -f progen.yml -skip=^dirs$ -skip=cmd.+
2023-02-05 14:18:11 INFO application working directory: /Users/user_1/GoProjects/service
2023-02-05 14:18:11 INFO configuration file: progen.yml
2023-02-05 14:18:11 INFO action tag will be skipped: cmd1
2023-02-05 14:18:11 INFO action tag will be skipped: cmd2
2023-02-05 14:18:11 INFO action tag will be skipped: dirs
2023-02-05 14:18:11 INFO action will be skipped: [cmd1]
2023-02-05 14:18:11 INFO action will be skipped: [cmd2]
2023-02-05 14:18:11 INFO action will be skipped: [dirs]
2023-02-05 14:18:11 INFO execute cmd: chmod -R 777 api/v1
2023-02-05 14:18:11 INFO dir created: api/v2
2023-02-05 14:18:11 INFO dir created: api/v3
Expand All @@ -468,6 +476,71 @@ settings:
PARAM_1: Val_1
```

### <a name="groups_of_actions"></a>Groups of actions

All actions execute in declaration order in the config file and can be union to groups.
All actions in `manual` groups will be skipped during execution process.

```yaml
settings:
groups:
- name: group1
actions: [ cmd, cmd_2 ]
manual: true
- name: group2
actions: [ cmd_2 ]
manual: true

cmd:
- echo CMD_1

cmd_2:
- echo CMD_2

cmd_3:
- echo CMD_3

cmd_4:
- echo CMD_4

```

```console
% progen -v
2024-02-05 23:08:21 INFO application working directory: /Users/user_1/GoProjects/service
2024-02-05 23:08:21 INFO configuration file: progen.yml
2024-02-05 23:08:21 INFO manual actions will be skipped: [cmd, cmd_2]
2024-02-05 23:08:21 INFO execute [dir: .]: echo CMD_3
out:
CMD_3

2024-02-05 23:08:21 INFO execute [dir: .]: echo CMD_4
out:
CMD_4

2024-02-05 23:08:21 INFO execution time: 7.916615ms
```

Actions in `manual` groups execute using `gp` flag (all action execute only once independent on declaration's quantity
in different groups).

```console
% progen -v -gp=group1 -gp=group2
2024-02-05 23:19:50 INFO application working directory: /Users/user_1/GoProjects/service
2024-02-05 23:19:50 INFO configuration file: progen.yml
2024-02-05 23:19:50 INFO groups will be execute: [group1, group2]
2024-02-05 23:19:50 INFO execute [dir: .]: echo CMD_1
out:
CMD_1

2024-02-05 23:19:50 INFO execute [dir: .]: echo CMD_2
out:
CMD_2

2024-02-05 23:19:50 INFO execution time: 7.192257ms

```

### Files

File's content can be declared in configuration file (`files.data` tag) or
Expand Down
108 changes: 101 additions & 7 deletions internal/config/config.go
Original file line number Diff line number Diff line change
@@ -1,13 +1,11 @@
package config

import (

Check failure on line 3 in internal/config/config.go

View workflow job for this annotation

GitHub Actions / lint

File is not `goimports`-ed (goimports)
"net/url"
"strings"

"github.com/kozmod/progen/internal/entity"
"golang.org/x/xerrors"
"gopkg.in/yaml.v3"

"github.com/kozmod/progen/internal/entity"
"net/url"
"strings"
)

const (
Expand All @@ -27,7 +25,8 @@
}

type Settings struct {
HTTP *HTTPClient `yaml:"http"`
HTTP *HTTPClient `yaml:"http"`
Groups Groups `yaml:"groups"`
}

type HTTPClient struct {
Expand All @@ -36,6 +35,42 @@
Debug bool `yaml:"debug"`
}

type Groups []Group

func (g Groups) ManualActions() map[string]struct{} {
manual := make(map[string]struct{})
for _, group := range g {
if !group.Manual {
continue
}
for _, action := range group.Actions {
manual[action] = struct{}{}
}
}
return manual
}

func (g Groups) GroupByAction() map[string]map[string]struct{} {
manual := make(map[string]map[string]struct{})
for _, group := range g {
for _, action := range group.Actions {
groups, ok := manual[action]
if !ok {
groups = make(map[string]struct{})
}
groups[group.Name] = struct{}{}
manual[action] = groups
}
}
return manual
}

type Group struct {
Name string `yaml:"name"`
Actions []string `yaml:"actions"`
Manual bool `yaml:"manual"`
}

type Section[T any] struct {
Line int32
Tag string
Expand Down Expand Up @@ -114,7 +149,27 @@
return nil
}

func ValidateFile(file File) error {
func (c Config) Validate() error {
for i, files := range c.Files {
for _, file := range files.Val {
err := validateFile(file)
if err != nil {
return xerrors.Errorf("files: %d [%s]: %w", i, file.Path, err)
}
}
}

if err := validateGroups(c.Settings.Groups); err != nil {
return xerrors.Errorf("groups: %w", err)
}

if err := validateConfigSections(c); err != nil {
return xerrors.Errorf("sections: %w", err)
}
return nil
}

func validateFile(file File) error {
notNil := entity.NotNilValues(file.Get, file.Data, file.Local)
switch {
case notNil == 0:
Expand All @@ -124,5 +179,44 @@
case strings.TrimSpace(file.Path) == entity.Empty:
return xerrors.Errorf("files: save `path` are empty")
}

return nil
}

func validateGroups(groups Groups) error {
var (
groupNameSet = make(map[string]int, len(groups))
groupNames = make([]string, 0, len(groups))
)
for _, group := range groups {
var (
name = group.Name
quantity, ok = groupNameSet[name]
)
if ok && quantity == 1 {
groupNames = append(groupNames, name)
}
groupNameSet[name] = groupNameSet[name] + 1
}

if len(groupNames) > 0 {
return xerrors.Errorf("duplicate names [%s]", strings.Join(groupNames, entity.LogSliceSep))
}
return nil
}

func validateConfigSections(conf Config) error {
var (
files = len(conf.Files)
dirs = len(conf.Dirs)
cmd = len(conf.Cmd)
fs = len(conf.FS)
)
if files == 0 && dirs == 0 && cmd == 0 && fs == 0 {
return xerrors.Errorf(
"config not contains executable actions [dirs: %d, files: %d, cms: %d, fs: %d]",
dirs, files, cmd, fs,
)
}
return nil
}
Loading
Loading