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

Automate releasing embedding SDK #42516

Merged
merged 47 commits into from
May 16, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
47 commits
Select commit Hold shift + click to select a range
47b59eb
WIP some workflows
WiNloSt May 10, 2024
b54a881
Merge branch 'master' into 42498-automate-sdk-release
WiNloSt May 13, 2024
453e1bf
Add reminder todo comment
WiNloSt May 13, 2024
97c06f7
Complete the workflow
WiNloSt May 13, 2024
c038d2e
Fix YAML syntax error
WiNloSt May 13, 2024
7997bc5
Trigger the workflow
WiNloSt May 13, 2024
97bd6ba
Fix resuable workflow
WiNloSt May 13, 2024
045964e
Fix uberjar workflow
WiNloSt May 13, 2024
273d6f7
Add missing steps before testing
WiNloSt May 13, 2024
920cc53
Pass recrets to resuable workflow, so it could run
WiNloSt May 13, 2024
7642849
Fix sdk artifact location
WiNloSt May 13, 2024
1bbd1bd
Remove unneeded output
WiNloSt May 13, 2024
8930d72
fetch tags, so it doesn't fail on push
WiNloSt May 13, 2024
d3c3fd8
Only running EE uberjar in SDK workflow
WiNloSt May 13, 2024
6f75cdd
Fix incorrect syntax
WiNloSt May 13, 2024
2b014db
Shuffle workflow so it failed fast
WiNloSt May 13, 2024
584de89
Fix syntax error
WiNloSt May 13, 2024
7ec3903
Attempt to bulid only EE jar
WiNloSt May 13, 2024
efdef6f
Fix the error handling step
WiNloSt May 13, 2024
4a0b355
Merge branch 'master' into 42498-automate-sdk-release
WiNloSt May 14, 2024
d0c32e0
Fix failing to upload to s3
WiNloSt May 14, 2024
a6d4306
Fix create a PR step
WiNloSt May 14, 2024
581c53d
Fix the last temporary command, so the build looks green
WiNloSt May 14, 2024
7ed56f8
Remove hack to trigger the workflow
WiNloSt May 14, 2024
91fbea7
Remove completed todo comment
WiNloSt May 14, 2024
27bbf85
Clean up S3 step
WiNloSt May 14, 2024
2037edd
Merge branch 'master' into 42498-automate-sdk-release
WiNloSt May 15, 2024
d39e5f0
Add todo comment
WiNloSt May 15, 2024
31989fd
Upload correct docker image name
WiNloSt May 15, 2024
9876036
Bump the package version before building SDK
WiNloSt May 15, 2024
827154c
Fix uploading the correct Metabase dev container name
WiNloSt May 15, 2024
8f6d3ab
Fix one too many double quote
WiNloSt May 15, 2024
59a2ded
Push the correct docker image
WiNloSt May 15, 2024
032e512
Fix PR creation step
WiNloSt May 15, 2024
0d29c66
Dry run publishing SDK
WiNloSt May 15, 2024
1b52957
Merge branch 'master' into 42498-automate-sdk-release
WiNloSt May 16, 2024
4f03563
Use a separate uberjar workflow for SDK
WiNloSt May 16, 2024
ec77bbe
Remove a bunch of unused steps
WiNloSt May 16, 2024
0639cfb
Update variable names, step names
WiNloSt May 16, 2024
0e3b35f
Improve tag error message
WiNloSt May 16, 2024
46c0ee9
Correct m2-cache-key to be unique
WiNloSt May 16, 2024
5df46dd
Fix the push tag failure step to only run when failed to push tag
WiNloSt May 16, 2024
025d62c
Fix changed artifact name
WiNloSt May 16, 2024
87b22fc
Improve env name for clarity
WiNloSt May 16, 2024
a4fbb2d
Fix extra trailing empty line
WiNloSt May 16, 2024
f97ed74
Remove conditions from running certian steps
WiNloSt May 16, 2024
81e4907
Removing npm publish dry-run
WiNloSt May 16, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
193 changes: 193 additions & 0 deletions .github/workflows/release-embedding-sdk.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,193 @@
name: Release Metabase Embedding SDK for React

