Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ jobs:
test:
runs-on: ubuntu-latest
strategy:
# Keep the required Node 20 branch-protection check while testing the
# supported Node 22 and 24 runtimes. The package engine floor remains 22.
matrix: { node: [20, 22, 24] }
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
Expand Down Expand Up @@ -35,7 +37,7 @@ jobs:
persist-credentials: false
- uses: actions/setup-node@949feb2413d6458794dcd2491c4babbbce0c15c1
with:
node-version: 20
node-version: 24
cache: npm
- run: npm ci --ignore-scripts
- run: npm run build:action
Expand Down
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,12 @@

## Unreleased

- Add `UG-EXT-001` for missing `owner_type` in structurally parsed Checkout and Customer Account UI extension metafield declarations; report an optional migration warning for target `2026-10` and a deployment error from target `2027-01`.
- Extend `UG-ADMIN-002` to detect literal references to the removed `DiscountAutomaticConnection` and `DiscountAutomaticEdge` GraphQL types.
- Raise the minimum CLI runtime from Node.js 20 to 22, test Node.js 22 and 24, and retain the Node.js 24 GitHub Action runtime.
- Reverify the Shopify version registry on 21 October 2026; `2027-01` remains a release candidate and `2025-10` is now beyond its documented access cutoff.
- Retain GraphQL 16.14.2; the extension rule uses TOML parsing and does not depend on the separate open GraphQL 17 Dependabot change.

## 0.3.0

- Pin all CodeQL steps to the same immutable v4.38.3 commit to prevent mismatched init and analyze versions.
Expand Down
2 changes: 1 addition & 1 deletion CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ Do not add rules based only on blog posts, social posts, guesses, or undocumente

## Development

Requires Node.js 20 or newer.
Requires Node.js 22 or newer. The supported CI matrix uses Node.js 22 and 24.

```bash
npm ci
Expand Down
9 changes: 6 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ Shopify Upgrade Guard is an offline, evidence-backed CLI and GitHub Action for S

Maintained by RexCode Digital Ltd.

Part of the **RexCode Shopify developer tools** suite. Requires Node.js 20 or later for the CLI. The parser remains on GraphQL 16 because GraphQL 17.0.2 requires Node.js 22 or later, which would drop the supported Node.js 20 runtime. [Releases](https://github.com/RexCode-Digital/shopify-upgrade-guard/releases) · [npm](https://www.npmjs.com/package/shopify-upgrade-guard) · [Marketplace](https://github.com/marketplace/actions/shopify-upgrade-guard)
Part of the **RexCode Shopify developer tools** suite. This source version requires Node.js 22 or later for the CLI. [Releases](https://github.com/RexCode-Digital/shopify-upgrade-guard/releases) · [npm](https://www.npmjs.com/package/shopify-upgrade-guard) · [Marketplace](https://github.com/marketplace/actions/shopify-upgrade-guard)

## Quick start

Expand Down Expand Up @@ -102,13 +102,14 @@ The rule pack is intentionally focused. Literal GraphQL checks parse supported d
| --- | --- | --- |
| `UG-CHECKOUT-001` | `useBuyerJourneyIntercept` / `buyerJourney.intercept` | [Shopify changelog](https://shopify.dev/changelog/deprecating-the-usebuyerjourneyintercept-api-on-checkout-ui-extensions) |
| `UG-CHECKOUT-002` | Checkout `block_progress` capability | [Shopify changelog](https://shopify.dev/changelog/deprecating-the-usebuyerjourneyintercept-api-on-checkout-ui-extensions) |
| `UG-EXT-001` | Missing `owner_type` in eligible Checkout or Customer Account UI extension metafield declarations | [Shopify changelog](https://shopify.dev/changelog/posts/metafield-owner-types-required-for-checkout-and-customer-account-ui-extensions) |
| `UG-REST-001` | Legacy Admin REST usage | [REST Admin API](https://shopify.dev/docs/api/admin-rest) |
| `UG-VERSION-001` | Unsupported or target-retiring API versions | [API versioning](https://shopify.dev/docs/api/usage/versioning) |
| `UG-VERSION-002` | Supported versions older than the latest stable version | [API versioning](https://shopify.dev/docs/api/usage/versioning) |
| `UG-CUSTOMER-001` | Customer Account checkout removals relevant to 2026-10 | [Shopify changelog](https://shopify.dev/changelog/customer-account-api-last-incomplete-checkout-and-checkout-types-removed) |
| `UG-POS-001` | Removed POS `session.currentSession.staffMemberId` usage | [Shopify changelog](https://shopify.dev/changelog/removed-session-currentsession-staffmemberid-from-pos-ui-extensions-2026-10) |
| `UG-ADMIN-001` | Legacy Admin GraphQL `priceRule` usage | [2026-10 release notes](https://shopify.dev/release-notes/2026-10) |
| `UG-ADMIN-002` | Literal GraphQL root `automaticDiscounts` removed in 2027-01 | [Official removal](https://shopify.dev/changelog/posts/automaticdiscounts-query-is-removed-in-api-version-2027-01) |
| `UG-ADMIN-002` | Literal GraphQL `automaticDiscounts` root field and removed `DiscountAutomaticConnection` / `DiscountAutomaticEdge` types | [Official removal](https://shopify.dev/changelog/posts/automaticdiscounts-query-is-removed-in-api-version-2027-01) |
| `UG-ADMIN-003` | GraphQL `metafieldInteger` collection conditions and types removed in 2027-01 | [Official removal](https://shopify.dev/changelog/posts/metafieldinteger-collection-condition-removed-in-api-version-2027-01) |
| `UG-ADMIN-004` | `ProductVariant.barcode` read deprecated in 2026-10; it still works and no removal date is announced | [Official deprecation](https://shopify.dev/changelog/posts/product-variant-barcode-is-being-replaced-by-barcodes) |
| `UG-ADMIN-006` | Literal `marketCurrencySettingsUpdate` Admin mutation removed in 2027-01 | [Official removal](https://shopify.dev/changelog/posts/removing-marketcurrencysettingsupdate-mutation) |
Expand All @@ -119,6 +120,8 @@ The rule pack is intentionally focused. Literal GraphQL checks parse supported d

Supported inventory surfaces include Admin REST, Admin GraphQL, Checkout UI extensions, Customer Account UI extensions, POS UI extensions, Functions, Shopify app TOML, and recognized Shopify client configuration.

See the [2027-01 migration guide](docs/2027-01-migration.md) for the extension `owner_type` requirement, target-version behavior, evidence, and limits. The rule is in the Unreleased change set; existing npm packages and Action tags do not gain it until a release containing this branch is published.

## CLI

```text
Expand Down Expand Up @@ -160,7 +163,7 @@ Baselined findings remain reviewable while new fingerprints stay actionable.

