diff --git a/.github/workflows/docker-images.yaml b/.github/workflows/docker-images.yaml index 2544a659..dd1e4ce6 100644 --- a/.github/workflows/docker-images.yaml +++ b/.github/workflows/docker-images.yaml @@ -8,14 +8,23 @@ on: # rebuild any PRs and main branch changes jobs: build-images: + strategy: + matrix: + include: + - buildArgs: --repo-ref master + runTag: go-master + + # Latest release at the time this was written + # TODO(bergundy): Find some way to automatically upgrade to "latest" + - buildArgs: --version v1.16 + runTag: go-1.16.0 + runs-on: ubuntu-latest env: - # TODO(bergundy): get a permanent cloud namespace - TEMPORAL_CLOUD_ADDRESS: roey.temporal-dev.tmprl.cloud:7233 - TEMPORAL_CLOUD_NAMESPACE: roey.temporal-dev - # For some reason this needs to be set globally ¯\_(ツ)_/¯ - TEMPORAL_CLIENT_CERT: ${{ secrets.TEMPORAL_CLIENT_CERT }} - TEMPORAL_CLIENT_KEY: ${{ secrets.TEMPORAL_CLIENT_KEY }} + TEMPORAL_CLOUD_ADDRESS: sdk-ci.a2dd6.tmprl.cloud:7233 + TEMPORAL_CLOUD_NAMESPACE: sdk-ci.a2dd6 + REPO_URL: ${{ github.event.pull_request.head.repo.html_url }} + steps: - name: Print build information run: 'echo head_ref: ${{ github.head_ref }}, ref: ${{ github.ref }}, os: ${{ matrix.os }}' @@ -26,38 +35,30 @@ jobs: - name: Lint go docker image run: docker run --rm -i hadolint/hadolint < dockerfiles/go.Dockerfile - # Downlad the certs to be mounted as a volume in the running container - - run: mkdir /tmp/temporal-certs - - run: echo "$TEMPORAL_CLIENT_CERT" > /tmp/temporal-certs/client.pem - - run: echo "$TEMPORAL_CLIENT_KEY" > /tmp/temporal-certs/client.key - - # Just see if it runs for now, not publishing yet - # TODO(bergundy): run these in parallel - - - name: Build go master image - run: go run . build-image --lang go --repo-ref master - - name: Run go master image against Temporalite - run: docker run --rm -i -v /tmp/temporal-certs:/certs sdk-features:go-master - - name: Run go master image against Cloud + # Download the certs to be mounted as a volume in the running container + - name: Download certs to temporary directory run: | - docker run --rm -i -v /tmp/temporal-certs:/certs sdk-features:go-master \ - --server $TEMPORAL_CLOUD_ADDRESS \ - --namespace $TEMPORAL_CLOUD_NAMESPACE \ - --client-cert-path /certs/client.pem \ - --client-key-path /certs/client.key + mkdir /tmp/temporal-certs && + echo "$TEMPORAL_CLIENT_CERT" > /tmp/temporal-certs/client.pem && + echo "$TEMPORAL_CLIENT_KEY" > /tmp/temporal-certs/client.key && + wc /tmp/temporal-certs/client.pem /tmp/temporal-certs/client.key + env: + TEMPORAL_CLIENT_CERT: ${{ secrets.TEMPORAL_CLIENT_CERT }} + TEMPORAL_CLIENT_KEY: ${{ secrets.TEMPORAL_CLIENT_KEY }} - # Latest release at the time this was written - # TODO(bergundy): Find some way to automatically upgrade to "latest" - - name: Build go 1.16 image - run: go run . build-image --lang go --version v1.16 - - name: Run go 1.16 image against Temporalite - run: docker run --rm -i -v /tmp/temporal-certs:/certs sdk-features:go-1.16.0 - - name: Run go 1.16 image against Cloud + - name: Build go master image + run: go run . build-image --lang go ${{ matrix.buildArgs }} + - name: Test with Temporalite + run: docker run --rm -i -v /tmp/temporal-certs:/certs sdk-features:${{ matrix.runTag }} + - name: Test with Cloud run: | - docker run --rm -i -v /tmp/temporal-certs:/certs sdk-features:go-1.16.0 \ + docker run --rm -i -v /tmp/temporal-certs:/certs sdk-features:${{ matrix.runTag }} --server $TEMPORAL_CLOUD_ADDRESS \ --namespace $TEMPORAL_CLOUD_NAMESPACE \ --client-cert-path /certs/client.pem \ --client-key-path /certs/client.key + # Only supported in non-fork runs + if: ${{ github.event.pull_request.head.repo.full_name == '' || github.event.pull_request.head.repo.full_name == 'temporalio/sdk-features' }} - # TODO(bergundy): create a docker push step + # TODO(bergundy): create a docker push step (only run under certain conditions - like manual trigger or main + # branch trigger) diff --git a/cmd/build_image.go b/cmd/build_image.go index de3dcfaf..3470780a 100644 --- a/cmd/build_image.go +++ b/cmd/build_image.go @@ -7,6 +7,7 @@ import ( "os/exec" "path/filepath" "strings" + "time" "github.com/urfave/cli/v2" "go.temporal.io/server/common/log" @@ -155,8 +156,8 @@ func (i *ImageBuilder) buildFromRepo(ctx context.Context) error { return i.dockerBuild(ctx, buildConfig{ tags: tags, labels: map[string]string{ - "SDK_REPO_URL": i.config.RepoURL, - "SDK_REPO_REF": repoRef, + "io.temporal.sdk.repo-url": i.config.RepoURL, + "io.temporal.sdk.repo-ref": repoRef, }, buildArgs: map[string]string{"SDK_VERSION": repoDir, "REPO_DIR_OR_PLACEHOLDER": repoDir}, }) @@ -186,7 +187,9 @@ func (i *ImageBuilder) buildFromVersion(ctx context.Context) error { return i.dockerBuild(ctx, buildConfig{ tags: tags, buildArgs: map[string]string{"SDK_VERSION": version, "REPO_DIR_OR_PLACEHOLDER": "main.go"}, - labels: map[string]string{"SDK_VERSION": version}, + labels: map[string]string{ + "io.temporal.sdk.version": version, + }, }) } @@ -213,8 +216,6 @@ func (i *ImageBuilder) dockerBuild(ctx context.Context, config buildConfig) erro "--pull", "--file", fmt.Sprintf("dockerfiles/%s.Dockerfile", i.config.Lang), - "--label", - fmt.Sprintf("SDK_FEATURES_REF=%s", gitRef), } if i.config.Platform != "" { args = append(args, "--platform", i.config.Platform) @@ -222,6 +223,36 @@ func (i *ImageBuilder) dockerBuild(ctx context.Context, config buildConfig) erro for _, tag := range config.tags { args = append(args, "--tag", fmt.Sprintf("%s:%s", imageName, tag)) } + + // TODO(bergundy): Would be nicer to print plain text instead of markdown but this good enough for now + usage, err := (&cli.App{ + Name: "sdk-features", + Usage: "run a test or set of sdk-features tests", + Flags: (&RunConfig{}).dockerRunFlags(), + }).ToMarkdown() + if err != nil { + return fmt.Errorf("failed to generate usage string: %s", err) + } + repoURL := os.Getenv("REPO_URL") + if repoURL == "" { + repoURL = "https://github.com/temporalio/sdk-features" + } + + defaultLabels := map[string]string{ + "org.opencontainers.image.created": time.Now().UTC().Format(time.RFC3339), + "org.opencontainers.image.source": repoURL, + "org.opencontainers.image.vendor": "Temporal Technologies Inc.", + "org.opencontainers.image.authors": "Temporal SDK team ", + "org.opencontainers.image.licenses": "MIT", + "org.opencontainers.image.revision": gitRef, + "org.opencontainers.image.title": fmt.Sprintf("SDK features compliance test suite for %s", i.config.Lang), + "org.opencontainers.image.documentation": usage, + "io.temporal.sdk.name": i.config.Lang, + } + for k, v := range defaultLabels { + args = append(args, "--label", fmt.Sprintf("%s=%s", k, v)) + } + for k, v := range config.labels { args = append(args, "--label", fmt.Sprintf("%s=%s", k, v)) } diff --git a/cmd/run.go b/cmd/run.go index e80c4dde..b562ed76 100644 --- a/cmd/run.go +++ b/cmd/run.go @@ -48,25 +48,9 @@ type RunConfig struct { RetainTempDir bool } -func (r *RunConfig) flags() []cli.Flag { +// dockerRunFlags are a subset of flags that apply when running in a docker container +func (r *RunConfig) dockerRunFlags() []cli.Flag { return []cli.Flag{ - langFlag(&r.Lang), - &cli.StringFlag{ - Name: "version", - Usage: "SDK language version to run. Most languages support versions as paths. " + - "Version cannot be present if prepared directory is.", - Destination: &r.Version, - }, - &cli.BoolFlag{ - Name: "generate-history", - Usage: "Generate the history of the features that are run (overwrites any existing history)", - Destination: &r.GenerateHistory, - }, - &cli.BoolFlag{ - Name: "no-history-check", - Usage: "Do not verify history matches", - Destination: &r.DisableHistoryCheck, - }, &cli.StringFlag{ Name: "server", Usage: "The host:port of the server (default is to create ephemeral in-memory server)", @@ -87,6 +71,28 @@ func (r *RunConfig) flags() []cli.Flag { Usage: "Path of TLS client key to use (optional)", Destination: &r.ClientKeyPath, }, + } +} + +func (r *RunConfig) flags() []cli.Flag { + return append([]cli.Flag{ + langFlag(&r.Lang), + &cli.StringFlag{ + Name: "version", + Usage: "SDK language version to run. Most languages support versions as paths. " + + "Version cannot be present if prepared directory is.", + Destination: &r.Version, + }, + &cli.BoolFlag{ + Name: "generate-history", + Usage: "Generate the history of the features that are run (overwrites any existing history)", + Destination: &r.GenerateHistory, + }, + &cli.BoolFlag{ + Name: "no-history-check", + Usage: "Do not verify history matches", + Destination: &r.DisableHistoryCheck, + }, &cli.BoolFlag{ Name: "retain-temp-dir", Usage: "Do not delete the temp directory after the run", @@ -97,7 +103,7 @@ func (r *RunConfig) flags() []cli.Flag { Usage: "Relative directory already prepared. Cannot include version with this.", Destination: &r.Dir, }, - } + }, r.dockerRunFlags()...) } // Runner can run features.