diff --git a/.drone.yml b/.drone.yml index e688b8cbbd6..59a1e5332bc 100644 --- a/.drone.yml +++ b/.drone.yml @@ -4119,7 +4119,7 @@ steps: image: golang:1.20.1 name: compile-build-cmd - commands: - - ./bin/build artifacts publish --security --tag $${DRONE_TAG} --src-bucket $${PRERELEASE_BUCKET} + - ./bin/build artifacts packages --security --tag $${DRONE_TAG} --src-bucket $${PRERELEASE_BUCKET} depends_on: - compile-build-cmd environment: @@ -4131,10 +4131,21 @@ steps: from_secret: prerelease_bucket SECURITY_DEST_BUCKET: from_secret: security_dest_bucket + image: grafana/grafana-ci-deploy:1.3.3 + name: publish-artifacts +- commands: + - ./bin/build artifacts static-assets --tag ${DRONE_TAG} + depends_on: + - compile-build-cmd + environment: + GCP_KEY: + from_secret: gcp_key + PRERELEASE_BUCKET: + from_secret: prerelease_bucket STATIC_ASSET_EDITIONS: from_secret: static_asset_editions image: grafana/grafana-ci-deploy:1.3.3 - name: publish-artifacts + name: publish-static-assets trigger: event: - promote @@ -4170,7 +4181,7 @@ steps: image: golang:1.20.1 name: compile-build-cmd - commands: - - ./bin/build artifacts publish --tag $${DRONE_TAG} --src-bucket $${PRERELEASE_BUCKET} + - ./bin/build artifacts packages --tag $${DRONE_TAG} --src-bucket $${PRERELEASE_BUCKET} depends_on: - compile-build-cmd environment: @@ -4182,10 +4193,32 @@ steps: from_secret: prerelease_bucket SECURITY_DEST_BUCKET: from_secret: security_dest_bucket + image: grafana/grafana-ci-deploy:1.3.3 + name: publish-artifacts +- commands: + - ./bin/build artifacts static-assets --tag ${DRONE_TAG} + depends_on: + - compile-build-cmd + environment: + GCP_KEY: + from_secret: gcp_key + PRERELEASE_BUCKET: + from_secret: prerelease_bucket STATIC_ASSET_EDITIONS: from_secret: static_asset_editions image: grafana/grafana-ci-deploy:1.3.3 - name: publish-artifacts + name: publish-static-assets +- commands: + - ./bin/build artifacts storybook --tag ${DRONE_TAG} + depends_on: + - compile-build-cmd + environment: + GCP_KEY: + from_secret: gcp_key + PRERELEASE_BUCKET: + from_secret: prerelease_bucket + image: grafana/grafana-ci-deploy:1.3.3 + name: publish-storybook trigger: event: - promote @@ -6653,6 +6686,6 @@ kind: secret name: enterprise2_security_prefix --- kind: signature -hmac: 9b71733a5b0ba599d7863d6b4b8398f512d6b23f5fb4b70771ded64cbdec08f1 +hmac: cf4c62a39dcda88dd6df1cfb62c848527c7df5ee8936c7fb0da5822617a56f3a ... diff --git a/pkg/build/cmd/flags.go b/pkg/build/cmd/flags.go index f9ce438f290..fa45bfb5659 100644 --- a/pkg/build/cmd/flags.go +++ b/pkg/build/cmd/flags.go @@ -57,4 +57,22 @@ var ( Name: "tag", Usage: "Grafana version tag", } + securityFlag = cli.BoolFlag{ + Name: "security", + Usage: "Security release", + } + srcFlag = cli.StringFlag{ + Name: "src-bucket", + Value: "grafana-prerelease", + Usage: "Google Cloud Storage bucket", + } + securityDestBucketFlag = cli.StringFlag{ + Name: "security-dest-bucket", + Usage: "Google Cloud Storage bucket for security packages (or $SECURITY_DEST_BUCKET)", + } + destFlag = cli.StringFlag{ + Name: "dest-bucket", + Value: "grafana-downloads", + Usage: "Google Cloud Storage bucket for published packages", + } ) diff --git a/pkg/build/cmd/main.go b/pkg/build/cmd/main.go index 2d2f9cbe4c6..225a02f38bc 100644 --- a/pkg/build/cmd/main.go +++ b/pkg/build/cmd/main.go @@ -198,42 +198,31 @@ func main() { Usage: "Handle Grafana artifacts", Subcommands: cli.Commands{ { - Name: "publish", - Usage: "Publish Grafana artifacts", - Action: PublishArtifactsAction, + Name: "storybook", + Usage: "Publish Grafana storybook", + Action: PublishStorybookAction, Flags: []cli.Flag{ &editionFlag, - &cli.BoolFlag{ - Name: "security", - Usage: "Security release", - }, + &tagFlag, + &srcFlag, &cli.StringFlag{ - Name: "security-dest-bucket", - Usage: "Google Cloud Storage bucket for security packages (or $SECURITY_DEST_BUCKET)", - }, - &cli.StringFlag{ - Name: "tag", - Usage: "Grafana version tag", - }, - &cli.StringFlag{ - Name: "src-bucket", - Value: "grafana-prerelease", - Usage: "Google Cloud Storage bucket", - }, - &cli.StringFlag{ - Name: "dest-bucket", - Value: "grafana-downloads", - Usage: "Google Cloud Storage bucket for published packages", - }, - &cli.StringFlag{ - Name: "enterprise2-dest-bucket", - Value: "grafana-downloads-enterprise2", - Usage: "Google Cloud Storage bucket for published packages", - }, - &cli.StringFlag{ - Name: "enterprise2-security-prefix", - Usage: "Bucket path prefix for enterprise2 security releases (or $ENTERPRISE2_SECURITY_PREFIX)", + Name: "storybook-bucket", + Value: "grafana-storybook", + Usage: "Google Cloud Storage bucket for storybooks", }, + }, + }, + { + Name: "static-assets", + Usage: "Publish Grafana static assets", + Action: PublishStaticAssetsAction, + Flags: []cli.Flag{ + &editionFlag, + &securityFlag, + &securityDestBucketFlag, + &tagFlag, + &srcFlag, + &destFlag, &cli.StringFlag{ Name: "static-assets-bucket", Value: "grafana-static-assets", @@ -243,10 +232,32 @@ func main() { Name: "static-asset-editions", Usage: "All the editions of the static assets (or $STATIC_ASSET_EDITIONS)", }, + }, + }, + { + Name: "packages", + Usage: "Publish Grafana packages", + Action: PublishArtifactsAction, + Flags: []cli.Flag{ + &editionFlag, + &securityFlag, + &securityDestBucketFlag, + &tagFlag, + &srcFlag, + &destFlag, + &cli.StringSliceFlag{ + Name: "artifacts-editions", + Value: cli.NewStringSlice("oss", "enterprise", "enterprise2"), + Usage: "Editions for which the artifacts should be delivered (oss,enterprise,enterprise2), (or $ARTIFACTS_EDITIONS)", + }, &cli.StringFlag{ - Name: "storybook-bucket", - Value: "grafana-storybook", - Usage: "Google Cloud Storage bucket for storybooks", + Name: "enterprise2-dest-bucket", + Value: "grafana-downloads-enterprise2", + Usage: "Google Cloud Storage bucket for published packages", + }, + &cli.StringFlag{ + Name: "enterprise2-security-prefix", + Usage: "Bucket path prefix for enterprise2 security releases (or $ENTERPRISE2_SECURITY_PREFIX)", }, }, }, diff --git a/pkg/build/cmd/publishartifacts.go b/pkg/build/cmd/publishartifacts.go index bd158d6d3ad..bf3f162e362 100644 --- a/pkg/build/cmd/publishartifacts.go +++ b/pkg/build/cmd/publishartifacts.go @@ -3,60 +3,16 @@ package main import ( "fmt" "log" - "os" - "os/exec" "path/filepath" "strings" + "github.com/grafana/grafana/pkg/build/env" "github.com/grafana/grafana/pkg/build/gcloud" - "github.com/grafana/grafana/pkg/build/versions" + "github.com/grafana/grafana/pkg/build/gcloud/storage" "github.com/urfave/cli/v2" ) -type publishConfig struct { - tag string - srcBucket string - destBucket string - enterprise2DestBucket string - enterprise2SecurityPrefix string - staticAssetsBucket string - staticAssetEditions []string - storybookBucket string - security bool -} - -// requireListWithEnvFallback first checks the CLI for a flag with the required -// name. If this is empty, it falls back to taking the environment variable. -// Sadly, we cannot use cli.Flag.EnvVars for this due to it potentially leaking -// environment variables as default values in usage-errors. -func requireListWithEnvFallback(cctx *cli.Context, name string, envName string) ([]string, error) { - result := cctx.StringSlice(name) - if len(result) == 0 { - for _, v := range strings.Split(os.Getenv(envName), ",") { - value := strings.TrimSpace(v) - if value != "" { - result = append(result, value) - } - } - } - if len(result) == 0 { - return nil, cli.Exit(fmt.Sprintf("Required flag (%s) or environment variable (%s) not set", name, envName), 1) - } - return result, nil -} - -func requireStringWithEnvFallback(cctx *cli.Context, name string, envName string) (string, error) { - result := cctx.String(name) - if result == "" { - result = os.Getenv(envName) - } - if result == "" { - return "", cli.Exit(fmt.Sprintf("Required flag (%s) or environment variable (%s) not set", name, envName), 1) - } - return result, nil -} - -// Action implements the sub-command "publish-artifacts". +// PublishArtifactsAction Action implements the sub-command "publish-artifacts". func PublishArtifactsAction(c *cli.Context) error { if c.NArg() > 0 { if err := cli.ShowSubcommandHelp(c); err != nil { @@ -65,17 +21,23 @@ func PublishArtifactsAction(c *cli.Context) error { return cli.Exit("", 1) } - staticAssetEditions, err := requireListWithEnvFallback(c, "static-asset-editions", "STATIC_ASSET_EDITIONS") + security := c.Bool("security") + var securityDestBucket, enterprise2SecurityPrefix string + + artifactsEditions, err := env.RequireListWithEnvFallback(c, "artifacts-editions", "ARTIFACTS_EDITIONS") if err != nil { return err } - securityDestBucket, err := requireStringWithEnvFallback(c, "security-dest-bucket", "SECURITY_DEST_BUCKET") - if err != nil { - return err - } - enterprise2SecurityPrefix, err := requireStringWithEnvFallback(c, "enterprise2-security-prefix", "ENTERPRISE2_SECURITY_PREFIX") - if err != nil { - return err + + if security { + securityDestBucket, err = env.RequireStringWithEnvFallback(c, "security-dest-bucket", "SECURITY_DEST_BUCKET") + if err != nil { + return err + } + enterprise2SecurityPrefix, err = env.RequireStringWithEnvFallback(c, "enterprise2-security-prefix", "ENTERPRISE2_SECURITY_PREFIX") + if err != nil { + return err + } } if err := gcloud.ActivateServiceAccount(); err != nil { @@ -87,10 +49,7 @@ func PublishArtifactsAction(c *cli.Context) error { destBucket: c.String("dest-bucket"), enterprise2DestBucket: c.String("enterprise2-dest-bucket"), enterprise2SecurityPrefix: enterprise2SecurityPrefix, - staticAssetsBucket: c.String("static-assets-bucket"), - staticAssetEditions: staticAssetEditions, - storybookBucket: c.String("storybook-bucket"), - security: c.Bool("security"), + security: security, tag: strings.TrimPrefix(c.String("tag"), "v"), } @@ -98,114 +57,56 @@ func PublishArtifactsAction(c *cli.Context) error { cfg.destBucket = securityDestBucket } - err = copyStaticAssets(cfg) + gcs, err := storage.New() if err != nil { return err } - err = copyStorybook(cfg) - if err != nil { - return err - } - err = copyDownloads(cfg) - if err != nil { - return err - } - err = copyEnterprise2Downloads(cfg) - if err != nil { - return err + + for _, edition := range artifactsEditions { + switch edition { + case "oss", "enterprise": + err = copyArtifacts(c, gcs, cfg, edition) + if err != nil { + return err + } + case "enterprise2": + err = copyEnterprise2Artifacts(c, gcs, cfg) + if err != nil { + return err + } + default: + log.Printf("unrecognised artifacts edition: %s\n", edition) + } } + return nil } -func copyStaticAssets(cfg publishConfig) error { - for _, edition := range cfg.staticAssetEditions { - log.Printf("Copying static assets for %s", edition) - srcURL := fmt.Sprintf("%s/artifacts/static-assets/%s/%s/*", cfg.srcBucket, edition, cfg.tag) - destURL := fmt.Sprintf("%s/%s/%s/", cfg.staticAssetsBucket, edition, cfg.tag) - err := gcsCopy("static assets", srcURL, destURL) - if err != nil { - return fmt.Errorf("error copying static assets, %q", err) - } +func copyArtifacts(c *cli.Context, gcs *storage.Client, cfg publishConfig, edition string) error { + bucket := gcs.Bucket(cfg.destBucket) + destURL := edition + if !cfg.security { + destURL = filepath.Join(destURL, "release") } - log.Printf("Successfully copied static assets!") - return nil -} - -func copyStorybook(cfg publishConfig) error { - if cfg.security { - log.Printf("skipping storybook copy - not needed for a security release") - return nil - } - log.Printf("Copying storybooks...") - srcURL := fmt.Sprintf("%s/artifacts/storybook/v%s/*", cfg.srcBucket, cfg.tag) - destURL := fmt.Sprintf("%s/%s", cfg.storybookBucket, cfg.tag) - err := gcsCopy("storybook", srcURL, destURL) - if err != nil { - return fmt.Errorf("error copying storybook. %q", err) - } - stableVersion, err := versions.GetLatestVersion(versions.LatestStableVersionURL) - if err != nil { + log.Printf("Copying downloads for %s, from %s bucket to %s bucket", edition, cfg.srcBucket, destURL) + if err := gcs.CopyRemoteDir(c.Context, gcs.Bucket(cfg.srcBucket), fmt.Sprintf("artifacts/downloads/v%s/%s/release", cfg.tag, edition), bucket, destURL); err != nil { return err } - isLatest, err := versions.IsGreaterThanOrEqual(cfg.tag, stableVersion) - if err != nil { - return err - } - if isLatest { - log.Printf("Copying storybooks to latest...") - srcURL := fmt.Sprintf("%s/artifacts/storybook/v%s/*", cfg.srcBucket, cfg.tag) - destURL := fmt.Sprintf("%s/latest", cfg.storybookBucket) - err := gcsCopy("storybook (latest)", srcURL, destURL) - if err != nil { - return fmt.Errorf("error copying storybook to latest. %q", err) - } - } - log.Printf("Successfully copied storybook!") - return nil -} - -func copyDownloads(cfg publishConfig) error { - for _, edition := range []string{ - "oss", "enterprise", - } { - destURL := fmt.Sprintf("%s/%s/", cfg.destBucket, edition) - srcURL := fmt.Sprintf("%s/artifacts/downloads/v%s/%s/release/*", cfg.srcBucket, cfg.tag, edition) - if !cfg.security { - destURL = filepath.Join(destURL, "release") - } - log.Printf("Copying downloads for %s, from %s bucket to %s bucket", edition, srcURL, destURL) - err := gcsCopy("downloads", srcURL, destURL) - if err != nil { - return fmt.Errorf("error copying downloads, %q", err) - } - } log.Printf("Successfully copied downloads.") return nil } -func copyEnterprise2Downloads(cfg publishConfig) error { +func copyEnterprise2Artifacts(c *cli.Context, gcs *storage.Client, cfg publishConfig) error { + bucket := gcs.Bucket(cfg.enterprise2DestBucket) var prefix string if cfg.security { prefix = cfg.enterprise2SecurityPrefix } - srcURL := fmt.Sprintf("%s/artifacts/downloads-enterprise2/v%s/enterprise2/release/*", cfg.srcBucket, cfg.tag) - destURL := fmt.Sprintf("%s/enterprise2/%srelease", cfg.enterprise2DestBucket, prefix) - log.Printf("Copying downloads for enterprise2, from %s bucket to %s bucket", srcURL, destURL) - err := gcsCopy("enterprise2 downloads", srcURL, destURL) - if err != nil { - return fmt.Errorf("error copying ") - } - return nil -} - -func gcsCopy(desc, src, dest string) error { - args := strings.Split(fmt.Sprintf("-m cp -r gs://%s gs://%s", src, dest), " ") - // nolint:gosec - cmd := exec.Command("gsutil", args...) - out, err := cmd.CombinedOutput() - if err != nil { - return fmt.Errorf("failed to publish %s: %w\n%s", desc, err, out) + destURL := fmt.Sprintf("enterprise2/%srelease", prefix) + log.Printf("Copying downloads for enterprise2, from %s bucket to %s bucket", cfg.srcBucket, destURL) + if err := gcs.CopyRemoteDir(c.Context, gcs.Bucket(cfg.srcBucket), fmt.Sprintf("artifacts/downloads-enterprise2/v%s/enterprise2/release", cfg.tag), bucket, destURL); err != nil { + return err } return nil } diff --git a/pkg/build/cmd/publishconfig.go b/pkg/build/cmd/publishconfig.go new file mode 100644 index 00000000000..4715fce25e7 --- /dev/null +++ b/pkg/build/cmd/publishconfig.go @@ -0,0 +1,13 @@ +package main + +type publishConfig struct { + tag string + srcBucket string + destBucket string + enterprise2DestBucket string + enterprise2SecurityPrefix string + staticAssetsBucket string + staticAssetEditions []string + storybookBucket string + security bool +} diff --git a/pkg/build/cmd/publishstaticassets.go b/pkg/build/cmd/publishstaticassets.go new file mode 100644 index 00000000000..5b6eff9f12a --- /dev/null +++ b/pkg/build/cmd/publishstaticassets.go @@ -0,0 +1,51 @@ +package main + +import ( + "fmt" + "strings" + + "github.com/grafana/grafana/pkg/build/env" + "github.com/grafana/grafana/pkg/build/gcloud" + "github.com/grafana/grafana/pkg/build/gcloud/storage" + "github.com/urfave/cli/v2" +) + +// PublishStaticAssetsAction Action implements the sub-command "artifacts static-assets". +func PublishStaticAssetsAction(c *cli.Context) error { + if c.NArg() > 0 { + if err := cli.ShowSubcommandHelp(c); err != nil { + return cli.Exit(err.Error(), 1) + } + return cli.Exit("", 1) + } + + staticAssetEditions, err := env.RequireListWithEnvFallback(c, "static-asset-editions", "STATIC_ASSET_EDITIONS") + if err != nil { + return err + } + + if err := gcloud.ActivateServiceAccount(); err != nil { + return fmt.Errorf("error connecting to gcp, %q", err) + } + + cfg := publishConfig{ + srcBucket: c.String("src-bucket"), + staticAssetsBucket: c.String("static-assets-bucket"), + staticAssetEditions: staticAssetEditions, + tag: strings.TrimPrefix(c.String("tag"), "v"), + } + + gcs, err := storage.New() + if err != nil { + return err + } + bucket := gcs.Bucket(cfg.staticAssetsBucket) + + for _, edition := range staticAssetEditions { + if err := gcs.CopyRemoteDir(c.Context, gcs.Bucket(cfg.srcBucket), fmt.Sprintf("artifacts/static-assets/%s/%s", edition, cfg.tag), bucket, fmt.Sprintf("%s/%s", edition, cfg.tag)); err != nil { + return err + } + } + + return nil +} diff --git a/pkg/build/cmd/publishstorybook.go b/pkg/build/cmd/publishstorybook.go new file mode 100644 index 00000000000..b147d9a7b40 --- /dev/null +++ b/pkg/build/cmd/publishstorybook.go @@ -0,0 +1,64 @@ +package main + +import ( + "fmt" + "log" + "strings" + + "github.com/grafana/grafana/pkg/build/gcloud" + "github.com/grafana/grafana/pkg/build/gcloud/storage" + "github.com/grafana/grafana/pkg/build/versions" + "github.com/urfave/cli/v2" +) + +// PublishStorybookAction Action implements the sub-command "publish-artifacts". +func PublishStorybookAction(c *cli.Context) error { + if c.NArg() > 0 { + if err := cli.ShowSubcommandHelp(c); err != nil { + return cli.Exit(err.Error(), 1) + } + return cli.Exit("", 1) + } + + if err := gcloud.ActivateServiceAccount(); err != nil { + return fmt.Errorf("error connecting to gcp, %q", err) + } + + cfg := publishConfig{ + srcBucket: c.String("src-bucket"), + storybookBucket: c.String("storybook-bucket"), + tag: strings.TrimPrefix(c.String("tag"), "v"), + } + + gcs, err := storage.New() + if err != nil { + return err + } + bucket := gcs.Bucket(cfg.storybookBucket) + if err := gcs.CopyRemoteDir(c.Context, gcs.Bucket(cfg.srcBucket), fmt.Sprintf("artifacts/storybook/v%s", cfg.tag), bucket, cfg.tag); err != nil { + return err + } + + if latest, err := isLatest(cfg); err != nil && latest { + log.Printf("Copying storybooks to latest...") + if err := gcs.CopyRemoteDir(c.Context, gcs.Bucket(cfg.srcBucket), fmt.Sprintf("artifacts/storybook/v%s", cfg.tag), bucket, "latest"); err != nil { + return err + } + } else { + return err + } + + return nil +} + +func isLatest(cfg publishConfig) (bool, error) { + stableVersion, err := versions.GetLatestVersion(versions.LatestStableVersionURL) + if err != nil { + return false, err + } + isLatest, err := versions.IsGreaterThanOrEqual(cfg.tag, stableVersion) + if err != nil { + return false, err + } + return isLatest, nil +} diff --git a/pkg/build/env/fallback.go b/pkg/build/env/fallback.go new file mode 100644 index 00000000000..7f4f31cb09e --- /dev/null +++ b/pkg/build/env/fallback.go @@ -0,0 +1,40 @@ +package env + +import ( + "fmt" + "os" + "strings" + + "github.com/urfave/cli/v2" +) + +// RequireListWithEnvFallback first checks the CLI for a flag with the required +// name. If this is empty, it falls back to taking the environment variable. +// Sadly, we cannot use cli.Flag.EnvVars for this due to it potentially leaking +// environment variables as default values in usage-errors. +func RequireListWithEnvFallback(cctx *cli.Context, name string, envName string) ([]string, error) { + result := cctx.StringSlice(name) + if len(result) == 0 { + for _, v := range strings.Split(os.Getenv(envName), ",") { + value := strings.TrimSpace(v) + if value != "" { + result = append(result, value) + } + } + } + if len(result) == 0 { + return nil, cli.Exit(fmt.Sprintf("Required flag (%s) or environment variable (%s) not set", name, envName), 1) + } + return result, nil +} + +func RequireStringWithEnvFallback(cctx *cli.Context, name string, envName string) (string, error) { + result := cctx.String(name) + if result == "" { + result = os.Getenv(envName) + } + if result == "" { + return "", cli.Exit(fmt.Sprintf("Required flag (%s) or environment variable (%s) not set", name, envName), 1) + } + return result, nil +} diff --git a/pkg/build/env/fallback_test.go b/pkg/build/env/fallback_test.go new file mode 100644 index 00000000000..d14e13ee774 --- /dev/null +++ b/pkg/build/env/fallback_test.go @@ -0,0 +1,143 @@ +package env + +import ( + "flag" + "fmt" + "os" + "testing" + + "github.com/stretchr/testify/require" + "github.com/urfave/cli/v2" +) + +const ( + flag1 = "flag1" + flag2 = "flag2" +) + +func TestRequireListWithEnvFallback(t *testing.T) { + var app = cli.NewApp() + tests := []struct { + testName string + ctx *cli.Context + name string + envName string + expected []string + expectedErr error + }{ + { + testName: "string slice present in context", + ctx: cli.NewContext(app, applyFlagSet(t, flag1, "a"), nil), + name: flag1, + envName: "", + expected: []string{"a"}, + expectedErr: nil, + }, + { + testName: "string slice present in env", + ctx: cli.NewContext(app, flag.NewFlagSet("test", 0), nil), + name: flag1, + envName: setEnv(t, flag1, "a"), + expected: []string{"a"}, + expectedErr: nil, + }, + { + testName: "string slice absent in both context and env", + ctx: cli.NewContext(app, flag.NewFlagSet("test", 0), nil), + name: flag1, + envName: "", + expected: []string(nil), + expectedErr: cli.Exit("Required flag (flag1) or environment variable () not set", 1), + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + flagList, err := RequireListWithEnvFallback(tt.ctx, tt.name, tt.envName) + if tt.expectedErr != nil { + require.Error(t, err) + } + require.Equal(t, tt.expected, flagList) + }) + } +} + +func TestRequireStringWithEnvFallback(t *testing.T) { + var app = cli.NewApp() + tests := []struct { + testName string + ctx *cli.Context + name string + envName string + expected string + expectedErr error + }{ + { + testName: "string present in the context", + ctx: cli.NewContext(app, setFlags(t, flag1, flag2, flag.NewFlagSet("test", flag.ContinueOnError)), nil), + name: flag1, + envName: "", + expected: "a", + expectedErr: nil, + }, + { + testName: "string present in env", + ctx: cli.NewContext(app, setFlags(t, "", "", flag.NewFlagSet("test", flag.ContinueOnError)), nil), + name: flag1, + envName: setEnv(t, flag1, "a"), + expected: "a", + expectedErr: nil, + }, + { + testName: "string absent from both context and env", + ctx: cli.NewContext(app, setFlags(t, "", flag2, flag.NewFlagSet("test", flag.ContinueOnError)), nil), + name: flag1, + envName: "", + expected: "", + expectedErr: cli.Exit("Required flag (flag1) or environment variable () not set", 1), + }, + } + for _, tt := range tests { + t.Run(tt.testName, func(t *testing.T) { + flagString, err := RequireStringWithEnvFallback(tt.ctx, tt.name, tt.envName) + if tt.expectedErr != nil { + require.Error(t, err) + } + require.Equal(t, tt.expected, flagString) + }) + } +} + +func applyFlagSet(t *testing.T, aFlag, aValue string) *flag.FlagSet { + t.Helper() + var val cli.StringSlice + fl := cli.StringSliceFlag{Name: aFlag, EnvVars: []string{"FLAG"}, Value: &val} + set := flag.NewFlagSet("test", 0) + parseInput := []string{fmt.Sprintf("-%s", aFlag), aValue} + err := fl.Apply(set) + require.NoError(t, err) + err = set.Parse(parseInput) + require.NoError(t, err) + return set +} + +func setFlags(t *testing.T, flag1, flag2 string, flagSet *flag.FlagSet) *flag.FlagSet { + t.Helper() + if flag1 != "" { + flagSet.StringVar(&flag1, "flag1", "a", "") + } + if flag2 != "" { + flagSet.StringVar(&flag2, "flag2", "b", "") + } + return flagSet +} + +func setEnv(t *testing.T, key, value string) string { + t.Helper() + os.Clearenv() + + err := os.Setenv(key, value) + if err != nil { + require.NoError(t, err) + } + return key +} diff --git a/pkg/build/gcloud/storage/gsutil.go b/pkg/build/gcloud/storage/gsutil.go index f32189bc84e..8bc92066e94 100644 --- a/pkg/build/gcloud/storage/gsutil.go +++ b/pkg/build/gcloud/storage/gsutil.go @@ -206,7 +206,6 @@ func (client *Client) RemoteCopy(ctx context.Context, file File, fromBucket, toB return fmt.Errorf("failed to copy object %s, to %s, err: %w", file.FullPath, dstObject, err) } - log.Printf("%s was successfully copied to %v bucket!.\n\n", file.FullPath, toBucket) return nil } diff --git a/scripts/drone/events/release.star b/scripts/drone/events/release.star index bbfda28c2d7..efdb81f4521 100644 --- a/scripts/drone/events/release.star +++ b/scripts/drone/events/release.star @@ -557,17 +557,54 @@ def publish_artifacts_step(mode): "PRERELEASE_BUCKET": from_secret("prerelease_bucket"), "ENTERPRISE2_SECURITY_PREFIX": from_secret("enterprise2_security_prefix"), "SECURITY_DEST_BUCKET": from_secret("security_dest_bucket"), - "STATIC_ASSET_EDITIONS": from_secret("static_asset_editions"), }, "commands": [ - "./bin/build artifacts publish {}--tag $${{DRONE_TAG}} --src-bucket $${{PRERELEASE_BUCKET}}".format( + "./bin/build artifacts packages {}--tag $${{DRONE_TAG}} --src-bucket $${{PRERELEASE_BUCKET}}".format( security, ), ], "depends_on": ["compile-build-cmd"], } +def publish_static_assets_step(): + return { + "name": "publish-static-assets", + "image": publish_image, + "environment": { + "GCP_KEY": from_secret("gcp_key"), + "PRERELEASE_BUCKET": from_secret("prerelease_bucket"), + "STATIC_ASSET_EDITIONS": from_secret("static_asset_editions"), + }, + "commands": [ + "./bin/build artifacts static-assets --tag ${DRONE_TAG}", + ], + "depends_on": ["compile-build-cmd"], + } + +def publish_storybook_step(): + return { + "name": "publish-storybook", + "image": publish_image, + "environment": { + "GCP_KEY": from_secret("gcp_key"), + "PRERELEASE_BUCKET": from_secret("prerelease_bucket"), + }, + "commands": [ + "./bin/build artifacts storybook --tag ${DRONE_TAG}", + ], + "depends_on": ["compile-build-cmd"], + } + def publish_artifacts_pipelines(mode): + """Published artifacts after they've been stored and tested in prerelease buckets. + + Args: + mode: public or security. + Defaults to ''. + + Returns: + List of Drone pipelines. + """ trigger = { "event": ["promote"], "target": [mode], @@ -575,7 +612,10 @@ def publish_artifacts_pipelines(mode): steps = [ compile_build_cmd(), publish_artifacts_step(mode), + publish_static_assets_step(), ] + if mode != "security": + steps.extend([publish_storybook_step()]) return [ pipeline(