From f4d1f0d8a223e739cf5e002f76389abcec1b393d Mon Sep 17 00:00:00 2001 From: Christian Winther Date: Mon, 13 May 2024 13:35:30 +0200 Subject: [PATCH] feat: reorgnize commands into github/gitlab specific commands --- .github/workflows/docs.yml | 3 + .github/workflows/test.yml | 10 +- .gitignore | 2 + Taskfile.yml | 13 +++ cmd/conventions.go | 1 - cmd/github.go | 66 ++++++++++++ cmd/gitlab.go | 108 ++++++++++++++++++++ cmd/{cmd_evaluate.go => gitlab_evaluate.go} | 4 - cmd/{cmd_server.go => gitlab_server.go} | 6 +- docs/commands/evaluate.md | 32 ------ docs/commands/server.md | 40 -------- docs/github/commands.md | 19 ++++ docs/gitlab/commands.md | 36 +++++++ main.go | 93 ++++++----------- mkdocs.yml | 3 +- 15 files changed, 291 insertions(+), 145 deletions(-) create mode 100644 cmd/github.go create mode 100644 cmd/gitlab.go rename cmd/{cmd_evaluate.go => gitlab_evaluate.go} (88%) rename cmd/{cmd_server.go => gitlab_server.go} (94%) delete mode 100644 docs/commands/evaluate.md delete mode 100644 docs/commands/server.md create mode 100644 docs/github/commands.md create mode 100644 docs/gitlab/commands.md diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml index 6a0e33b..f918919 100644 --- a/.github/workflows/docs.yml +++ b/.github/workflows/docs.yml @@ -31,5 +31,8 @@ jobs: - name: setup run: task setup + - name: generate + run: task docs:generate + - name: deploy run: task docs:deploy diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 2c562e2..cabbc0a 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -46,7 +46,7 @@ jobs: - name: Ensure scm-engine binary work run: ./scm-engine -h - - name: Test scm-engine against a GitLab project + - name: Test scm-engine against a GitLab project (deprecated) run: ./scm-engine evaluate all env: SCM_ENGINE_TOKEN: "${{ secrets.GITLAB_INTEGRATION_TEST_API_TOKEN }}" @@ -54,5 +54,13 @@ jobs: GITLAB_PROJECT: "jippi/scm-engine-schema-test" GITLAB_BASEURL: https://gitlab.com/ + - name: Test scm-engine against a GitLab project (new) + run: ./scm-engine gitlab evaluate all + env: + SCM_ENGINE_TOKEN: "${{ secrets.GITLAB_INTEGRATION_TEST_API_TOKEN }}" + SCM_ENGINE_CONFIG_FILE: ".scm-engine.gitlab.example.yml" + GITLAB_PROJECT: "jippi/scm-engine-schema-test" + GITLAB_BASEURL: https://gitlab.com/ + - name: Show any diff that may be in the project run: git diff diff --git a/.gitignore b/.gitignore index bfcc38e..d73ab5c 100644 --- a/.gitignore +++ b/.gitignore @@ -18,3 +18,5 @@ /scm-engine.exe /docs/gitlab/script-attributes.md /docs/github/script-attributes.md +/docs/github/_partials/cmd-* +/docs/gitlab/_partials/cmd-* diff --git a/Taskfile.yml b/Taskfile.yml index f1785ff..36ca1a0 100644 --- a/Taskfile.yml +++ b/Taskfile.yml @@ -30,6 +30,19 @@ tasks: generates: - ./scm-engine + docs:generate: + desc: "Generate docs" + cmds: + - mkdir -p docs/github/_partials + - go run . -h > docs/github/_partials/cmd-root.md + - go run . github -h > docs/github/_partials/cmd-github.md + - go run . github evaluate -h > docs/github/_partials/cmd-github-evaluate.md + + - mkdir -p docs/gitlab/_partials + - go run . -h > docs/gitlab/_partials/cmd-root.md + - go run . gitlab -h > docs/gitlab/_partials/cmd-gitlab.md + - go run . gitlab evaluate -h > docs/gitlab/_partials/cmd-gitlab-evaluate.md + - go run . gitlab server -h > docs/gitlab/_partials/cmd-gitlab-server.md docs:server: desc: Run Docs dev server with live preview cmds: diff --git a/cmd/conventions.go b/cmd/conventions.go index 313543d..7288ecc 100644 --- a/cmd/conventions.go +++ b/cmd/conventions.go @@ -6,7 +6,6 @@ const ( FlagConfigFile = "config" FlagDryRun = "dry-run" FlagMergeRequestID = "id" - FlagProvider = "provider" FlagSCMBaseURL = "base-url" FlagSCMProject = "project" FlagServerListen = "listen" diff --git a/cmd/github.go b/cmd/github.go new file mode 100644 index 0000000..c6aa8c1 --- /dev/null +++ b/cmd/github.go @@ -0,0 +1,66 @@ +package cmd + +import ( + "github.com/jippi/scm-engine/pkg/state" + "github.com/urfave/cli/v2" +) + +var GitHub = &cli.Command{ + Name: "github", + Usage: "GitHub related commands", + Before: func(ctx *cli.Context) error { + ctx.Context = state.WithProvider(ctx.Context, "github") + + return nil + }, + Flags: []cli.Flag{ + &cli.StringFlag{ + Name: FlagAPIToken, + Usage: "GitHub API token", + EnvVars: []string{ + "SCM_ENGINE_TOKEN", // SCM Engine Native + }, + }, + &cli.StringFlag{ + Name: FlagSCMBaseURL, + Usage: "Base URL for the SCM instance", + Value: "https://api.github.com/", + EnvVars: []string{ + "SCM_ENGINE_BASE_URL", // SCM Engine Native + }, + }, + }, + Subcommands: []*cli.Command{ + { + Name: "evaluate", + Usage: "Evaluate a Pull Request", + Args: true, + ArgsUsage: " [pr_id, pr_id, ...]", + Action: Evaluate, + Flags: []cli.Flag{ + &cli.StringFlag{ + Name: FlagSCMProject, + Usage: "GitHub project (example: 'jippi/scm-engine')", + Required: true, + EnvVars: []string{ + "GITHUB_REPOSITORY", // GitHub Actions CI + }, + }, + &cli.StringFlag{ + Name: FlagMergeRequestID, + Usage: "The Pull Request ID to process, if not provided as a CLI flag", + EnvVars: []string{ + "SCM_ENGINE_PULL_REQUEST_ID", // SCM Engine native + }, + }, + &cli.StringFlag{ + Name: FlagCommitSHA, + Usage: "The git commit sha", + EnvVars: []string{ + "GITHUB_SHA", // GitHub Actions + }, + }, + }, + }, + }, +} diff --git a/cmd/gitlab.go b/cmd/gitlab.go new file mode 100644 index 0000000..912955e --- /dev/null +++ b/cmd/gitlab.go @@ -0,0 +1,108 @@ +package cmd + +import ( + "github.com/jippi/scm-engine/pkg/state" + "github.com/urfave/cli/v2" +) + +var GitLab = &cli.Command{ + Name: "gitlab", + Usage: "GitLab related commands", + Before: func(cCtx *cli.Context) error { + cCtx.Context = state.WithBaseURL(cCtx.Context, cCtx.String(FlagSCMBaseURL)) + cCtx.Context = state.WithProvider(cCtx.Context, "gitlab") + cCtx.Context = state.WithToken(cCtx.Context, cCtx.String(FlagAPIToken)) + + return nil + }, + Flags: []cli.Flag{ + &cli.StringFlag{ + Name: FlagAPIToken, + Usage: "GitLab API token", + EnvVars: []string{ + "SCM_ENGINE_TOKEN", // SCM Engine Native + }, + }, + &cli.StringFlag{ + Name: FlagSCMBaseURL, + Usage: "Base URL for the SCM instance", + Value: "https://gitlab.com/", + EnvVars: []string{ + "SCM_ENGINE_BASE_URL", // SCM Engine Native + "CI_SERVER_URL", // GitLab CI + }, + }, + }, + Subcommands: []*cli.Command{ + { + Name: "evaluate", + Usage: "Evaluate a Merge Request", + Args: true, + ArgsUsage: " [mr_id, mr_id, ...]", + Action: Evaluate, + Flags: []cli.Flag{ + &cli.BoolFlag{ + Name: FlagUpdatePipeline, + Usage: "Update the CI pipeline status with progress", + Value: false, + EnvVars: []string{ + "SCM_ENGINE_UPDATE_PIPELINE", + }, + }, + &cli.StringFlag{ + Name: FlagSCMProject, + Usage: "GitLab project (example: 'gitlab-org/gitlab')", + EnvVars: []string{ + "GITLAB_PROJECT", + "CI_PROJECT_PATH", // GitLab CI + }, + }, + &cli.StringFlag{ + Name: FlagMergeRequestID, + Usage: "The Merge Request ID to process, if not provided as a CLI flag", + EnvVars: []string{ + "CI_MERGE_REQUEST_IID", // GitLab CI + }, + }, + &cli.StringFlag{ + Name: FlagCommitSHA, + Usage: "The git commit sha", + EnvVars: []string{ + "CI_COMMIT_SHA", // GitLab CI + }, + }, + }, + }, + { + Name: "server", + Usage: "Start HTTP server for webhook event driven usage", + Hidden: true, // DEPRECATED + Action: Server, + Flags: []cli.Flag{ + &cli.StringFlag{ + Name: FlagWebhookSecret, + Usage: "Used to validate received payloads. Sent with the request in the X-Gitlab-Token HTTP header", + EnvVars: []string{ + "SCM_ENGINE_WEBHOOK_SECRET", + }, + }, + &cli.StringFlag{ + Name: FlagServerListen, + Usage: "IP + Port that the HTTP server should listen on", + Value: "0.0.0.0:3000", + EnvVars: []string{ + "SCM_ENGINE_LISTEN", + }, + }, + &cli.BoolFlag{ + Name: FlagUpdatePipeline, + Usage: "Update the CI pipeline status with progress", + Value: true, + EnvVars: []string{ + "SCM_ENGINE_UPDATE_PIPELINE", + }, + }, + }, + }, + }, +} diff --git a/cmd/cmd_evaluate.go b/cmd/gitlab_evaluate.go similarity index 88% rename from cmd/cmd_evaluate.go rename to cmd/gitlab_evaluate.go index c15c301..efa6a7d 100644 --- a/cmd/cmd_evaluate.go +++ b/cmd/gitlab_evaluate.go @@ -11,11 +11,7 @@ import ( func Evaluate(cCtx *cli.Context) error { ctx := state.WithProjectID(cCtx.Context, cCtx.String(FlagSCMProject)) - ctx = state.WithBaseURL(ctx, cCtx.String(FlagSCMBaseURL)) ctx = state.WithCommitSHA(ctx, cCtx.String(FlagCommitSHA)) - ctx = state.WithDryRun(ctx, cCtx.Bool(FlagDryRun)) - ctx = state.WithProvider(ctx, cCtx.String(FlagProvider)) - ctx = state.WithToken(ctx, cCtx.String(FlagAPIToken)) ctx = state.WithToken(ctx, cCtx.String(FlagAPIToken)) ctx = state.WithUpdatePipeline(ctx, cCtx.Bool(FlagUpdatePipeline)) diff --git a/cmd/cmd_server.go b/cmd/gitlab_server.go similarity index 94% rename from cmd/cmd_server.go rename to cmd/gitlab_server.go index 269a2cf..6de3051 100644 --- a/cmd/cmd_server.go +++ b/cmd/gitlab_server.go @@ -56,11 +56,7 @@ func errHandler(ctx context.Context, w http.ResponseWriter, code int, err error) func Server(cCtx *cli.Context) error { // Initialize context - ctx := state.WithDryRun(cCtx.Context, cCtx.Bool(FlagDryRun)) - ctx = state.WithBaseURL(ctx, cCtx.String(FlagSCMBaseURL)) - ctx = state.WithToken(ctx, cCtx.String(FlagAPIToken)) - ctx = state.WithProvider(ctx, cCtx.String(FlagProvider)) - ctx = state.WithUpdatePipeline(ctx, cCtx.Bool(FlagUpdatePipeline)) + ctx := state.WithUpdatePipeline(cCtx.Context, cCtx.Bool(FlagUpdatePipeline)) slogctx.Info(ctx, "Starting HTTP server", slog.String("listen", cCtx.String(FlagServerListen))) diff --git a/docs/commands/evaluate.md b/docs/commands/evaluate.md deleted file mode 100644 index 89fab77..0000000 --- a/docs/commands/evaluate.md +++ /dev/null @@ -1,32 +0,0 @@ ---- -hide: - - toc ---- - -# Evaluate - -Evaluate the SCM engine rules against a specific Merge Request. - -```plain -NAME: - scm-engine evaluate - Evaluate a Merge Request - -USAGE: - scm-engine evaluate [command options] [mr_id, mr_id, ...] - -OPTIONS: - --update-pipeline Update the CI pipeline status with progress (default: false) [$SCM_ENGINE_UPDATE_PIPELINE] - --project value GitLab project (example: 'gitlab-org/gitlab') [$GITLAB_PROJECT, $CI_PROJECT_PATH, $GITHUB_REPOSITORY] - --id value The pull/merge ID to process, if not provided as a CLI flag [$CI_MERGE_REQUEST_IID] - --commit value The git commit sha [$CI_COMMIT_SHA, $GITHUB_SHA] - --help, -h show help - -GLOBAL OPTIONS: - --config value Path to the scm-engine config file (default: ".scm-engine.yml") [$SCM_ENGINE_CONFIG_FILE] - --provider value SCM provider to use. Must be either "github" or "gitlab". SCM Engine will automatically detect "github" if "GITHUB_ACTIONS" environment variable is set (e.g., inside GitHub Actions) and detect "gitlab" if "GITLAB_CI" environment variable is set (e.g., inside GitLab CI). [$SCM_ENGINE_PROVIDER] - --api-token value GitHub/GitLab API token [$SCM_ENGINE_TOKEN, $GITHUB_TOKEN] - --base-url value Base URL for the SCM instance (default: "https://gitlab.com/") [$GITLAB_BASEURL, $CI_SERVER_URL, $GITHUB_API_URL] - --dry-run Dry run, don't actually _do_ actions, just print them (default: false) - --help, -h show help - --version, -v print the version -``` diff --git a/docs/commands/server.md b/docs/commands/server.md deleted file mode 100644 index bf8ec40..0000000 --- a/docs/commands/server.md +++ /dev/null @@ -1,40 +0,0 @@ ---- -hide: - - toc ---- - -# Server - -Point your GitLab webhook at the `/gitlab` endpoint. - -Support the following events, and they will both trigger an Merge Request `evaluation` - -- [`Comments`](https://docs.gitlab.com/ee/user/project/integrations/webhook_events.html#comment-events) - A comment is made or edited on an issue or merge request. -- [`Merge request events`](https://docs.gitlab.com/ee/user/project/integrations/webhook_events.html#merge-request-events) - A merge request is created, updated, or merged. - -!!! tip - - You have access to the raw webhook event payload via `webhook_event.*` fields in Expr script fields when using `server` mode. See the [GitLab Webhook Events documentation](https://docs.gitlab.com/ee/user/project/integrations/webhook_events.html) for available fields. - -```plain -NAME: - scm-engine server - Start HTTP server for webhook event driven usage - -USAGE: - scm-engine server [command options] - -OPTIONS: - --webhook-secret value Used to validate received payloads. Sent with the request in the X-Gitlab-Token HTTP header [$SCM_ENGINE_WEBHOOK_SECRET] - --listen value IP + Port that the HTTP server should listen on (default: "0.0.0.0:3000") [$SCM_ENGINE_LISTEN] - --update-pipeline Update the CI pipeline status with progress (default: true) [$SCM_ENGINE_UPDATE_PIPELINE] - --help, -h show help - -GLOBAL OPTIONS: - --config value Path to the scm-engine config file (default: ".scm-engine.yml") [$SCM_ENGINE_CONFIG_FILE] - --provider value SCM provider to use. Must be either "github" or "gitlab". SCM Engine will automatically detect "github" if "GITHUB_ACTIONS" environment variable is set (e.g., inside GitHub Actions) and detect "gitlab" if "GITLAB_CI" environment variable is set (e.g., inside GitLab CI). [$SCM_ENGINE_PROVIDER] - --api-token value GitHub/GitLab API token [$SCM_ENGINE_TOKEN, $GITHUB_TOKEN] - --base-url value Base URL for the SCM instance (default: "https://gitlab.com/") [$GITLAB_BASEURL, $CI_SERVER_URL, $GITHUB_API_URL] - --dry-run Dry run, don't actually _do_ actions, just print them (default: false) - --help, -h show help - --version, -v print the version -``` diff --git a/docs/github/commands.md b/docs/github/commands.md new file mode 100644 index 0000000..baa01c5 --- /dev/null +++ b/docs/github/commands.md @@ -0,0 +1,19 @@ +# Commands + +## `scm-engine` + +```plain +--8<-- "docs/github/_partials/cmd-root.md" +``` + +## `scm-engine github` + +```plain +--8<-- "docs/github/_partials/cmd-github.md" +``` + +## `scm-engine github evaluate` + +```plain +--8<-- "docs/github/_partials/cmd-github-evaluate.md" +``` diff --git a/docs/gitlab/commands.md b/docs/gitlab/commands.md new file mode 100644 index 0000000..e4352f6 --- /dev/null +++ b/docs/gitlab/commands.md @@ -0,0 +1,36 @@ +# Commands + +## `scm-engine` + +```plain +--8<-- "docs/gitlab/_partials/cmd-root.md" +``` + +## `scm-engine gitlab` + +```plain +--8<-- "docs/gitlab/_partials/cmd-gitlab.md" +``` + +## `scm-engine gitlab evaluate` + +```plain +--8<-- "docs/gitlab/_partials/cmd-gitlab-evaluate.md" +``` + +## `scm-engine gitlab server` + +Point your GitLab webhook at the `/gitlab` endpoint. + +Support the following events, and they will both trigger an Merge Request `evaluation` + +- [`Comments`](https://docs.gitlab.com/ee/user/project/integrations/webhook_events.html#comment-events) - A comment is made or edited on an issue or merge request. +- [`Merge request events`](https://docs.gitlab.com/ee/user/project/integrations/webhook_events.html#merge-request-events) - A merge request is created, updated, or merged. + +!!! tip + + You have access to the raw webhook event payload via `webhook_event.*` fields in Expr script fields when using `server` mode. See the [GitLab Webhook Events documentation](https://docs.gitlab.com/ee/user/project/integrations/webhook_events.html) for available fields. + +```plain +--8<-- "docs/gitlab/_partials/cmd-gitlab-server.md" +``` diff --git a/main.go b/main.go index b91f5ae..a536260 100644 --- a/main.go +++ b/main.go @@ -8,6 +8,7 @@ import ( "github.com/davecgh/go-spew/spew" "github.com/jippi/scm-engine/cmd" + "github.com/jippi/scm-engine/pkg/state" "github.com/jippi/scm-engine/pkg/tui" "github.com/urfave/cli/v2" slogctx "github.com/veqryn/slog-context" @@ -37,9 +38,13 @@ func main() { }, }, Before: func(cCtx *cli.Context) error { + // Setup global state cCtx.Context = tui.NewContext(cCtx.Context, cCtx.App.Writer, cCtx.App.ErrWriter) cCtx.Context = slogctx.With(cCtx.Context, "scm_engine_version", version) + // Write global flags to context + cCtx.Context = state.WithDryRun(cCtx.Context, cCtx.Bool(cmd.FlagDryRun)) + return nil }, Flags: []cli.Flag{ @@ -52,33 +57,6 @@ func main() { "SCM_ENGINE_CONFIG_FILE", }, }, - &cli.StringFlag{ - Name: cmd.FlagProvider, - Usage: `SCM provider to use. Must be either "github" or "gitlab". SCM Engine will automatically detect "github" if "GITHUB_ACTIONS" environment variable is set (e.g., inside GitHub Actions) and detect "gitlab" if "GITLAB_CI" environment variable is set (e.g., inside GitLab CI).`, - Value: detectProviderFromEnv(), - EnvVars: []string{ - "SCM_ENGINE_PROVIDER", - }, - }, - &cli.StringFlag{ - Name: cmd.FlagAPIToken, - Usage: "GitHub/GitLab API token", - Required: true, - EnvVars: []string{ - "SCM_ENGINE_TOKEN", // SCM Engine Native - "GITHUB_TOKEN", // GitHub Actions - }, - }, - &cli.StringFlag{ - Name: cmd.FlagSCMBaseURL, - Usage: "Base URL for the SCM instance", - Value: "https://gitlab.com/", - EnvVars: []string{ - "GITLAB_BASEURL", - "CI_SERVER_URL", // GitLab CI - "GITHUB_API_URL", // GitHub Actions - }, - }, &cli.BoolFlag{ Name: cmd.FlagDryRun, Usage: "Dry run, don't actually _do_ actions, just print them", @@ -86,13 +64,40 @@ func main() { }, }, Commands: []*cli.Command{ + cmd.GitLab, + cmd.GitHub, + // DEPRECATED COMMANDS { Name: "evaluate", Usage: "Evaluate a Merge Request", + Hidden: true, // DEPRECATED Args: true, ArgsUsage: " [mr_id, mr_id, ...]", Action: cmd.Evaluate, + Before: func(cCtx *cli.Context) error { + cCtx.Context = state.WithBaseURL(cCtx.Context, cCtx.String(cmd.FlagSCMBaseURL)) + cCtx.Context = state.WithProvider(cCtx.Context, "gitlab") + cCtx.Context = state.WithToken(cCtx.Context, cCtx.String(cmd.FlagAPIToken)) + + return nil + }, Flags: []cli.Flag{ + &cli.StringFlag{ + Name: cmd.FlagAPIToken, + Usage: "GitLab API token", + EnvVars: []string{ + "SCM_ENGINE_TOKEN", // SCM Engine Native + }, + }, + &cli.StringFlag{ + Name: cmd.FlagSCMBaseURL, + Usage: "Base URL for the SCM instance", + Value: "https://gitlab.com/", + EnvVars: []string{ + "SCM_ENGINE_BASE_URL", // SCM Engine Native + "CI_SERVER_URL", // GitLab CI + }, + }, &cli.BoolFlag{ Name: cmd.FlagUpdatePipeline, Usage: "Update the CI pipeline status with progress", @@ -107,8 +112,7 @@ func main() { Required: true, EnvVars: []string{ "GITLAB_PROJECT", - "CI_PROJECT_PATH", // GitLab CI - "GITHUB_REPOSITORY", // GitHub Actions + "CI_PROJECT_PATH", // GitLab CI }, }, &cli.StringFlag{ @@ -123,37 +127,6 @@ func main() { Usage: "The git commit sha", EnvVars: []string{ "CI_COMMIT_SHA", // GitLab CI - "GITHUB_SHA", // GitHub Actions - }, - }, - }, - }, - { - Name: "server", - Usage: "Start HTTP server for webhook event driven usage", - Action: cmd.Server, - Flags: []cli.Flag{ - &cli.StringFlag{ - Name: cmd.FlagWebhookSecret, - Usage: "Used to validate received payloads. Sent with the request in the X-Gitlab-Token HTTP header", - EnvVars: []string{ - "SCM_ENGINE_WEBHOOK_SECRET", - }, - }, - &cli.StringFlag{ - Name: cmd.FlagServerListen, - Usage: "IP + Port that the HTTP server should listen on", - Value: "0.0.0.0:3000", - EnvVars: []string{ - "SCM_ENGINE_LISTEN", - }, - }, - &cli.BoolFlag{ - Name: cmd.FlagUpdatePipeline, - Usage: "Update the CI pipeline status with progress", - Value: true, - EnvVars: []string{ - "SCM_ENGINE_UPDATE_PIPELINE", }, }, }, diff --git a/mkdocs.yml b/mkdocs.yml index ec6c5d2..c3370aa 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -12,9 +12,8 @@ nav: - index.md - install.md - configuration.md - - ... | commands/*.md - - ... | github/*.md - ... | gitlab/*.md + - ... | github/*.md plugins: - awesome-pages: # pip install mkdocs-awesome-pages-plugin