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

Add storybook command #107

Merged
merged 10 commits into from
Jul 27, 2023
1 change: 1 addition & 0 deletions cmd/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ var app = &cli.App{
ZipCommand,
ValidateCommand,
ProImageCommand,
StorybookCommand,
},
}

Expand Down
17 changes: 17 additions & 0 deletions cmd/storybook.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package main

import (
"github.com/grafana/grafana-build/pipelines"
"github.com/urfave/cli/v2"
)

var StorybookCommand = &cli.Command{
Name: "storybook",
Action: PipelineActionWithPackageInput(pipelines.Storybook),
Usage: "Using a grafana.tar.gz as input (ideally one built using the 'package' command), take the storybook files and upload them to the destination. This can be used to put Grafana's storybook assets into a bucket for external use.",
Flags: JoinFlagsWithDefault(
PackageInputFlags,
PublishFlags,
GCPFlags,
),
}
19 changes: 19 additions & 0 deletions containers/storybook.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package containers

import (
"dagger.io/dagger"
)

// Storybook returns a dagger.Directory which contains the Grafana NPM packages from the grafana source code.
guicaulada marked this conversation as resolved.
Show resolved Hide resolved
func Storybook(d *dagger.Client, src *dagger.Directory, opts *YarnCacheOpts, version, nodeVersion string) *dagger.Directory {
c := NodeContainer(d, NodeImage(nodeVersion)).
WithMountedDirectory("/src", src).
WithWorkdir("/src")

c = WithYarnCache(c, opts)

c = c.WithExec([]string{"yarn", "install", "--immutable"}).
WithExec([]string{"yarn", "run", "storybook:build"})

return c.Directory("./packages/grafana-ui/dist/storybook")
}
3 changes: 3 additions & 0 deletions pipelines/package.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ var PackagedPaths = []string{
"plugins-bundled/",
"public/",
"npm-artifacts/",
"storybook",
guicaulada marked this conversation as resolved.
Show resolved Hide resolved
}

