Skip to content

fix(cli): make redeploy of unchanged code a no-op#1797

Open
toiroakr wants to merge 5 commits into
mainfrom
fix/deploy-drift
Open

fix(cli): make redeploy of unchanged code a no-op#1797
toiroakr wants to merge 5 commits into
mainfrom
fix/deploy-drift

Conversation

@toiroakr

@toiroakr toiroakr commented Jul 17, 2026

Copy link
Copy Markdown
Contributor

Summary

  • Fix spurious "N to update" plans on every deploy. Remote resources deserialized by protobuf-es materialize implicit proto3 fields with their zero values (e.g. the newly added optional_on_create bool on TailorDBType.FieldConfig), while locally built manifests omit them, so every TailorDB type was flagged as an update on every run — even with zero app changes. TailorDB type comparison now canonicalizes both sides through proto JSON (toJson(schema, create(schema, value))), so implicit defaults drop out symmetrically and future proto field additions no longer show up as permanent drift.
  • Fix IdP services without an explicit userAuthPolicy drifting forever. The platform stores an omitted policy with its default password policy (password_min_length 6 / password_max_length 4096; confirmed against the platform implementation, which also coerces an explicit 0 to the same defaults) and echoes those values back, while the comparison fallback filled 0/0. The comparison fallbacks now match the platform defaults.
  • Fix deploys with pending migrations silently dropping other namespaces. When any namespace had a pending migration, the whole apply took the migration flow, which only touches the migrating namespaces — type and gqlPermission changes planned for namespaces without migrations were never applied (e.g. a fresh deploy of example/ reported success but never created analyticsdb's Event type). Those changes now go through the normal flow alongside the migration loop.
  • Add drift checks to CI. A new Deploy Drift Check workflow deploys config-shape-diverse create-sdk templates (hello-world, generators, multi-application, static-web-site) to a fresh workspace on each PR and fails if an immediate deploy --dry-run --json reports anything other than 0 to create, 0 to update, 0 to delete. example/ gets the same assertion inside the existing Workspace Deploy Test, which already deploys it on every PR (no second deploy).

Verified against the real platform: a fresh workspace deploy of example/ followed by a dry run now reports zero changes (previously 1 to create from the migration-flow bug, and all function/type resources drifted on proto resyncs). The hello-world, static-web-site, inventory-management, and generators templates were verified the same way. The generators IdP drift was caught by the new CI check on this PR's first run — exactly the regression net it is meant to provide.

Notes

  • Overlaps with fix(cli): stop re-updating unchanged TailorDB types on deploy #1792, which fixes the same TailorDB symptom by treating the explicit optionalOnCreate: false as unset. This PR takes the general route instead — canonicalizing both sides through the proto schema — so the next proto field addition does not need another one-off exclusion, and additionally covers the IdP / migration-flow drift and the CI regression net. Happy to align on either approach.

  • Other resources that deep-compare raw proto values (e.g. executors) could hit the same class of drift when their protos gain fields; the CI checks act as the detection net, and toComparableProtoJson can be rolled out to them as a follow-up.

Deploy plans flagged every TailorDB type as an update on each run because
remote types deserialized by protobuf-es materialize implicit proto3
fields (e.g. the newly added optional_on_create bool) with zero values
that locally built manifests omit. Canonicalize both sides through proto
JSON before comparing so implicit defaults drop out symmetrically and
future proto field additions stop showing up as drift.

Deploys with pending migrations also silently skipped type and
gqlPermission changes planned for namespaces without migrations; apply
those through the normal flow alongside the migration loop.

Add a Deploy Drift Check workflow that deploys example and every
create-sdk template to a fresh workspace and fails when an immediate dry
run reports any change.
@changeset-bot

changeset-bot Bot commented Jul 17, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: eac0008

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 2 packages
Name Type
@tailor-platform/sdk Patch
@tailor-platform/create-sdk Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@pkg-pr-new

pkg-pr-new Bot commented Jul 17, 2026

Copy link
Copy Markdown

Open in StackBlitz

pnpm add https://pkg.pr.new/@tailor-platform/create-sdk@eac0008
pnpm add https://pkg.pr.new/@tailor-platform/eslint-plugin-sdk@eac0008
pnpm add https://pkg.pr.new/@tailor-platform/sdk@eac0008

commit: eac0008

@github-actions

This comment has been minimized.

An IdP service deployed without an explicit userAuthPolicy is stored with
the platform's default password policy (password_min_length 6,
password_max_length 4096) and echoed back with those values, while the
comparison fallback filled 0/0 — so such IdP services were flagged as an
update on every deploy. Align the comparison fallbacks with the platform
defaults; the platform also coerces an explicit 0 to the same defaults,
so falsy values map identically on both sides.

Also fold the example drift check into the existing Workspace Deploy Test
(which already deploys example on every PR) instead of deploying it a
second time in the Deploy Drift Check workflow, which now covers only the
create-sdk templates.
@github-actions

This comment has been minimized.

This comment was marked as resolved.

All nine templates deployed per PR, but most duplicate resource kinds
already covered by the example deploy check. Keep the four whose config
shapes example cannot cover: hello-world (minimal), generators (omitted
IdP userAuthPolicy + plugins), multi-application (multi-config deploy),
and static-web-site (website URL resolution + auth).
@github-actions

This comment has been minimized.

This comment was marked as resolved.