on:
workflow_dispatch:
heypoom marked this conversation as resolved.
Show resolved Hide resolved
inputs:
# TODO: Add a version validation, so the workflow won't fail when publishing to npm
sdk_version:
description: 'SDK version (e.g. 0.1.3)'
WiNloSt marked this conversation as resolved.
Show resolved Hide resolved
type: string
required: true
git_ref:
description: 'Valid git reference e.g. branches, tags, hashes'
type: string
required: true

concurrency:
# We want to ensure only one job is running at a time because
# there could be a conflict when updating the readme file.
group: ${{ github.workflow }}
cancel-in-progress: true
Comment on lines +16 to +20
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👌


jobs:
git-tag:
runs-on: ubuntu-22.04
timeout-minutes: 20
env:
tag: embedding-sdk-${{ inputs.sdk_version }}
steps:
- name: Check out the code using the provided ref
uses: actions/checkout@v4
with:
ref: ${{ inputs.git_ref }}

- name: Setup git user
run: |
git config --global user.email "metabase-bot@metabase.com"
git config --global user.name "Metabase bot"

- name: Create a new git tag
run: |
git tag ${{ env.tag }}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit:
Do we intentionally provide only a lightweight tag here?

cc @WiNloSt

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We don't have any information we want to include in the annotated tag other than repeating the version in the tag name itself, so it should be safe to use a lightweight tag here.


- name: Push the new tag
id : push-tag
run: |
git push origin ${{ env.tag }}
- if: ${{ failure() && steps.push-tag.outcome == 'failure' }}
run: echo "Tag '${{ env.tag }}' already exists. If you expect to run this workflow with the same tag, please remove the tag first and rerun this workflow again."

test:
needs: git-tag
runs-on: ubuntu-22.04
timeout-minutes: 20
steps:
- name: Check out the code using the provided ref
uses: actions/checkout@v4
with:
ref: ${{ inputs.git_ref }}

- name: Prepare front-end environment
uses: ./.github/actions/prepare-frontend

- name: Prepare back-end environment
uses: ./.github/actions/prepare-backend
with:
m2-cache-key: "release-sdk"

- name: Run unit tests
run: yarn embedding-sdk:test-unit

build-sdk:
WiNloSt marked this conversation as resolved.
Show resolved Hide resolved
needs: test
runs-on: ubuntu-22.04
timeout-minutes: 20
steps:
- name: Check out the code using the provided ref
uses: actions/checkout@v4
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: wondering if we can cache the checkout here with https://github.com/actions/cache since we checked out twice. let's worry about this later.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

with:
ref: ${{ inputs.git_ref }}

- name: Prepare front-end environment
uses: ./.github/actions/prepare-frontend

- name: Prepare back-end environment
uses: ./.github/actions/prepare-backend
with:
m2-cache-key: "release-sdk"

- name: Bump published npm package version
run: |
sed -i -E 's/("version": ").*"/\1${{ inputs.sdk_version }}"/' enterprise/frontend/src/embedding-sdk/package.template.json

- name: Build SDK bundle
run: yarn run build-embedding-sdk

- name: Generate SDK package.json in the build directory
run: yarn run embedding-sdk:generate-package

- name: Upload built SDK package as artifact
uses: actions/upload-artifact@v4
with:
name: metabase-sdk
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

simplify the name since it seems to be local to each workflow run.

From this doc., the name is default to artifact, so we probably don't need to make it super unique with workflow ID, commit hash or whatnot.

   # Name of the artifact to upload.
   # Optional. Default is 'artifact'
   name:

path: ./resources/embedding-sdk

build-jar:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just for me to understand - why do we need to build and upload jar?
I would assume - to make sure clients use specific metabase version that we tested with SDK, right?

Copy link
Member Author