func PathsWithRoot(root string, paths []string) []string {
Expand Down Expand Up @@ -100,6 +101,7 @@ func PackageFiles(ctx context.Context, d *dagger.Client, opts PackageOpts) (map[
var (
frontend = containers.CompileFrontend(d, src, cacheOpts, nodeVersion)
npmPackages = containers.NPMPackages(d, src, cacheOpts, version, nodeVersion)
storybook = containers.Storybook(d, src, cacheOpts, version, nodeVersion)
)

name := "grafana"
Expand All @@ -123,6 +125,7 @@ func PackageFiles(ctx context.Context, d *dagger.Client, opts PackageOpts) (map[
WithMountedDirectory(path.Join("/src", root, "bin"), backend).
WithMountedDirectory(path.Join("/src", root, "public"), frontend).
WithMountedDirectory(path.Join("/src", root, "npm-artifacts"), npmPackages).
WithMountedDirectory(path.Join("/src", root, "storybook"), storybook).
WithWorkdir("/src")

opts := TarFileOpts{
Expand Down
47 changes: 47 additions & 0 deletions pipelines/storybook.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
package pipelines

import (
"context"
"fmt"
"log"
"os"
"strings"

"dagger.io/dagger"
"github.com/grafana/grafana-build/containers"
)

func Storybook(ctx context.Context, d *dagger.Client, args PipelineArgs) error {
packages, err := containers.GetPackages(ctx, d, args.PackageInputOpts, args.GCPOpts)
if err != nil {
return err
}

// Extract the package(s)
for i, v := range args.PackageInputOpts.Packages {
var (
name = ReplaceExt(v, "")
targz = packages[i]
)

// We can't use path.Join here because publishopts.Destination might have a URL scheme which will get santizied, and we can't use filepath.Join because Windows would use \\ filepath separators.
dst := strings.Join([]string{args.PublishOpts.Destination, name, "storybook"}, "/")

log.Println("Copying storybook assets for", name, "to", dst)
folder := fmt.Sprintf("/src/%s", name)

// gcloud rsync the storybook folder to ['dst']/storybook
storybook := d.Container().From("busybox").
WithFile("/src/grafana.tar.gz", targz).
WithExec([]string{"mkdir", "-p", folder}).
WithExec([]string{"tar", "--strip-components=1", "-xzf", "/src/grafana.tar.gz", "-C", folder}).
Directory(folder + "/storybook")

dst, err := containers.PublishDirectory(ctx, d, storybook, args.GCPOpts, dst)
if err != nil {
return err
}
fmt.Fprintln(os.Stdout, dst)
}
return nil
}
24 changes: 16 additions & 8 deletions scripts/drone_publish_tag_all.sh
Original file line number Diff line number Diff line change
Expand Up @@ -54,12 +54,19 @@ cat pro.txt grafana.txt > assets.txt
# Create the npm artifacts using only the amd64 linux package
go run ./scripts/copy_npm $(cat assets.txt | grep tar.gz | grep linux | grep amd64 | grep -v enterprise | grep -v pro | grep -v sha256 -m 1) > npm.txt

# Copy only the linux/amd64 edition storybook into a separate folder
go run ./cmd storybook \
$(cat assets.txt | grep tar.gz | grep linux | grep amd64 | grep -v enterprise | grep -v pro | grep -v sha256 | awk '{print "--package=" $0}') \
--destination=${local_dst} \
--gcp-service-account-key-base64=${GCP_KEY_BASE64} > storybook.txt &

# Use the non-pro, non-windows, non-darwin packages and create deb packages from them.
go run ./cmd deb \
$(cat assets.txt | grep tar.gz | grep -v docker | grep -v sha256 | grep -v windows | grep -v darwin | awk '{print "--package=" $0}') \
--checksum \
--destination=${local_dst} \
--gcp-service-account-key-base64=${GCP_KEY_BASE64} > debs.txt &

# Make rpm installers for all the same Linux distros, and sign them because RPM packages are signed.
go run ./cmd rpm \
$(cat assets.txt | grep tar.gz | grep -v docker | grep -v sha256 | grep -v windows | grep -v darwin | awk '{print "--package=" $0}') \
Expand All @@ -70,37 +77,38 @@ go run ./cmd rpm \
--gpg-private-key-base64=$(echo $GPG_PRIVATE_KEY | base64 -w 0) \
--gpg-public-key-base64=$(echo $GPG_PUBLIC_KEY | base64 -w 0) \
--gpg-passphrase-base64=$(echo $GPG_PASSPHRASE | base64 -w 0) > rpms.txt &

# For Windows we distribute zips and exes
go run ./cmd zip \
$(cat assets.txt | grep tar.gz | grep -v docker | grep -v sha256 | grep windows | awk '{print "--package=" $0}') \
--destination=${local_dst} \
--gcp-service-account-key-base64=${GCP_KEY_BASE64} \
--checksum > zips.txt &

go run ./cmd windows-installer \
$(cat assets.txt | grep tar.gz | grep -v docker | grep -v sha256 | grep windows | awk '{print "--package=" $0}') \
--destination=${local_dst} \
--gcp-service-account-key-base64=${GCP_KEY_BASE64} \
--checksum > exes.txt &


wait

# Build a docker iamge for all Linux distros except armv6
# Build a docker image for all Linux distros except armv6
go run ./cmd docker \
$(cat assets.txt | grep tar.gz | grep -v docker | grep -v sha256 | grep -v windows | grep -v darwin | grep -v arm-6 | awk '{print "--package=" $0}') \
--checksum \
--ubuntu-base="ubuntu:22.10" \
--alpine-base="alpine:3.18.0" \
--destination=${local_dst} \
--gcp-service-account-key-base64=${GCP_KEY_BASE64} > docker.txt
--gcp-service-account-key-base64=${GCP_KEY_BASE64} > docker.txt &

# Copy only the linux/amd64 edition frontends into a separate folder
go run ./cmd cdn \
$(cat assets.txt | grep tar.gz | grep pro | grep -v docker | grep -v sha256 | grep linux_amd64 | awk '{print "--package=" $0}') \
$(cat assets.txt | grep tar.gz | grep pro | grep linux | grep amd64 | grep -v docker | grep -v sha256 | awk '{print "--package=" $0}') \
--destination=${local_dst} \
--gcp-service-account-key-base64=${GCP_KEY_BASE64} > cdn.txt
--gcp-service-account-key-base64=${GCP_KEY_BASE64} > cdn.txt &

wait

cat debs.txt rpms.txt zips.txt exes.txt docker.txt cdn.txt npm.txt >> assets.txt
cat debs.txt rpms.txt zips.txt exes.txt docker.txt cdn.txt npm.txt storybook.txt >> assets.txt

# Move the tar.gz packages to their expected locations
cat assets.txt | DESTINATION=gs://grafana-prerelease-dev go run ./scripts/move_packages.go ./dist/prerelease
8 changes: 7 additions & 1 deletion scripts/drone_publish_tag_grafana.sh
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,12 @@ echo "Done building tar.gz packages..."
# Create the npm artifacts using only the amd64 linux package
go run ./scripts/copy_npm $(cat assets.txt | grep tar.gz | grep linux | grep amd64 | grep -v sha256 -m 1) > npm.txt &

# Copy only the linux/amd64 edition storybook into a separate folder
go run ./cmd storybook \
$(cat assets.txt | grep tar.gz | grep linux | grep amd64 | grep -v sha256 | awk '{print "--package=" $0}') \
--destination=${local_dst} \
--gcp-service-account-key-base64=${GCP_KEY_BASE64} > storybook.txt &

# Use the non-windows, non-darwin packages and create deb packages from them.
go run ./cmd deb \
$(cat assets.txt | grep tar.gz | grep -v docker | grep -v sha256 | grep -v windows | grep -v darwin | awk '{print "--package=" $0}') \
Expand Down Expand Up @@ -71,7 +77,7 @@ go run ./cmd docker \

wait

cat debs.txt rpms.txt zips.txt exes.txt docker.txt npm.txt >> assets.txt
cat debs.txt rpms.txt zips.txt exes.txt docker.txt npm.txt storybook.txt >> assets.txt

# Move the tar.gz packages to their expected locations
cat assets.txt | DESTINATION=gs://grafana-prerelease-dev go run ./scripts/move_packages.go ./dist/prerelease
54 changes: 36 additions & 18 deletions scripts/move_packages.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,9 @@ const (
// 2. name (grafana-oss | grafana-enterprise)
cdnFormat = "artifacts/static-assets/%[2]s/%[1]s/public"

// 1: ersion
storybookFormat = "artifacts/storybook/%[1]s"

// 1: version
// 2: package name (@grafana-ui-10.0.0.tgz)
npmFormat = "artifacts/npm/%[1]s/npm-artifacts/%[2]s"
Expand Down Expand Up @@ -325,6 +328,17 @@ func CDNHandler(name string) []string {
return names
}

func StorybookHandler(name string) []string {
n := filepath.Base(strings.ReplaceAll(name, "/storybook", ".tar.gz")) // Surprisingly still works even with 'gs://' urls
opts := pipelines.TarOptsFromFileName(n)

names := []string{
fmt.Sprintf(storybookFormat, strings.TrimPrefix(opts.Version, "v")),
}

return names
}

// A hopefully temporary script that prints the gsutil commands that will move these artifacts into the location where they were expected previously.
// Just pipe this into bash or exec or whatever to do the actual copying.
// Run without redirecting stdout to verify the operations.
Expand Down Expand Up @@ -372,26 +386,30 @@ func main() {
}
handler := Handlers[ext]
if ext == "" {
destinations := make([]string, 0)
if filepath.Base(name) == "public" {
destinations := CDNHandler(name)
for _, v := range destinations {
dir := filepath.Join(prefix, filepath.Dir(v))
v := filepath.Join(prefix, v)

log.Println("Creating dir", dir)
if err := os.MkdirAll(dir, 0700); err != nil {
panic(err)
}
log.Println("Copying", name, "to", v)
//nolint:gosec
cmd := exec.Command("cp", "-r", strings.TrimPrefix(name, "file://"), v)
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
if err := cmd.Run(); err != nil {
panic(err)
}
//container = container.WithExec([]string{"gcloud", "storage", "cp", "-r", name, v})
destinations = CDNHandler(name)
}
if filepath.Base(name) == "storybook" {
destinations = StorybookHandler(name)
}
for _, v := range destinations {
dir := filepath.Join(prefix, filepath.Dir(v))
v := filepath.Join(prefix, v)

log.Println("Creating dir", dir)
if err := os.MkdirAll(dir, 0700); err != nil {
panic(err)
}
log.Println("Copying", name, "to", v)
//nolint:gosec
cmd := exec.Command("cp", "-r", strings.TrimPrefix(name, "file://"), v)
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
if err := cmd.Run(); err != nil {
panic(err)
}
//container = container.WithExec([]string{"gcloud", "storage", "cp", "-r", name, v})
}
continue
}
Expand Down
50 changes: 50 additions & 0 deletions scripts/move_packages_storybook_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
package main

import (
"sort"
"testing"
)

var storybookMapping = []m{
{
input: "gs://bucket/tag/grafana_v1.2.3_102_linux_amd64/storybook",
output: []string{
"artifacts/static-assets/grafana-oss/1.2.3/storybook",
"artifacts/static-assets/grafana/1.2.3/storybook",
},
},
{
input: "gs://bucket/tag/grafana-enterprise_v1.2.3_102_linux_amd64/storybook",
output: []string{
"artifacts/static-assets/grafana-enterprise/1.2.3/storybook",
},
},
{
input: "gs://bucket/tag/grafana-pro_v1.2.3_102_linux_amd64/storybook",
output: []string{
"artifacts/static-assets/grafana-pro/1.2.3/storybook",
},
},
}

func TestMoveStorybook(t *testing.T) {
for _, v := range storybookMapping {
out := StorybookHandler(v.input)

if len(out) != len(v.output) {
t.Errorf("expected %d in output but received %d\nexpected: %v\nreceived: %v", len(v.output), len(out), v.output, out)
continue
}
sort.Strings(out)
exp := v.output
sort.Strings(exp)

for i := range out {
got := out[i]
expect := exp[i]
if expect != got {
t.Errorf("\nExpected %s\nReceived %s", expect, got)
}
}
}
}
Loading