Skip to content

Commit

Permalink
allow popular actions data set generator to set actions registry via …
Browse files Browse the repository at this point in the history
…command line argument
  • Loading branch information
rhysd committed Mar 5, 2024
1 parent 7f6a29e commit 2903dbc
Show file tree
Hide file tree
Showing 18 changed files with 111 additions and 91 deletions.
1 change: 1 addition & 0 deletions scripts/generate-popular-actions/.gitignore
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
/generate-popular-actions
/generate-popular-actions.exe
2 changes: 2 additions & 0 deletions scripts/generate-popular-actions/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -42,3 +42,5 @@ of each action registry. Each registry is a JSON object containing the following
| `skip_inputs` | Skipping checking inputs of this action or not | `true` | No |
| `skip_outputs` | Skipping checking outputs of this action or not | `true` | No |
| `file_ext` | File extension of action metadata file. The default is `"yml"` | `"yaml"` | No |

Alternative actions registry JSON file can be used via `-r` option.
35 changes: 22 additions & 13 deletions scripts/generate-popular-actions/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -65,23 +65,19 @@ type gen struct {
stdout io.Writer
stderr io.Writer
log *log.Logger
registry []*registry
rawRegistry []byte
}

func newGen(stdout, stderr, dbgout io.Writer, registry []*registry) *gen {
func newGen(stdout, stderr, dbgout io.Writer) *gen {
l := log.New(dbgout, "", log.LstdFlags)
return &gen{stdout, stderr, l, registry}
return &gen{stdout, stderr, l, defaultPopularActionsJSON}
}

func (g *gen) getRegistry() ([]*registry, error) {
if g.registry != nil {
return g.registry, nil
}
func (g *gen) registry() ([]*registry, error) {
var a []*registry
if err := json.Unmarshal(defaultPopularActionsJSON, &a); err != nil {
if err := json.Unmarshal(g.rawRegistry, &a); err != nil {
return nil, err
}
g.registry = a
return a, nil
}

Expand All @@ -97,7 +93,7 @@ func (g *gen) fetchRemote() (map[string]*actionlint.ActionMetadata, error) {
err error
}

actions, err := g.getRegistry()
actions, err := g.registry()
if err != nil {
return nil, err
}
Expand Down Expand Up @@ -302,7 +298,7 @@ func (g *gen) readJSONL(file string) (map[string]*actionlint.ActionMetadata, err
}

func (g *gen) detectNewReleaseURLs() ([]string, error) {
actions, err := g.getRegistry()
actions, err := g.registry()
if err != nil {
return nil, err
}
Expand Down Expand Up @@ -380,10 +376,12 @@ func (g *gen) run(args []string) int {
var format string
var quiet bool
var detect bool
var registry string

flags := flag.NewFlagSet(args[0], flag.ContinueOnError)
flags.StringVar(&source, "s", "", "source of actions as local jsonl file path instead of fetching actions metadata from github.com")
flags.StringVar(&format, "f", "go", "format of generated code output to stdout. \"go\" or \"jsonl\"")
flags.StringVar(&format, "f", "go", `format of generated code output to stdout. "go" or "jsonl"`)
flags.StringVar(&registry, "r", "", "registry of actions as local JSON file path. when this flag is not given, the default popular actions registry will be used")
flags.BoolVar(&detect, "d", false, "detect new version of actions are released")
flags.BoolVar(&quiet, "q", false, "disable log output to stderr")
flags.SetOutput(g.stderr)
Expand All @@ -397,6 +395,9 @@ func (g *gen) run(args []string) int {
It can fetch data from remote GitHub repositories and from local JSONL file
(-s option). And it can output Go code or JSONL serialized data (-f option).
What actions to be included is defined in the popular actions registry embedded
in the executable. To use your own registry JSON file, use -r option.
When -d flag is given, it tries to detect new release for popular actions.
When detecting some new releases, it shows their URLs to stdout and returns
non-zero exit status.
Expand All @@ -420,6 +421,14 @@ Flags:`)
defer func() { g.log.SetOutput(w) }()
g.log.SetOutput(io.Discard)
}
if registry != "" {
b, err := os.ReadFile(registry)
if err != nil {
fmt.Fprintf(g.stderr, "could not read actions registry from JSON file: %s\n", err)
return 1
}
g.rawRegistry = b
}

g.log.Println("Start generate-popular-actions script")

Expand Down Expand Up @@ -496,5 +505,5 @@ Flags:`)
}

func main() {
os.Exit(newGen(os.Stdout, os.Stderr, os.Stderr, nil).run(os.Args))
os.Exit(newGen(os.Stdout, os.Stderr, os.Stderr).run(os.Args))
}
116 changes: 38 additions & 78 deletions scripts/generate-popular-actions/main_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ var testDummyPopularActions = []*registry{
// Normal cases

func TestDefaultPopularActions(t *testing.T) {
popularActions, err := newGen(nil, nil, nil, nil).getRegistry()
popularActions, err := newGen(nil, nil, nil).registry()
if err != nil {
t.Fatal("could not load default popular actions:", err)
}
Expand Down Expand Up @@ -75,11 +75,11 @@ func TestReadWriteJSONL(t *testing.T) {

for _, file := range files {
t.Run(file, func(t *testing.T) {
f := filepath.Join("testdata", file)
f := filepath.Join("testdata", "actions", file)
stdout := &bytes.Buffer{}
stderr := &bytes.Buffer{}

status := newGen(stdout, stderr, io.Discard, testDummyPopularActions).run([]string{"test", "-s", f, "-f", "jsonl"})
status := newGen(stdout, stderr, io.Discard).run([]string{"test", "-s", f, "-f", "jsonl"})
if status != 0 {
t.Fatalf("exit status is non-zero: %d: %s", status, stderr.Bytes())
}
Expand Down Expand Up @@ -121,13 +121,12 @@ func TestWriteGoToStdout(t *testing.T) {
t.Run(tc.in, func(t *testing.T) {
stdout := &bytes.Buffer{}
stderr := &bytes.Buffer{}
g := newGen(stdout, stderr, io.Discard, testDummyPopularActions)
status := g.run([]string{"test", "-s", filepath.Join("testdata", tc.in)})
status := newGen(stdout, stderr, io.Discard).run([]string{"test", "-s", filepath.Join("testdata", "actions", tc.in)})
if status != 0 {
t.Fatalf("exit status is non-zero: %d: %s", status, stderr.Bytes())
}

b, err := os.ReadFile(filepath.Join("testdata", tc.want))
b, err := os.ReadFile(filepath.Join("testdata", "go", tc.want))
if err != nil {
panic(err)
}
Expand All @@ -142,7 +141,7 @@ func TestWriteGoToStdout(t *testing.T) {
}

func TestWriteJSONLFile(t *testing.T) {
in := filepath.Join("testdata", "test.jsonl")
in := filepath.Join("testdata", "actions", "test.jsonl")
b, err := os.ReadFile(in)
if err != nil {
panic(err)
Expand All @@ -153,7 +152,7 @@ func TestWriteJSONLFile(t *testing.T) {

stdout := io.Discard
stderr := io.Discard
status := newGen(stdout, stderr, io.Discard, testDummyPopularActions).run([]string{"test", "-s", in, "-f", "jsonl", out})
status := newGen(stdout, stderr, io.Discard).run([]string{"test", "-s", in, "-f", "jsonl", out})
if status != 0 {
t.Fatal("exit status is non-zero:", status)
}
Expand All @@ -171,18 +170,18 @@ func TestWriteJSONLFile(t *testing.T) {
}

func TestWriteGoFile(t *testing.T) {
in := filepath.Join("testdata", "test.jsonl")
out := filepath.Join("testdata", "out.go")
in := filepath.Join("testdata", "actions", "test.jsonl")
out := filepath.Join("testdata", "go", "out.go")
defer os.Remove(out)

stdout := io.Discard
stderr := io.Discard
status := newGen(stdout, stderr, io.Discard, testDummyPopularActions).run([]string{"test", "-s", in, out})
status := newGen(stdout, stderr, io.Discard).run([]string{"test", "-s", in, out})
if status != 0 {
t.Fatal("exit status is non-zero:", status)
}

b, err := os.ReadFile(filepath.Join("testdata", "want.go"))
b, err := os.ReadFile(filepath.Join("testdata", "go", "want.go"))
if err != nil {
panic(err)
}
Expand All @@ -200,25 +199,15 @@ func TestWriteGoFile(t *testing.T) {
}

func TestFetchRemoteYAML(t *testing.T) {
data := []*registry{
{
Slug: "rhysd/action-setup-vim",
Tags: []string{"v1.2.7"},
},
{
Slug: "rhysd/changelog-from-release",
Path: "/action",
Tags: []string{"v2.2.2"},
},
}
f := filepath.Join("testdata", "registry", "fetch.json")
stdout := &bytes.Buffer{}
stderr := io.Discard
status := newGen(stdout, stderr, io.Discard, data).run([]string{"test"})
status := newGen(stdout, stderr, io.Discard).run([]string{"test", "-r", f})
if status != 0 {
t.Fatal("exit status is non-zero:", status)
}

b, err := os.ReadFile(filepath.Join("testdata", "fetched.go"))
b, err := os.ReadFile(filepath.Join("testdata", "go", "fetched.go"))
if err != nil {
panic(err)
}
Expand All @@ -231,10 +220,10 @@ func TestFetchRemoteYAML(t *testing.T) {
}

func TestLogOutput(t *testing.T) {
f := filepath.Join("testdata", "test.jsonl")
f := filepath.Join("testdata", "actions", "test.jsonl")
stdout := &bytes.Buffer{}
logged := &bytes.Buffer{}
status := newGen(stdout, io.Discard, logged, testDummyPopularActions).run([]string{"test", "-s", f, "-f", "jsonl"})
status := newGen(stdout, io.Discard, logged).run([]string{"test", "-s", f, "-f", "jsonl"})
if status != 0 {
t.Fatal("exit status is non-zero:", status)
}
Expand All @@ -250,7 +239,7 @@ func TestLogOutput(t *testing.T) {

stdout = &bytes.Buffer{}
logged = &bytes.Buffer{}
status = newGen(stdout, io.Discard, logged, testDummyPopularActions).run([]string{"test", "-s", f, "-f", "jsonl", "-q"})
status = newGen(stdout, io.Discard, logged).run([]string{"test", "-s", f, "-f", "jsonl", "-q"})
if status != 0 {
t.Fatal("exit status is non-zero:", status)
}
Expand All @@ -268,7 +257,7 @@ func TestLogOutput(t *testing.T) {
func TestHelpOutput(t *testing.T) {
stdout := io.Discard
stderr := &bytes.Buffer{}
status := newGen(stdout, stderr, io.Discard, testDummyPopularActions).run([]string{"test", "-help"})
status := newGen(stdout, stderr, io.Discard).run([]string{"test", "-help"})
if status != 0 {
t.Fatal("exit status is non-zero:", status)
}
Expand All @@ -279,16 +268,10 @@ func TestHelpOutput(t *testing.T) {
}

func TestDetectNewRelease(t *testing.T) {
data := []*registry{
{
Slug: "rhysd/action-setup-vim",
Tags: []string{"v0"},
Next: "v1",
},
}
f := filepath.Join("testdata", "registry", "new_release.json")
stdout := &bytes.Buffer{}
stderr := io.Discard
status := newGen(stdout, stderr, io.Discard, data).run([]string{"test", "-d"})
status := newGen(stdout, stderr, io.Discard).run([]string{"test", "-d", "-r", f})
if status != 2 {
t.Fatal("exit status is not 2:", status)
}
Expand All @@ -300,26 +283,17 @@ func TestDetectNewRelease(t *testing.T) {
}

func TestDetectNoRelease(t *testing.T) {
testCases := []struct {
what string
next string
}{
{"no new version yet", "this-is-awesome-new-version"},
{"no next version", ""},
files := []string {
"no_new_version.json",
"empty_next_version.json",
}

for _, tc := range testCases {
t.Run(tc.what, func(t *testing.T) {
data := []*registry{
{
Slug: "rhysd/action-setup-vim",
Tags: []string{"v1"},
Next: tc.next,
},
}
for _, f := range files {
t.Run(f, func(t *testing.T) {
stdout := &bytes.Buffer{}
stderr := io.Discard
status := newGen(stdout, stderr, io.Discard, data).run([]string{"test", "-d"})
p := filepath.Join("testdata", "registry", f)
status := newGen(stdout, stderr, io.Discard).run([]string{"test", "-d", "-r", p})
if status != 0 {
t.Fatal("exit status is non-zero:", status)
}
Expand All @@ -344,11 +318,11 @@ func TestCouldNotReadJSONLFile(t *testing.T) {
}
for _, tc := range testCases {
t.Run(tc.file, func(t *testing.T) {
f := filepath.Join("testdata", tc.file)
f := filepath.Join("testdata", "actions", tc.file)
stdout := io.Discard
stderr := &bytes.Buffer{}

status := newGen(stdout, stderr, io.Discard, testDummyPopularActions).run([]string{"test", "-s", f})
status := newGen(stdout, stderr, io.Discard).run([]string{"test", "-s", f})
if status == 0 {
t.Fatal("exit status is unexpectedly zero")
}
Expand All @@ -362,12 +336,12 @@ func TestCouldNotReadJSONLFile(t *testing.T) {
}

func TestCouldNotCreateOutputFile(t *testing.T) {
f := filepath.Join("testdata", "test.jsonl")
f := filepath.Join("testdata", "actions", "test.jsonl")
out := filepath.Join("testdata", "this-dir-does-not-exit", "foo.jsonl")
stdout := io.Discard
stderr := &bytes.Buffer{}

status := newGen(stdout, stderr, io.Discard, testDummyPopularActions).run([]string{"test", "-s", f, "-f", "jsonl", out})
status := newGen(stdout, stderr, io.Discard).run([]string{"test", "-s", f, "-f", "jsonl", out})
if status == 0 {
t.Fatal("exit status is unexpectedly zero")
}
Expand All @@ -387,11 +361,11 @@ func (w testErrorWriter) Write(b []byte) (int, error) {
func TestWriteError(t *testing.T) {
for _, format := range []string{"go", "jsonl"} {
t.Run(format, func(t *testing.T) {
f := filepath.Join("testdata", "test.jsonl")
f := filepath.Join("testdata", "actions", "test.jsonl")
stdout := testErrorWriter{}
stderr := &bytes.Buffer{}

status := newGen(stdout, stderr, io.Discard, testDummyPopularActions).run([]string{"test", "-s", f, "-f", format})
status := newGen(stdout, stderr, io.Discard).run([]string{"test", "-s", f, "-f", format})
if status == 0 {
t.Fatal("exit status is unexpectedly zero")
}
Expand All @@ -405,18 +379,11 @@ func TestWriteError(t *testing.T) {
}

func TestCouldNotFetch(t *testing.T) {
data := []*registry{
{
Slug: "rhysd/this-action-does-not-exist",
Tags: []string{"v1"},
Next: "v2",
},
}

stdout := testErrorWriter{}
stderr := &bytes.Buffer{}
f := filepath.Join("testdata", "registry", "repo_not_found.json")

status := newGen(stdout, stderr, io.Discard, data).run([]string{"test"})
status := newGen(stdout, stderr, io.Discard).run([]string{"test", "-r", f})
if status == 0 {
t.Fatal("exit status is unexpectedly zero")
}
Expand All @@ -442,7 +409,7 @@ func TestInvalidCommandArgs(t *testing.T) {
stdout := testErrorWriter{}
stderr := &bytes.Buffer{}

status := newGen(stdout, stderr, io.Discard, testDummyPopularActions).run(tc.args)
status := newGen(stdout, stderr, io.Discard).run(tc.args)
if status == 0 {
t.Fatal("exit status is unexpectedly zero")
}
Expand All @@ -456,17 +423,10 @@ func TestInvalidCommandArgs(t *testing.T) {
}

func TestDetectErrorBadRequest(t *testing.T) {
data := []*registry{
// This expects to cause 400 Bad Request
{
Slug: "",
Tags: []string{"v1"},
Next: "v2",
},
}
stdout := io.Discard
stderr := &bytes.Buffer{}
status := newGen(stdout, stderr, io.Discard, data).run([]string{"test", "-d"})
f := filepath.Join("testdata", "registry", "empty_slug.json")
status := newGen(stdout, stderr, io.Discard).run([]string{"test", "-d", "-r", f})
if status != 1 {
t.Fatal("exit status is not 1:", status)
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
[
{
"slug": "rhysd/action-setup-vim",
"tags": ["v1"],
"next": ""
}
]
Loading

0 comments on commit 2903dbc

Please sign in to comment.