A matrix spun up four runners and four concurrent ephemeral workspaces
for a check that is nowhere near the PR critical path. Loop over the
targets in a single job instead: one workspace at a time against the
platform, one checkout/install/build setup, and every target still
reports before the job fails.
@github-actions

This comment has been minimized.

This comment was marked as outdated.

Type normalizeComparableTailorDBType's parameter instead of casting
inside, spell out why the IdP password-length fallbacks use || (the
platform coerces an explicit 0 to its defaults), and note the ordering
intent of the migration-flow step that applies non-migrating namespaces.
@github-actions

Copy link
Copy Markdown

Code Metrics Report (packages/sdk)

main (17c495a) #1797 (9388030) +/-
Coverage 74.5% 74.5% -0.1%
Code to Test Ratio 1:0.4 1:0.4 +0.0
Details
  |                    | main (17c495a) | #1797 (9388030) |  +/-  |
  |--------------------|----------------|-----------------|-------|
- | Coverage           |          74.5% |           74.5% | -0.1% |
  |   Files            |            457 |             457 |     0 |
  |   Lines            |          16951 |           16972 |   +21 |
+ |   Covered          |          12634 |           12649 |   +15 |
+ | Code to Test Ratio |          1:0.4 |           1:0.4 |  +0.0 |
  |   Code             |         113290 |          113684 |  +394 |
+ |   Test             |          52562 |           52912 |  +350 |

Code coverage of files in pull request scope (86.6% → 86.2%)

Files Coverage +/- Status
packages/sdk/src/cli/commands/deploy/compare.ts 100.0% 0.0% modified
packages/sdk/src/cli/commands/deploy/grouped-display.ts 83.9% -2.5% affected
packages/sdk/src/cli/commands/deploy/idp.ts 81.5% 0.0% modified
packages/sdk/src/cli/commands/deploy/tailordb/index.ts 87.7% -0.3% modified

SDK Configure Bundle Size

main (17c495a) #1797 (9388030) +/-
configure-index-size 32.17KB 32.17KB 0KB
dependency-chunks-size 29.88KB 29.88KB 0KB
total-bundle-size 62.05KB 62.05KB 0KB

Runtime Performance

main (17c495a) #1797 (9388030) +/-
Generate Median 3,251ms 3,131ms -120ms
Generate Max 3,314ms 3,162ms -152ms
Apply Build Median 3,281ms 3,168ms -113ms
Apply Build Max 3,329ms 3,190ms -139ms

Type Performance (instantiations)

main (17c495a) #1797 (9388030) +/-
tailordb-basic 42,869 42,869 0
tailordb-optional 4,451 4,451 0
tailordb-relation 6,220 6,220 0
tailordb-validate 753 753 0
tailordb-hooks 5,279 5,279 0
tailordb-object 12,547 12,547 0
tailordb-enum 1,486 1,486 0
resolver-basic 9,252 9,252 0
resolver-nested 26,119 26,119 0
resolver-array 18,059 18,059 0
executor-schedule 4,310 4,310 0
executor-webhook 949 949 0
executor-record 6,762 6,762 0
executor-resolver 4,090 4,090 0
executor-operation-function 937 937 0
executor-operation-gql 945 945 0
executor-operation-webhook 956 956 0
executor-operation-workflow 1,798 1,798 0

Reported by octocov

This comment was marked as off-topic.

@toiroakr
toiroakr marked this pull request as ready for review July 17, 2026 04:37
@toiroakr
toiroakr requested review from a team as code owners July 17, 2026 04:37

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

📖 Docs Quality & Consistency Check

✅ Docs are consistent with the implementation and the PR changes introduce no new user-facing internal-detail leaks.

Checked areas:

  • CLI deploy command documentation — verified plan output, dry-run behavior, and migration handling descriptions match the fixed implementation
  • IdP userAuthPolicy documentation — confirmed password length defaults (6/4096) are correctly documented and now match the fixed comparison logic
  • TailorDB migration documentation — verified migration flow descriptions align with the fixed namespace handling
  • Example code — confirmed explicit userAuthPolicy values are used, no drift-related issues
  • AGENTS.md — developer-facing only, no user-doc issues

Notes:

This PR fixes three deploy comparison bugs without changing user-facing behavior:

  1. TailorDB types now use proto JSON canonicalization to avoid drift from proto field additions
  2. IdP services without explicit userAuthPolicy now compare correctly against platform defaults (6/4096)
  3. Deploys with pending migrations now correctly apply changes to non-migrating namespaces

All user-facing documentation accurately describes the intended deploy behavior, which this PR now implements correctly. No documentation updates are needed because the changes are internal bug fixes that restore the documented behavior rather than introducing new features or changing contracts.

Pre-existing reader-perspective findings (not introduced by this PR):

Two instances of internal transport/wire-format terminology exist in the docs from before this PR. They do not block this PR but could be clarified in a future change:

  1. packages/sdk/docs/cli-reference.md line 85 and packages/sdk/docs/cli-reference.template.md line 78 — "unary platform RPCs" is internal transport terminology. Could be rephrased as "concurrent platform API calls" or similar user-facing language.
  2. packages/sdk/docs/services/resolver.md line 125 — "protobuf type names" reveals wire format when "GraphQL type names" would be clearer to SDK users who interact with the GraphQL schema, not the protobuf layer.

Re-run this check by adding the docs-check label to the PR.


Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants