@databricks-solutions/lakebase-scm-utils 0.3.4 → 0.3.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (46) hide show
  1. package/dist/scripts/github/index.cjs +14 -0
  2. package/dist/scripts/github/index.d.cts +19 -1
  3. package/dist/scripts/github/index.d.ts +19 -1
  4. package/dist/scripts/github/index.js +13 -0
  5. package/dist/scripts/index.cjs +79 -2
  6. package/dist/scripts/index.d.cts +2 -2
  7. package/dist/scripts/index.d.ts +2 -2
  8. package/dist/scripts/index.js +76 -2
  9. package/dist/scripts/lakebase/ci-resolve-branch.cli.cjs +2 -2
  10. package/dist/scripts/lakebase/ci-resolve-branch.cli.js +2 -2
  11. package/dist/scripts/lakebase/collapse-heads.cli.cjs +2 -2
  12. package/dist/scripts/lakebase/collapse-heads.cli.js +2 -2
  13. package/dist/scripts/lakebase/detect-language.cli.cjs +2 -2
  14. package/dist/scripts/lakebase/detect-language.cli.js +2 -2
  15. package/dist/scripts/lakebase/doctor.cli.cjs +15664 -7598
  16. package/dist/scripts/lakebase/doctor.cli.js +8243 -106
  17. package/dist/scripts/lakebase/get-connection.cli.cjs +2 -2
  18. package/dist/scripts/lakebase/get-connection.cli.js +2 -2
  19. package/dist/scripts/lakebase/index.cjs +172 -95
  20. package/dist/scripts/lakebase/index.d.cts +22 -1
  21. package/dist/scripts/lakebase/index.d.ts +22 -1
  22. package/dist/scripts/lakebase/index.js +170 -95
  23. package/dist/scripts/lakebase/infra-runner.cli.cjs +2 -2
  24. package/dist/scripts/lakebase/infra-runner.cli.js +2 -2
  25. package/dist/scripts/lakebase/new-migration.cli.cjs +2 -2
  26. package/dist/scripts/lakebase/new-migration.cli.js +2 -2
  27. package/dist/scripts/lakebase/schema-diff.cli.cjs +2 -2
  28. package/dist/scripts/lakebase/schema-diff.cli.js +2 -2
  29. package/dist/scripts/lakebase/schema-migrate.cli.cjs +2 -2
  30. package/dist/scripts/lakebase/schema-migrate.cli.js +2 -2
  31. package/dist/scripts/lakebase/scm-claim-feature.cli.cjs +2 -2
  32. package/dist/scripts/lakebase/scm-claim-feature.cli.js +2 -2
  33. package/dist/scripts/lakebase/scm-doctor.cli.cjs +2 -2
  34. package/dist/scripts/lakebase/scm-doctor.cli.js +2 -2
  35. package/dist/scripts/lakebase/scm-merge.cli.cjs +2 -2
  36. package/dist/scripts/lakebase/scm-merge.cli.js +2 -2
  37. package/dist/scripts/lakebase/scm-reconcile-tier.cli.cjs +2 -2
  38. package/dist/scripts/lakebase/scm-reconcile-tier.cli.js +2 -2
  39. package/dist/scripts/util/index.cjs +2 -2
  40. package/dist/scripts/util/index.js +2 -2
  41. package/package.json +1 -1
  42. package/scripts/github/repo.ts +37 -1
  43. package/scripts/lakebase/create-preflight.ts +45 -0
  44. package/scripts/lakebase/create-project.ts +15 -0
  45. package/scripts/lakebase/doctor.ts +50 -0
  46. package/templates/project/common/.github/workflows/pr.yml +14 -5
