From f2ecb444dac93fa558080843e6e7618baa32f8e6 Mon Sep 17 00:00:00 2001 From: Pawel Kosiec Date: Fri, 10 Apr 2026 09:29:00 +0200 Subject: [PATCH 1/3] refactor: rename prepare-pr-template to prepare-template-artifact Signed-off-by: Pawel Kosiec --- .github/workflows/ci.yml | 2 +- tools/{prepare-pr-template.ts => prepare-template-artifact.ts} | 0 2 files changed, 1 insertion(+), 1 deletion(-) rename tools/{prepare-pr-template.ts => prepare-template-artifact.ts} (100%) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 77bae315..f6c735ba 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -162,7 +162,7 @@ jobs: run: pnpm pack:sdk - name: Prepare template artifact - run: pnpm exec tsx tools/prepare-pr-template.ts "${{ steps.version.outputs.version }}" + run: pnpm exec tsx tools/prepare-template-artifact.ts "${{ steps.version.outputs.version }}" - name: Install template dependencies working-directory: pr-template diff --git a/tools/prepare-pr-template.ts b/tools/prepare-template-artifact.ts similarity index 100% rename from tools/prepare-pr-template.ts rename to tools/prepare-template-artifact.ts From e5f3723dcfc80516ec9cb6224dbc8f7f5386b59f Mon Sep 17 00:00:00 2001 From: Pawel Kosiec Date: Fri, 10 Apr 2026 09:30:22 +0200 Subject: [PATCH 2/3] feat: add template artifact job to prepare-release pipeline - Add --version, --tarball-dir, and --output-dir flags to prepare-template-artifact.ts for reuse across CI and release - Add template-artifact job to prepare-release workflow that downloads release tarballs and produces a template zip artifact - Update install-appkit-tarball skill with --template mode for scaffolding new apps from CI template artifacts - Temporarily trigger prepare-release on this branch for testing Signed-off-by: Pawel Kosiec --- .claude/skills/install-appkit-artifact.md | 194 ++++++++++++++++++++++ .claude/skills/install-appkit-tarball.md | 126 -------------- .github/workflows/ci.yml | 2 +- .github/workflows/prepare-release.yml | 57 +++++++ docs/static/appkit-ui/styles.gen.css | 28 +++- tools/prepare-template-artifact.ts | 58 +++++-- 6 files changed, 317 insertions(+), 148 deletions(-) create mode 100644 .claude/skills/install-appkit-artifact.md delete mode 100644 .claude/skills/install-appkit-tarball.md diff --git a/.claude/skills/install-appkit-artifact.md b/.claude/skills/install-appkit-artifact.md new file mode 100644 index 00000000..8f29df11 --- /dev/null +++ b/.claude/skills/install-appkit-artifact.md @@ -0,0 +1,194 @@ +--- +name: install-appkit-artifact +description: "Install appkit CI artifacts into a project or scaffold a new app from a CI template artifact. Downloads from the prepare-release CI workflow (default) or builds locally. Use when testing appkit release candidates, installing pre-release appkit, scaffolding a new app from template, or when user says 'install appkit tarball', 'install appkit artifact', 'install local appkit', 'use local appkit', 'link appkit tgz', 'install appkit from CI', 'create app from template', 'init app from CI'." +user-invocable: true +allowed-tools: Read, Edit, Bash, Glob +--- + +# Install AppKit Artifact + +Installs AppKit tgz packages into a project from either the CI prepare-release workflow or a local build. Can also scaffold a new app from a CI template artifact. + +## Arguments + +Parse the user's input to determine mode and options: + +- **No args** → CI mode, latest successful prepare-release run, install in CWD +- **GitHub Actions URL** (contains `actions/runs/`) → CI mode, extract run ID from URL +- **Numeric run ID** → CI mode, that specific run +- **`--local `** → Local build mode from the given appkit repo path +- **`--dir `** (combinable with any above) → Override install target directory (default: CWD) +- **`--template`** → Template mode: scaffold a new app from the CI template artifact instead of installing tarballs into an existing project + +## Workflow + +Follow these steps exactly: + +### Step 1: Determine mode + +If `--template` was provided, go to **Template Mode** below. Otherwise continue with **Install Mode**. + +--- + +## Install Mode + +### Step 2: Determine target directory + +If `--dir` was provided, use that path. Otherwise use the current working directory. +Verify `package.json` exists in the target directory. + +### Step 3: Get tgz files + +#### Option A: CI mode (default) + +**3a. Find the workflow run:** + +If no run ID was provided, get the latest successful run: + +```bash +gh run list --repo databricks/appkit --workflow prepare-release.yml --status success --limit 1 --json databaseId,number +``` + +If a GitHub Actions URL was provided, extract the run ID from it (the number after `/runs/`). + +**3b. Find the artifact name:** + +```bash +gh api "repos/databricks/appkit/actions/runs/{RUN_ID}/artifacts" --jq '.artifacts[] | select(.name | test("^appkit-release-[0-9]")) | .name' +``` + +**3c. Download the artifact:** + +```bash +gh run download {RUN_ID} --repo databricks/appkit --name "{ARTIFACT_NAME}" --dir /tmp/appkit-release-artifacts +``` + +**3d. Verify checksums:** + +```bash +cd /tmp/appkit-release-artifacts && shasum -a 256 -c SHA256SUMS +``` + +Note: Use `shasum -a 256` (macOS) not `sha256sum` (Linux). + +**3e. Print the downloaded version:** + +```bash +cat /tmp/appkit-release-artifacts/VERSION +``` + +The tgz files are now at `/tmp/appkit-release-artifacts/databricks-appkit-*.tgz` and `/tmp/appkit-release-artifacts/databricks-appkit-ui-*.tgz`. + +#### Option B: Local build mode + +**3a. Build tgz files:** + +```bash +cd {LOCAL_APPKIT_PATH} && pnpm pack:sdk +``` + +**3b. Find the tgz files:** + +Glob for `*.tgz` in: +- `{LOCAL_APPKIT_PATH}/packages/appkit/tmp/*.tgz` +- `{LOCAL_APPKIT_PATH}/packages/appkit-ui/tmp/*.tgz` + +There should be exactly one tgz in each directory. + +### Step 4: Copy tgz files to target directory + +Copy both `databricks-appkit-*.tgz` and `databricks-appkit-ui-*.tgz` to the target directory. + +### Step 5: Update package.json + +Read `package.json` in the target directory. Edit `@databricks/appkit` and `@databricks/appkit-ui` dependency values to use `file:./` prefix pointing to the tgz filenames. + +For example, if the tgz file is `databricks-appkit-0.22.0.tgz`: +```json +"@databricks/appkit": "file:./databricks-appkit-0.22.0.tgz" +``` + +Same pattern for `@databricks/appkit-ui`. + +### Step 6: Install dependencies + +Run in the target directory: + +```bash +npm install --force ./databricks-appkit-{VERSION}.tgz ./databricks-appkit-ui-{VERSION}.tgz +``` + +### Step 7: Clean up + +If CI mode was used, remove the temp directory: + +```bash +rm -rf /tmp/appkit-release-artifacts +``` + +### Step 8: Report + +Print a summary: +- Source: CI run #{number} or local build from {path} +- Version installed +- Target directory +- Installed packages + +--- + +## Template Mode + +Scaffolds a new app by downloading the template artifact from a CI run and using `databricks apps init`. + +### Step 2: Find the workflow run + +If no run ID was provided, get the latest successful run: + +```bash +gh run list --repo databricks/appkit --workflow prepare-release.yml --status success --limit 1 --json databaseId,number +``` + +If a GitHub Actions URL or numeric run ID was provided, use that instead. + +### Step 3: Find the template artifact name + +```bash +gh api "repos/databricks/appkit/actions/runs/{RUN_ID}/artifacts" --jq '.artifacts[] | select(.name | test("^appkit-template-")) | .name' +``` + +### Step 4: Download the template artifact + +```bash +gh run download {RUN_ID} --repo databricks/appkit --name "{ARTIFACT_NAME}" --dir /tmp/appkit-template-artifact +``` + +### Step 5: Unzip the template + +```bash +mkdir -p /tmp/appkit-template && unzip -o /tmp/appkit-template-artifact/template.zip -d /tmp/appkit-template +``` + +Note: The zip is named `template.zip` for release artifacts and `pr-template.zip` for PR artifacts. Check which file exists. + +### Step 6: Hand off to the user + +**Do NOT run `databricks apps init` yourself** — it is an interactive command that prompts for app name, features, resources, etc. + +Print the following for the user to run in their terminal: + +``` +databricks apps init --template /tmp/appkit-template +``` + +Then tell them to clean up afterward: + +``` +rm -rf /tmp/appkit-template-artifact /tmp/appkit-template +``` + +### Step 7: Report + +Print a summary: +- Source: CI run #{number} +- Template extracted to `/tmp/appkit-template` +- Command to run provided above diff --git a/.claude/skills/install-appkit-tarball.md b/.claude/skills/install-appkit-tarball.md deleted file mode 100644 index a8808896..00000000 --- a/.claude/skills/install-appkit-tarball.md +++ /dev/null @@ -1,126 +0,0 @@ ---- -name: install-appkit-tarball -description: "Install appkit tgz builds into a project. Downloads from the prepare-release CI workflow (default) or builds locally. Use when testing appkit release candidates, installing pre-release appkit, or when user says 'install appkit tarball', 'install local appkit', 'use local appkit', 'link appkit tgz', 'install appkit from CI'." -user-invocable: true -allowed-tools: Read, Edit, Bash, Glob ---- - -# Install AppKit Tarball - -Installs AppKit tgz packages into a project from either the CI prepare-release workflow or a local build. - -## Arguments - -Parse the user's input to determine mode and options: - -- **No args** → CI mode, latest successful prepare-release run, install in CWD -- **GitHub Actions URL** (contains `actions/runs/`) → CI mode, extract run ID from URL -- **Numeric run ID** → CI mode, that specific run -- **`--local `** → Local build mode from the given appkit repo path -- **`--dir `** (combinable with any above) → Override install target directory (default: CWD) - -## Workflow - -Follow these steps exactly: - -### Step 1: Determine target directory - -If `--dir` was provided, use that path. Otherwise use the current working directory. -Verify `package.json` exists in the target directory. - -### Step 2: Get tgz files - -#### Option A: CI mode (default) - -**2a. Find the workflow run:** - -If no run ID was provided, get the latest successful run: - -```bash -gh run list --repo databricks/appkit --workflow prepare-release.yml --status success --limit 1 --json databaseId,number -``` - -If a GitHub Actions URL was provided, extract the run ID from it (the number after `/runs/`). - -**2b. Find the artifact name:** - -```bash -gh api "repos/databricks/appkit/actions/runs/{RUN_ID}/artifacts" --jq '.artifacts[] | select(.name | test("^appkit-release-[0-9]")) | .name' -``` - -**2c. Download the artifact:** - -```bash -gh run download {RUN_ID} --repo databricks/appkit --name "{ARTIFACT_NAME}" --dir /tmp/appkit-release-artifacts -``` - -**2d. Verify checksums:** - -```bash -cd /tmp/appkit-release-artifacts && shasum -a 256 -c SHA256SUMS -``` - -Note: Use `shasum -a 256` (macOS) not `sha256sum` (Linux). - -**2e. Print the downloaded version:** - -```bash -cat /tmp/appkit-release-artifacts/VERSION -``` - -The tgz files are now at `/tmp/appkit-release-artifacts/databricks-appkit-*.tgz` and `/tmp/appkit-release-artifacts/databricks-appkit-ui-*.tgz`. - -#### Option B: Local build mode - -**2a. Build tgz files:** - -```bash -cd {LOCAL_APPKIT_PATH} && pnpm pack:sdk -``` - -**2b. Find the tgz files:** - -Glob for `*.tgz` in: -- `{LOCAL_APPKIT_PATH}/packages/appkit/tmp/*.tgz` -- `{LOCAL_APPKIT_PATH}/packages/appkit-ui/tmp/*.tgz` - -There should be exactly one tgz in each directory. - -### Step 3: Copy tgz files to target directory - -Copy both `databricks-appkit-*.tgz` and `databricks-appkit-ui-*.tgz` to the target directory. - -### Step 4: Update package.json - -Read `package.json` in the target directory. Edit `@databricks/appkit` and `@databricks/appkit-ui` dependency values to use `file:./` prefix pointing to the tgz filenames. - -For example, if the tgz file is `databricks-appkit-0.22.0.tgz`: -```json -"@databricks/appkit": "file:./databricks-appkit-0.22.0.tgz" -``` - -Same pattern for `@databricks/appkit-ui`. - -### Step 5: Install dependencies - -Run in the target directory: - -```bash -npm install --force ./databricks-appkit-{VERSION}.tgz ./databricks-appkit-ui-{VERSION}.tgz -``` - -### Step 6: Clean up - -If CI mode was used, remove the temp directory: - -```bash -rm -rf /tmp/appkit-release-artifacts -``` - -### Step 7: Report - -Print a summary: -- Source: CI run #{number} or local build from {path} -- Version installed -- Target directory -- Installed packages diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index f6c735ba..a9fffe54 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -162,7 +162,7 @@ jobs: run: pnpm pack:sdk - name: Prepare template artifact - run: pnpm exec tsx tools/prepare-template-artifact.ts "${{ steps.version.outputs.version }}" + run: pnpm exec tsx tools/prepare-template-artifact.ts --version "${{ steps.version.outputs.version }}" - name: Install template dependencies working-directory: pr-template diff --git a/.github/workflows/prepare-release.yml b/.github/workflows/prepare-release.yml index bf0a2c89..858532e0 100644 --- a/.github/workflows/prepare-release.yml +++ b/.github/workflows/prepare-release.yml @@ -4,6 +4,7 @@ on: push: branches: - main + - pkosiec/template-artifact # temporary: remove before merge concurrency: group: prepare-release @@ -15,6 +16,8 @@ permissions: jobs: prepare: + outputs: + version: ${{ steps.version.outputs.version }} runs-on: group: databricks-protected-runner-group labels: linux-ubuntu-latest @@ -112,3 +115,57 @@ jobs: VERSION SHA256SUMS NOTICE.md + + template-artifact: + needs: [prepare] + if: needs.prepare.outputs.version != '' + runs-on: + group: databricks-protected-runner-group + labels: linux-ubuntu-latest + + steps: + - name: Checkout + uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1 + + - name: Setup JFrog npm + uses: ./.github/actions/setup-jfrog-npm + + - name: Setup pnpm + uses: pnpm/action-setup@fc06bc1257f339d1d5d8b3a19a8cae5388b55320 # v5.0.0 + + - name: Setup Node.js + uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0 + with: + node-version: 24 + cache: "pnpm" + + - name: Install dependencies + run: pnpm install --frozen-lockfile + + - name: Download release artifacts + uses: actions/download-artifact@37930b1c2abaa49bbe596cd826c3c89aef350131 # v7.0.0 + with: + name: appkit-release-${{ github.run_number }} + path: release-artifacts + + - name: Prepare template artifact + run: > + pnpm exec tsx tools/prepare-template-artifact.ts + --version "${{ needs.prepare.outputs.version }}" + --tarball-dir release-artifacts + --output-dir template-artifact + + - name: Install template dependencies + working-directory: template-artifact + run: npm install + + - name: Create zip artifact + working-directory: template-artifact + run: zip -r ../template.zip . -x 'node_modules/*' + + - name: Upload template artifact + uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0 + with: + name: appkit-template-${{ github.run_number }} + retention-days: 7 + path: template.zip diff --git a/docs/static/appkit-ui/styles.gen.css b/docs/static/appkit-ui/styles.gen.css index 9a9a38eb..a2192039 100644 --- a/docs/static/appkit-ui/styles.gen.css +++ b/docs/static/appkit-ui/styles.gen.css @@ -831,9 +831,6 @@ .max-w-\[calc\(100\%-2rem\)\] { max-width: calc(100% - 2rem); } - .max-w-full { - max-width: 100%; - } .max-w-max { max-width: max-content; } @@ -4514,6 +4511,11 @@ width: calc(var(--spacing) * 5); } } + .\[\&_\[data-slot\=scroll-area-viewport\]\>div\]\:\!block { + & [data-slot=scroll-area-viewport]>div { + display: block !important; + } + } .\[\&_a\]\:underline { & a { text-decoration-line: underline; @@ -4637,11 +4639,26 @@ color: var(--muted-foreground); } } + .\[\&_table\]\:block { + & table { + display: block; + } + } + .\[\&_table\]\:max-w-full { + & table { + max-width: 100%; + } + } .\[\&_table\]\:border-collapse { & table { border-collapse: collapse; } } + .\[\&_table\]\:overflow-x-auto { + & table { + overflow-x: auto; + } + } .\[\&_table\]\:text-xs { & table { font-size: var(--text-xs); @@ -4851,6 +4868,11 @@ width: 100%; } } + .\[\&\>\*\]\:min-w-0 { + &>* { + min-width: calc(var(--spacing) * 0); + } + } .\[\&\>\*\]\:focus-visible\:relative { &>* { &:focus-visible { diff --git a/tools/prepare-template-artifact.ts b/tools/prepare-template-artifact.ts index 5b00596c..df2e9274 100644 --- a/tools/prepare-template-artifact.ts +++ b/tools/prepare-template-artifact.ts @@ -1,15 +1,19 @@ #!/usr/bin/env tsx /** - * Prepares a PR template artifact for testing. + * Prepares a template artifact for testing or release. * - * Copies the template/ directory into a staging folder, bundles the SDK tarballs - * built by `pnpm pack:sdk`, and rewrites package.json to use `file:` references - * so the template can be tested against the PR's version of appkit/appkit-ui. + * Copies the template/ directory into a staging folder, bundles the SDK tarballs, + * and rewrites package.json to use `file:` references so the template can be + * tested against a specific version of appkit/appkit-ui. * * Usage: - * tsx tools/prepare-pr-template.ts + * tsx tools/prepare-template-artifact.ts --version [--tarball-dir ] [--output-dir ] * - * The version should match the one used when building the tarballs (e.g. 0.18.0-my-branch). + * Options: + * --version Required. Version string used to locate tarball filenames. + * --tarball-dir Optional. Single directory containing both tarballs. + * Defaults to packages/appkit/tmp/ and packages/appkit-ui/tmp/. + * --output-dir Optional. Staging directory name. Defaults to "pr-template". */ import { @@ -20,32 +24,50 @@ import { writeFileSync, } from "node:fs"; import { join } from "node:path"; +import { parseArgs } from "node:util"; const ROOT = process.cwd(); -const version = process.argv[2]; + +const { values } = parseArgs({ + options: { + version: { type: "string" }, + "tarball-dir": { type: "string" }, + "output-dir": { type: "string", default: "pr-template" }, + }, + strict: true, +}); + +const version = values.version; if (!version) { - console.error("Usage: tsx tools/prepare-pr-template.ts "); + console.error( + "Usage: tsx tools/prepare-template-artifact.ts --version [--tarball-dir ] [--output-dir ]", + ); process.exit(1); } -const STAGING_DIR = join(ROOT, "pr-template"); +const tarballDir = values["tarball-dir"]; +// biome-ignore lint/style/noNonNullAssertion: default value guarantees this is defined +const outputDir = values["output-dir"]!; + +const STAGING_DIR = join(ROOT, outputDir); const APPKIT_TARBALL = `databricks-appkit-${version}.tgz`; const APPKIT_UI_TARBALL = `databricks-appkit-ui-${version}.tgz`; // 1. Copy template into staging directory mkdirSync(STAGING_DIR, { recursive: true }); cpSync(join(ROOT, "template"), STAGING_DIR, { recursive: true }); -console.log("✓ Copied template/ → pr-template/"); +console.log(`✓ Copied template/ → ${outputDir}/`); // 2. Copy tarballs into staging directory -copyFileSync( - join(ROOT, "packages/appkit/tmp", APPKIT_TARBALL), - join(STAGING_DIR, APPKIT_TARBALL), -); -copyFileSync( - join(ROOT, "packages/appkit-ui/tmp", APPKIT_UI_TARBALL), - join(STAGING_DIR, APPKIT_UI_TARBALL), -); +const appkitSrc = tarballDir + ? join(ROOT, tarballDir, APPKIT_TARBALL) + : join(ROOT, "packages/appkit/tmp", APPKIT_TARBALL); +const appkitUiSrc = tarballDir + ? join(ROOT, tarballDir, APPKIT_UI_TARBALL) + : join(ROOT, "packages/appkit-ui/tmp", APPKIT_UI_TARBALL); + +copyFileSync(appkitSrc, join(STAGING_DIR, APPKIT_TARBALL)); +copyFileSync(appkitUiSrc, join(STAGING_DIR, APPKIT_UI_TARBALL)); console.log(`✓ Copied ${APPKIT_TARBALL} and ${APPKIT_UI_TARBALL}`); // 3. Rewrite package.json dependencies to point at the local tarballs From 7cfdd3155ecb79f720260ce4dac649baafb8bf35 Mon Sep 17 00:00:00 2001 From: Pawel Kosiec Date: Fri, 10 Apr 2026 10:36:32 +0200 Subject: [PATCH 3/3] chore: remove temporary branch trigger from prepare-release Signed-off-by: Pawel Kosiec --- .github/workflows/prepare-release.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.github/workflows/prepare-release.yml b/.github/workflows/prepare-release.yml index 858532e0..6c694704 100644 --- a/.github/workflows/prepare-release.yml +++ b/.github/workflows/prepare-release.yml @@ -4,7 +4,6 @@ on: push: branches: - main - - pkosiec/template-artifact # temporary: remove before merge concurrency: group: prepare-release