Skip to content

Conversation

@dmerand
Copy link
Contributor

@dmerand dmerand commented Jan 14, 2026

WHY are these changes introduced?

The current implementation uses hasFeatureFlag which does not delegate to Experiments Platform -- it only uses Business Platform-native feature flags, which are deprecated. Per this Slack discussion, the enabledFlags API does delegate to Verdict and should be used for new feature flags.

However, we need to maintain backward compatibility with existing beta flags while enabling new templates to use Verdict-delegated flags. More on the reasoning for that here.

WHAT is this pull request doing?

This PR implements a dual flag strategy that allows gradual migration from legacy beta flags to modern exp flags:

Dual Flag System

  • organizationBetaFlags (Legacy) → Uses hasFeatureFlag without Verdict delegation
  • organizationExpFlags (Modern) → Uses enabledFlags with Verdict delegation

NOTE That Business Platform doesn't dynamically retrieve ExP flags, so you'll still need to submit a PR to organizations flag seeds to track Verdict flags there.

Templates can now specify either or both flag types:

// Legacy templates (existing)
{organizationBetaFlags: ['oldFlag']}

// Modern templates (new - uses short hash instead of flag name)
{organizationExpFlags: ['2d5e9acc']}

// Transition templates (requires both)
{
  organizationBetaFlags: ['oldFlag'],
  organizationExpFlags: ['2d5e9acc']
}

Benefits:

  • Backward compatible - Existing beta flags continue working unchanged
  • Forward compatible - New templates can use Verdict-delegated flags. We're also using hashed flags which leak less internal information 👍🏼
  • Gradual migration - Teams can migrate at their own pace
  • No breaking changes - All existing functionality preserved
  • Performance optimized - Both flag types fetched in parallel

How to test your changes?

Test with a custom templates.json file

I used this flag which is already rolled out to test. You want to use the short flag hash in templates.json.

# Download the production templates as a base
curl https://cdn.shopify.com/static/cli/extensions/templates.json > /tmp/test-templates.json

# Edit /tmp/test-templates.json and update an existing template with a flag to match:
{
  "identifier": "whatever",
  "name": "Whatever",
  "organizationExpFlags": ["2d5e9acc"],
  //etc.
}
SHOPIFY_CLI_APP_TEMPLATES_JSON_PATH=/tmp/test-templates.json \
  shopify app generate extension

You should see whichever template you've enabled by the flag show up!

Measuring impact

How do we know this change was effective? Please choose one:

  • n/a - this doesn't need measurement, e.g. a linting rule or a bug-fix

Checklist

  • I've considered possible cross-platform impacts (Mac, Linux, Windows)
  • I've considered possible documentation changes
  • I've added comprehensive test coverage for the new functionality

Copy link
Contributor Author

dmerand commented Jan 14, 2026

This stack of pull requests is managed by Graphite. Learn more about stacking.

@github-actions
Copy link
Contributor

github-actions bot commented Jan 14, 2026

Coverage report