`--fail-on-new` requires a valid Git base comparison. Upgrade Guard scans the base commit and head tree independently, then matches findings by rule, file identity, and evidence; recognized file renames keep existing debt stable. JSON includes `resolvedFindings`, and human output reports their count. Fetch full history and provide `--base-ref`, or use the pull-request Action. Missing refs/history exit 2 instead of passing an incomplete comparison.

The bundled snapshot, verified 14 October 2026, lists `2026-10` as the latest stable API and `2027-01` as a release candidate for development testing. Version status uses Shopify's exact `accessibleUntil` timestamp: `2025-10` remains accessible until 16 October 2026 at 15:00 UTC, then becomes unsupported. Future version names do not imply verified rule coverage.
The bundled snapshot, verified 21 October 2026, lists `2026-10` as the latest stable API and `2027-01` as a release candidate for development testing. Shopify lists `2027-01` as a release candidate until 1 January 2027, when it becomes stable. Version status uses Shopify's exact `accessibleUntil` timestamp; `2025-10` became unsupported on 16 October 2026 at 15:00 UTC. Future version names do not imply verified rule coverage.

The 2027-01 tax payload change converts IDs in tax calculation requests and tax summary webhook payloads to Global IDs. Upgrade Guard cannot reliably tell whether arbitrary runtime parsing assumes numeric IDs, so tax app handlers need review against Shopify's [official migration note](https://shopify.dev/changelog/posts/tax-webhook-summary-and-calculation-requests-now-use-global-ids).

Expand Down
1 change: 1 addition & 0 deletions ROADMAP.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
# Roadmap

- Extend target-aware rules when official Shopify notes support reliable static detection.
- Prepare the `UG-EXT-001` 2027-01 extension metafield migration check for the next reviewed release; see [the migration guide](docs/2027-01-migration.md).
- Expand high-confidence coverage where Customer Account, POS, Functions, and GraphQL changes can be identified statically.
- Revisit generated GraphQL deprecation metadata only if Shopify provides a versioned source with clear redistribution rights; see [the technical decision](docs/graphql-deprecation-metadata.md).
- Publish signed release artifacts after npm and GitHub account gates are configured.
24 changes: 23 additions & 1 deletion THIRD_PARTY_NOTICES.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Third-party notices

The generated GitHub Action bundle `dist/index.js` contains third-party code. Its companion `dist/licenses.txt` is generated by ncc from the bundled dependency graph and carries the full licence texts for bundled modules. The direct GraphQL.js dependency is resolved in `package-lock.json` and is listed below.
The generated GitHub Action bundle `dist/index.js` contains third-party code. Its companion `dist/licenses.txt` is generated by ncc from the bundled dependency graph and carries the full licence texts for bundled modules. The direct GraphQL.js and TOML parser dependencies are resolved in `package-lock.json` and listed below.

## GraphQL.js

Expand Down Expand Up @@ -31,3 +31,25 @@ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
```

## @iarna/toml

- Upstream: [iarna/iarna-toml](https://github.com/iarna/iarna-toml)
- Version resolved by this repository: 2.2.5
- Licence: ISC

```text
Copyright (c) 2016, Rebecca Turner <me@re-becca.org>

Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.

THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
```
2 changes: 1 addition & 1 deletion data/versions.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"verifiedAt": "2026-10-14",
"verifiedAt": "2026-10-21",
"source": "https://shopify.dev/docs/api/usage/versioning",
"versions": [
{
Expand Down
2 changes: 1 addition & 1 deletion dist/index.js

Large diffs are not rendered by default.

18 changes: 18 additions & 0 deletions dist/licenses.txt
Original file line number Diff line number Diff line change
@@ -1,3 +1,21 @@
@iarna/toml
ISC
Copyright (c) 2016, Rebecca Turner <me@re-becca.org>

Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.

THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.



graphql
MIT
MIT License
Expand Down
28 changes: 28 additions & 0 deletions docs/2027-01-migration.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
# Shopify API 2027-01 migration guide

Shopify's `2027-01` API is a release candidate for development testing as of 21 October 2026. Shopify's release notes list it as stable from 1 January 2027. Do not treat the release candidate as a production stable version.

## Extension metafield `owner_type`

Checkout and Customer Account UI extensions can add `owner_type` to metafield declarations from API version `2026-10`. Shopify requires it for each `[[extensions.metafields]]` and `[[extensions.targeting.metafields]]` declaration starting with `2027-01`. A deployment targeting `2027-01` or later is blocked if a declaration omits the property.

Upgrade Guard reports this as `UG-EXT-001` when a structurally parsed `shopify.extension.toml` contains a `type = "ui_extension"` extension with a Checkout or Customer Account target:

- For target `2026-10`, a missing property is a warning. It is optional in that version; add the correct resource owner before upgrading.
- For target `2027-01` or later, a missing property is an error because Shopify blocks deployment.
- Targets before `2026-10` are not reported because the property is not available there.

Choose the owner type from the resource that actually owns each metafield. Upgrade Guard does not infer it from `namespace`, `key`, the extension name, or the target. If one namespace/key pair refers to multiple resource types, Shopify's migration guidance calls for a separate declaration for each owner type.

The detector follows each extension's TOML structure. It checks global declarations only when that extension has an eligible target, and checks target-specific declarations only for the matching Checkout or Customer Account target. Other extension types and targets are ignored. Findings identify the relative TOML file and table-header line; they do not include the namespace or key.

```sh
shopify-upgrade-guard scan --target 2026-10
shopify-upgrade-guard scan --target 2027-01
```

`2027-01` is a release candidate, so use it for migration review and development testing. This check proves only that a supported static TOML declaration is missing the property; it does not validate that a chosen owner type is semantically correct. Malformed `shopify.extension.toml` input fails the scan instead of being treated as a clean result.

This rule is in the Unreleased change set. Existing npm package versions and published Action tags do not include it until a release containing the change is published.

Evidence: [Shopify's owner_type changelog](https://shopify.dev/changelog/posts/metafield-owner-types-required-for-checkout-and-customer-account-ui-extensions), [Checkout metafield configuration](https://shopify.dev/docs/apps/build/checkout/metafields), [Customer Account metafields](https://shopify.dev/docs/apps/build/customer-accounts/metafields-in-customer-accounts), and [2027-01 release notes](https://shopify.dev/changelog/release-notes/2027-01).
8 changes: 7 additions & 1 deletion docs/release-process.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,4 +10,10 @@ Before enabling the first release tag, configure npm Trusted Publishing for pack
- workflow: `.github/workflows/release.yml`;
- environment: leave unset unless the npm package policy requires one.

For 0.2.0, verify the release PR, generated `dist`, coverage, package smoke test, and official evidence links before creating the tag. Marketplace submission is a separate final UI gate.
For each release, verify the reviewed PR, generated `dist`, coverage, package smoke test, third-party license inventory, and official evidence links before creating a tag. Marketplace submission is a separate final UI gate.

## Next candidate: 0.4.0

The next candidate is `0.4.0` under the current 0.x versioning policy. Requiring Node.js 22 is a breaking change for users still on Node.js 20, so include it in the release notes and check `engines.node`, setup-node matrices, and runtime documentation together.

Before any release, require PR review and hosted CI on Node.js 22 and 24, reproducible Action bundling, clean package installation and smoke checks, `npm pack --dry-run`, dependency audit, and a review of third-party notices and immutable Action SHAs. Confirm npm provenance configuration and changelog accuracy. This is a plan only; it does not create a tag, GitHub Release, or npm publication.
7 changes: 7 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@
"prebuild:action": "node scripts/write-version.mjs"
},
"engines": {
"node": ">=20"
"node": ">=22"
},
"license": "MIT",
"repository": {
Expand Down Expand Up @@ -56,6 +56,7 @@
"c8": "12.0.0"
},
"dependencies": {
"@iarna/toml": "2.2.5",
"graphql": "16.14.2"
},
"homepage": "https://github.com/RexCode-Digital/shopify-upgrade-guard#readme"
Expand Down
Loading
Loading