@WiNloSt WiNloSt May 15, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, for now, we say the jar built with the same commit as the SDK would be compatible with the SDK, this could change when we start shipping Metabase v0.50. I think we mentioned we'll then use the jar from the release branch, but I'm not totally 100% sure what commit we'll use in that case.

For more context:

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If this has the chance to be only a temporary solution, I wouldn't alter the existing uberjar.yml workflow (it's heavy already).

WDYT about creating a temporary uberjar-sdk.yml instead?
The benefit is that you can create it either as a workflow or as a composite action even.

I feel 90% confident that we should not modify the existing uberjar workflow for now.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed in 4f03563

needs: test
uses: ./.github/workflows/uberjar-sdk.yml
with:
git_ref: ${{ inputs.git_ref }}
image_name: embedding-sdk-${{ inputs.sdk_version }}
secrets: inherit
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is needed, otherwise uberjar workflow won't be able to access secrets.*. Alternatively we could specify which secrets we want to pass to it, but we can just use inherit which passes all secrets.


upload-jar:
needs: build-jar
runs-on: ubuntu-22.04
timeout-minutes: 20
steps:
- uses: actions/download-artifact@v4
name: Retrieve uberjar artifact
with:
name: metabase-ee-uberjar

- name: Configure AWS credentials
uses: aws-actions/configure-aws-credentials@v4
with:
aws-access-key-id: ${{ secrets.AWS_S3_RELEASE_ACCESS_KEY_ID }}
aws-secret-access-key: ${{ secrets.AWS_S3_RELEASE_SECRET_ACCESS_KEY }}
aws-region: ${{ vars.AWS_REGION }}

- name: Upload uberjar to S3
env:
BUCKET: ${{ vars.AWS_S3_DOWNLOADS_BUCKET }}
BUCKET_PATH: sdk/v${{ inputs.sdk_version }}/metabase.jar
FILE: ./target/uberjar/metabase.jar
shell: bash
run: |
aws s3 cp $FILE s3://$BUCKET/$BUCKET_PATH


publish-npm:
needs: [build-sdk, upload-jar]
runs-on: ubuntu-22.04
timeout-minutes: 20
steps:
- name: Check out master to prepare for a SDK version bump PR
uses: actions/checkout@v4
with:
# when we created version update PR, it would only have diff from 2 files SDK readme and SDK package.json template
ref: master
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We checkout this last step with master so the created version update PR would only have diff from these 2 files:

  1. SDK readme
  2. SDK package.json template

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This would be useful to have as an actual comment in the code.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed in 0639cfb


- name: Setup git user
run: |
git config --global user.email "metabase-bot@metabase.com"
git config --global user.name "Metabase bot"

- name: Update readme
run: |
sed -i -E 's|(embedding-sdk-)[0-9.]+|\1${{ inputs.sdk_version }}|' enterprise/frontend/src/embedding-sdk/README.md
sed -i -E 's|(http://downloads.metabase.com/sdk/v)[0-9.]+|\1${{ inputs.sdk_version }}|' enterprise/frontend/src/embedding-sdk/README.md
Comment on lines +158 to +159
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Verified locally that regex here works.

I wonder if we should run this as part of the README copy function in generate-sdk-package-files though. We currently run copyFileToOutput("frontend/src/embedding-sdk/README.md", "README.md");, so we could as easily modify the content there. I guess we do this because we want to bump the version without relying on the script?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good question. I just think of this step as a separate one from generating the package.json which generate-sdk-package-files.js handles.

However, generate-sdk-package-files already accepts an argument as a commit hash, I'm not very familiar with writing CLI, so we could accept named argument instead so I could do --version=<new_version> without having to pass the commit hash.

This could surely become an improvement later on.


- name: Bump published npm package version
run: |
sed -i -E 's/("version": ").*"/\1${{ inputs.sdk_version }}"/' enterprise/frontend/src/embedding-sdk/package.template.json

- uses: actions/create-github-app-token@v1
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This uses GitHub's own https://github.com/actions/create-github-app-token action rather than a 3rd party one we used in other workflow e.g.

- uses: tibdex/github-app-token@v2.1.0
id: generate-token
with:
app_id: ${{ secrets.METABASE_BOT_APP_ID }}
private_key: ${{ secrets.METABASE_BOT_APP_PRIVATE_KEY }}

id: app-token
with:
app-id: ${{ secrets.METABASE_BOT_APP_ID }}
private-key: ${{ secrets.METABASE_BOT_APP_PRIVATE_KEY }}

- name: Create a PR updating readme + published version
WiNloSt marked this conversation as resolved.
Show resolved Hide resolved
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just to be sure, this PR that gets created will update the versions, but the package with the specified version will already be published right?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yeah, but to be specific the package would be published in the last step within this job. The PR would have been created at this step and we will have to manually merge the PR.

Realistically, by the time we look at the PR, the SDK package would already likely be published.

run: |
git checkout -b update-sdk-version-${{ inputs.sdk_version }}
git commit -a -m 'Update Readme version references and published npm version to ${{ inputs.sdk_version }}'
git push origin HEAD
gh pr create --base master\
--assignee "${GITHUB_ACTOR}"\
--title "Update SDK version to ${{ inputs.sdk_version }}"\
--body "Update Readme version references and published npm package version to ${{ inputs.sdk_version }}"
env:
GH_TOKEN: ${{ steps.app-token.outputs.token }}

- name: Retrieve build SDK package artifact
uses: actions/download-artifact@v4
with:
name: metabase-sdk
path: sdk

- name: Publish to NPM
run: |
cd sdk
echo //registry.npmjs.org/:_authToken=${{ secrets.NPM_RELEASE_TOKEN }} > .npmrc
npm publish
157 changes: 157 additions & 0 deletions .github/workflows/uberjar-sdk.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,157 @@
name: Build + Docker Uberjar for SDK
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is copied over from uberjar.yml and

  1. strip out unused parts e.g. steps that only run on master
  2. all triggers outside workflow_call
  3. Simplify the artifact name to metabase-ee-uberjar
  4. accepts a new input image_name previously the image name is determined from a branch name that triggers the workflow, but we want to use the tag name (which created within the workflow) instead.


on:
# This workflow will be called from "release-embedding-sdk.yml"
workflow_call:
inputs:
git_ref:
description: 'Valid git reference e.g. branches, tags, hashes'
type: string
required: true
image_name:
description: Docker image used to upload to Dockerhub
type: string
required: true

jobs:
build:
name: Build MB ${{ matrix.edition }}
runs-on: ubuntu-22.04
timeout-minutes: 40
strategy:
matrix:
edition: [ee]
env:
MB_EDITION: ${{ matrix.edition }}
INTERACTIVE: false
steps:
- name: Check out the code
uses: actions/checkout@v4
with:
ref: ${{ inputs.git_ref }}
- name: Prepare front-end environment
uses: ./.github/actions/prepare-frontend
- name: Prepare back-end environment
uses: ./.github/actions/prepare-backend
with:
m2-cache-key: uberjar
- name: Build
run: ./bin/build.sh
- name: Prepare uberjar artifact
uses: ./.github/actions/prepare-uberjar-artifact
with:
name: metabase-ee-uberjar

check_jar_health:
runs-on: ubuntu-22.04
name: Is ${{ matrix.edition }} (java ${{ matrix.java-version }}) healthy?
needs: build
timeout-minutes: 10
strategy:
matrix:
edition: [ee]
java-version: [11, 17]
steps:
- name: Prepare JRE (Java Run-time Environment)
uses: actions/setup-java@v4
with:
java-package: jre
java-version: ${{ matrix.java-version }}
distribution: 'temurin'
- run: java -version
- uses: actions/download-artifact@v4
name: Retrieve uberjar artifact
with:
name: metabase-ee-uberjar
- name: Launch uberjar
run: java -jar ./target/uberjar/metabase.jar &
- name: Wait for Metabase to start
run: while ! curl 'http://localhost:3000/api/health' | grep '{"status":"ok"}'; do sleep 1; done

containerize_test_and_push_container:
runs-on: ubuntu-22.04
name: Containerize ${{ matrix.edition }}
needs: check_jar_health
strategy:
matrix:
edition: [ee]
services:
registry:
image: registry:2
ports:
- 5000:5000
steps:
- name: Extract and clean branch name
shell: bash
run: echo "branch=$(echo $GITHUB_REF_NAME | sed 's/[^-._a-zA-Z0-9]/-/g')" >> $GITHUB_OUTPUT
id: extract_branch

- name: Set image name to env
run: echo "image_name=${{ inputs.image_name || steps.extract_branch.outputs.branch }}" >> "$GITHUB_ENV"

- name: Verify the intended tag of the container image
run: echo "Container image will be tagged as ${{ env.image_name }}-${{ matrix.edition }}"

- name: Check out the code (Dockerfile needed)
uses: actions/checkout@v4
with:
ref: ${{ inputs.git_ref }}

- name: Download uploaded artifacts to insert into container
uses: actions/download-artifact@v4
with:
name: metabase-ee-uberjar
path: bin/docker/

- name: Move the ${{ matrix.edition }} uberjar to the context dir
run: mv bin/docker/target/uberjar/metabase.jar bin/docker/.

- name: Set up Docker Buildx
id: buildx
uses: docker/setup-buildx-action@v2.5.0
with:
driver-opts: network=host

- name: Build ${{ matrix.edition }} container
uses: docker/build-push-action@v3
with:
context: bin/docker/.
platforms: linux/amd64
network: host
tags: localhost:5000/metabase-dev:${{ env.image_name }}-${{ matrix.edition }}
no-cache: true
push: true

- name: Launch ${{ matrix.edition }} container
run: docker run --rm -dp 3000:3000 localhost:5000/metabase-dev:${{ env.image_name }}-${{ matrix.edition }}
timeout-minutes: 5

- name: Is Docker running?
run: docker ps

- name: Wait for Metabase to start and reach 100% health
run: while ! curl -s 'http://localhost:3000/api/health' | grep '{"status":"ok"}'; do sleep 1; done
timeout-minutes: 3

- name: Login to Docker Hub
uses: docker/login-action@v2
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}

- name: Retag and push images
run: docker tag localhost:5000/metabase-dev:${{ env.image_name }}-ee ${{ github.repository_owner }}/metabase-dev:${{ env.image_name }} && docker push ${{ github.repository_owner }}/metabase-dev:${{ env.image_name }}

- name: Run Trivy vulnerability scanner
uses: aquasecurity/trivy-action@master
env:
TRIVY_OFFLINE_SCAN: true
with:
image-ref: docker.io/${{ github.repository_owner }}/metabase-dev:${{ env.image_name }}
format: sarif
output: trivy-results.sarif

- name: Upload Trivy scan results to GitHub Security tab
uses: github/codeql-action/upload-sarif@v2
with:
sarif_file: 'trivy-results.sarif'
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -355,6 +355,7 @@
"embedding-sdk:fixup-types-imports": "node ./bin/embedding-sdk/fixup-types-after-compilation.js",
"embedding-sdk:generate-package": "node ./bin/embedding-sdk/generate-sdk-package-files.js",
"embedding-sdk:publish": "cd ./resources/embedding-sdk && npm publish",
"embedding-sdk:test-unit": "yarn test-unit enterprise/frontend/src/embedding-sdk/",
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just a simple sanity check for SDK, we have more tests when running the uberjar workflow already.

"eslint-fix": "yarn lint-eslint --fix",
"generate-cypress-html-report": "mochawesome-merge cypress/reports/mochareports/*.json > cypress/reports/cypress-test-report.json && marge cypress/reports/cypress-test-report.json -o cypress/reports/mochareports --inline",
"lint": "yarn lint-eslint && yarn lint-prettier && yarn lint-docs-links && yarn lint-yaml && yarn type-check",
Expand Down