St.
Category Percentage Covered / Total
🟡 Statements
79.51% (+0.29% 🔼)
14345/18041
🟡 Branches
73.7% (+0.59% 🔼)
7085/9613
🟡 Functions
79.66% (+0.29% 🔼)
3670/4607
🟡 Lines
79.88% (+0.3% 🔼)
13562/16977
Show new covered files 🐣
St.
File Statements Branches Functions Lines
🟢
... / admin-as-app.ts
100% 100% 100% 100%
🟢
... / metafield_definitions.ts
100% 100% 100% 100%
🟢
... / metaobject_definitions.ts
100% 100% 100% 100%
🟢
... / bulk-operation-cancel.ts
100% 100% 100% 100%
🟢
... / bulk-operation-run-mutation.ts
100% 100% 100% 100%
🟢
... / bulk-operation-run-query.ts
100% 100% 100% 100%
🟢
... / get-bulk-operation-by-id.ts
100% 100% 100% 100%
🟢
... / list-bulk-operations.ts
100% 100% 100% 100%
🟢
... / staged-uploads-create.ts
100% 100% 100% 100%
🟢
... / fetch_store_by_domain.ts
100% 100% 100% 100%
🟢
... / organization_exp_flags.ts
100% 100% 100% 100%
🔴
... / import-custom-data-definitions.ts
0% 100% 0% 0%
🔴
... / cancel.ts
0% 100% 0% 0%
🔴
... / execute.ts
0% 0% 0% 0%
🔴
... / status.ts
0% 0% 0% 0%
🔴
... / pull.ts
0% 100% 0% 0%
🟡
... / execute-operation.ts
75% 50% 100% 75%
🔴
... / pull.ts
0% 0% 0% 0%
🟢
... / bulk-operation-status.ts
96.55% 92.11% 100% 100%
🟢
... / cancel-bulk-operation.ts
100% 100% 100% 100%
🟢
... / constants.ts
100% 100% 100% 100%
🟢
... / download-bulk-operation-results.ts
100% 100% 100% 100%
🟢
... / execute-bulk-operation.ts
92.06% 86.05% 100% 93.55%
🟢
... / format-bulk-operation-status.ts
100% 100% 100% 100%
🟢
... / run-mutation.ts
100% 100% 100% 100%
🟢
... / run-query.ts
100% 100% 100% 100%
🟡
... / stage-file.ts
73.53% 62.5% 85.71% 72.73%
🟢
... / watch-bulk-operation.ts
100% 94.74% 100% 100%
🟢
... / declarative-definitions.ts
98.54% 93.18% 100% 98.51%
🟢
... / common.ts
97.62% 95% 100% 97.06%
🟢
... / execute-command-helpers.ts
100% 100% 100% 100%
🟢
... / file-formatter.ts
100% 100% 100% 100%
🔴
... / promiseWithResolvers.ts
33.33% 50% 50% 33.33%
Show files with reduced coverage 🔻
St.
File Statements Branches Functions Lines
🔴
... / execute.ts
0%
0% (-100% 🔻)
0% 0%
🟢
... / loader.ts
94.06% (+0.2% 🔼)
86.41% (-0.42% 🔻)
97.17% (+0.11% 🔼)
94.85% (+0.18% 🔼)
🟢
... / extension-instance.ts
84.8% (+0.23% 🔼)
77.6% (-0.91% 🔻)
92.06% (+0.13% 🔼)
85.11% (+0.24% 🔼)
🟡
... / specification.ts
69.64% (+0.55% 🔼)
75.61% (+2.44% 🔼)
76.47% (-1.31% 🔻)
69.39% (+0.64% 🔼)
🟢
... / ui_extension.ts
87.9% (-6.93% 🔻)
77.19% (-4.06% 🔻)
85.19% (-14.81% 🔻)
90.07% (-6.39% 🔻)
🟢
... / deploy-release.ts
97.4% (-2.6% 🔻)
96.55% (-3.45% 🔻)
100% 100%
🟢
... / store-context.ts
100%
82.35% (-0.98% 🔻)
100% 100%
🟢
... / Logs.tsx
90%
90.91% (-5.97% 🔻)
100% 90%
🟢
... / fetch.ts
84.21% (+0.88% 🔼)
82.35% (-0.98% 🔻)
75%
85.29% (+1.42% 🔼)
🟢
... / app-event-watcher-handler.ts
86.36% (-4.11% 🔻)
75% 86.67%
85.71% (-5.19% 🔻)
🟢
... / bundle.ts
93.22%
63.33% (-3.33% 🔻)
94.12% (+5.88% 🔼)
96.3%
🟢
... / developer-platform-client.ts
84.62% (-1.5% 🔻)
71.43% (+0.84% 🔼)
81.82% (+1.82% 🔼)
93.75% (+0.42% 🔼)
🔴
... / http-reverse-proxy.ts
58.97% (-4.91% 🔻)
37.04% (-2.96% 🔻)
58.33% (-5.3% 🔻)
59.46% (-5.25% 🔻)
🟢
... / api.ts
87.07% (-0.43% 🔻)
76.71% (-0.1% 🔻)
100%
86.49% (-0.43% 🔻)
🟢
... / ConcurrentOutput.tsx
98.36% (-1.64% 🔻)
92% (-4% 🔻)
100%
98.33% (-1.67% 🔻)
🟢
... / SingleTask.tsx
84.21% (-15.79% 🔻)
50% (-50% 🔻)
80% (-20% 🔻)
84.21% (-15.79% 🔻)
🔴
... / environment.ts
35% (-5% 🔻)
41.18%
40% (-10% 🔻)
36.84% (-5.26% 🔻)
🔴
... / ui.tsx
50.82% (-0.79% 🔻)
42.86% (-5.53% 🔻)
54.55% (+1.42% 🔼)
50% (-0.82% 🔻)
🟢
... / console.ts
81.82% (+15.15% 🔼)
75% (-25% 🔻)
100% (+33.33% 🔼)
81.82% (+15.15% 🔼)
🟢
... / init.ts
88% (-0.89% 🔻)
71.43% (+4.76% 🔼)
86.67% (+4.85% 🔼)
88% (-0.89% 🔻)
🟢
... / storefront-renderer.ts
90.2% (-0.54% 🔻)
78.95%
81.82% (-1.52% 🔻)
90.2% (-0.54% 🔻)
🟡
... / theme-polling.ts
67.12% (-0.93% 🔻)
68.75% 78.57%
66.67% (-0.98% 🔻)

Test suite run success

3657 tests passing in 1428 suites.

Report generated by 🧪jest coverage report action from 2b1c630

@dmerand dmerand force-pushed the dlm-org-flags-query branch 3 times, most recently from d9c7461 to 2a975f5 Compare January 15, 2026 17:33
@dmerand dmerand marked this pull request as ready for review January 15, 2026 17:33
@dmerand dmerand requested a review from a team as a code owner January 15, 2026 17:33
@github-actions
Copy link
Contributor

We detected some changes at packages/*/src and there are no updates in the .changeset.
If the changes are user-facing, run pnpm changeset add to track your changes and include them in the next release CHANGELOG.

Caution

DO NOT create changesets for features which you do not wish to be included in the public changelog of the next CLI release.

@dmerand dmerand force-pushed the dlm-org-flags-query branch from 2a975f5 to 2b1c630 Compare January 15, 2026 17:52
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.

1 participant