@@ -20,6 +20,8 @@ import {
20
20
  import {
21
21
  checkDatabricksAuth,
22
22
  databricksAuthPrereqMessage,
23
+ checkGitHubWorkflowScope,
24
+ githubWorkflowScopePrereqMessage,
23
25
  withLakebaseRollback,
24
26
  validateCreateInputs,
25
27
  dirIsEmpty,
@@ -289,6 +291,19 @@ export async function createProject(
289
291
  throw new Error(databricksAuthPrereqMessage(host, auth.reason));
290
292
  }
291
293
 
294
+ // ── GitHub token `workflow` scope precondition ────────────────
295
+ // The scaffold's final push commits .github/workflows/*, which GitHub rejects
296
+ // unless the token carries the `workflow` OAuth scope. Check it HERE, before any
297
+ // GitHub repo or Lakebase project exists, so a missing scope fails in seconds with
298
+ // a fix instead of at the final push after all provisioning (which then rolls back).
299
+ if (useGithub) {
300
+ report("Checking GitHub token scopes...");
301
+ const scope = await checkGitHubWorkflowScope();
302
+ if (!scope.ok) {
303
+ throw new Error(githubWorkflowScopePrereqMessage(scope.reason));
304
+ }
305
+ }
306
+
292
307
  // ── Step 1+2: GitHub repo + clone, OR local-only setup ────────
293
308
  if (useGithub) {
294
309
  report("Creating GitHub repository...", fullRepoName);
@@ -14,6 +14,7 @@ import { listBranches } from "./branch-utils.js";
14
14
  import { verifyHooks } from "./project-verify.js";
15
15
  import { detectLanguage } from "./schema-migrate.js";
16
16
  import { detectWorkflowDrift } from "./workflow-drift.js";
17
+ import { checkGitHubScopes } from "../github/repo.js";
17
18
 
18
19
  export type CheckStatus = "ok" | "warn" | "fail" | "skip";
19
20
 
@@ -593,6 +594,53 @@ async function checkGitRemote(projectDir: string): Promise<CheckResult> {
593
594
  }
594
595
  }
595
596
 
597
+ /**
598
+ * Probe whether the GitHub token carries the `workflow` scope needed to push
599
+ * `.github/workflows/*`. A missing scope is exactly why a scaffold push (or any
600
+ * later workflow edit) gets rejected at the very end and rolls back. Best-effort:
601
+ * no token, OR a fine-grained / GitHub App token (no visible OAuth scopes), OR
602
+ * an API error → `skip`, never a false `fail`. `probe` is injectable for tests.
603
+ */
604
+ export async function checkGitHubTokenScope(
605
+ probe: () => Promise<{ granted: string[] | null; missing: string[] }> = () =>
606
+ checkGitHubScopes(["workflow"])
607
+ ): Promise<CheckResult> {
608
+ try {
609
+ const { granted, missing } = await probe();
610
+ if (granted === null) {
611
+ return {
612
+ name: "github-token-scope",
613
+ status: "skip",
614
+ message:
615
+ "GitHub token scopes not visible (fine-grained PAT / App token) - `workflow` scope unverified",
616
+ };
617
+ }
618
+ if (missing.includes("workflow")) {
619
+ return {
620
+ name: "github-token-scope",
621
+ status: "fail",
622
+ message:
623
+ "GitHub token lacks the `workflow` scope - pushes touching .github/workflows/* will be rejected",
624
+ detail: { granted },
625
+ hint: "Grant it with `gh auth refresh -h github.com -s workflow`, re-sign in to GitHub in VS Code and approve the workflow scope, or set GITHUB_TOKEN to a PAT that includes `workflow`.",
626
+ };
627
+ }
628
+ return {
629
+ name: "github-token-scope",
630
+ status: "ok",
631
+ message: "GitHub token has the `workflow` scope",
632
+ detail: { granted },
633
+ };
634
+ } catch (err) {
635
+ return {
636
+ name: "github-token-scope",
637
+ status: "skip",
638
+ message: "GitHub token scope check skipped (no token resolved, or GitHub unreachable)",
639
+ detail: { error: (err as Error).message },
640
+ };
641
+ }
642
+ }
643
+
596
644
  function checkLanguage(projectDir: string): CheckResult {
597
645
  try {
598
646
  const lang = detectLanguage(projectDir);
@@ -732,6 +780,7 @@ export async function runDoctor(args: DoctorArgs = {}): Promise<DoctorReport> {
732
780
  host
733
781
  );
734
782
  const gitRemote = await checkGitRemote(projectDir);
783
+ const githubTokenScope = await checkGitHubTokenScope();
735
784
  const language = checkLanguage(projectDir);
736
785
  const hooks = checkHooks(projectDir);
737
786
  const workflowDrift = checkWorkflowDrift(projectDir);
@@ -763,6 +812,7 @@ export async function runDoctor(args: DoctorArgs = {}): Promise<DoctorReport> {
763
812
  configProfile,
764
813
  lakebaseProject,
765
814
  gitRemote,
815
+ githubTokenScope,
766
816
  language,
767
817
  hooks,
768
818
  workflowDrift,
@@ -148,11 +148,6 @@ jobs:
148
148
  # the CI branch is provisioned and fail fast. `--if-present` no-ops a
149
149
  # client with no `test` script. The client's Playwright E2E runs later
150
150
  # (its own step, gated on client/playwright.config.ts).
151
- - name: Run client unit tests
152
- if: hashFiles('client/package.json') != ''
153
- working-directory: client
154
- run: npm run test --if-present
155
-
156
151
  # The official action installs to a user-writable path (no sudo). It's
157
152
  # a no-op if a compatible databricks CLI is already on PATH.
158
153
  - name: Install Databricks CLI
@@ -384,6 +379,20 @@ jobs:
384
379
  --pretty
385
380
  echo "Migrations completed."
386
381
 
382
+ - name: Run client unit tests
383
+ # The kit's client/vitest.globalSetup.ts boots a REAL backend over the /api
384
+ # boundary (never mock when a real counterpart exists), so the component suite
385
+ # NEEDS the CI Lakebase branch + DATABASE_URL. Run it AFTER datasource config +
386
+ # migrations, not before. No-op when there are no component tests (globalSetup
387
+ # returns early); skipped when there is no CI Lakebase branch (url empty).
388
+ if: hashFiles('client/package.json') != '' && steps.lakebase-db.outputs.url != ''
389
+ working-directory: client
390
+ env:
391
+ DATABASE_URL: ${{ env.DATABASE_URL }}
392
+ DB_USERNAME: ${{ env.DB_USERNAME }}
393
+ DB_PASSWORD: ${{ env.DB_PASSWORD }}
394
+ run: npm run test --if-present
395
+
387
396
  - name: Run tests
388
397
  env:
389
398
  DATABASE_URL: ${{ env.DATABASE_URL }}