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: 2 additions & 2 deletions .changeset/config.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
"version": true,
"tag": true
},
"baseBranch": "integrations/makeswift",
"baseBranch": "integrations/b2b-makeswift",
"updateInternalDependencies": "patch",
"ignore": ["@bigcommerce/catalyst"]
"ignore": ["@bigcommerce/catalyst", "@bigcommerce/create-catalyst"]
}
22 changes: 12 additions & 10 deletions .github/scripts/prevent-invalid-changesets.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,18 +5,18 @@ module.exports = async ({ core, exec }) => {
await exec.exec("git", [
"fetch",
"https://github.com/bigcommerce/catalyst.git",
"integrations/makeswift",
"integrations/b2b-makeswift",
]);

const { stdout } = await exec.getExecOutput("git", [
"diff",
"--name-only",
`origin/integrations/makeswift...HEAD`,
`origin/integrations/b2b-makeswift...HEAD`,
]);

const allFilenames = stdout.split("\n").filter((line) => line.trim());
const changesetFilenames = allFilenames.filter(
(file) => file.startsWith(".changeset/") && file.endsWith(".md")
(file) => file.startsWith(".changeset/") && file.endsWith(".md"),
);

if (changesetFilenames.length === 0) {
Expand Down Expand Up @@ -45,8 +45,10 @@ module.exports = async ({ core, exec }) => {
}

if (!fs.existsSync(filename)) {
core.setFailed(`File not found: ${filename}`);
return;
core.warning(
`File not found: ${filename}. This is likely a version PR where the changeset was already consumed. Skipping validation for this file.`,
);
continue;
}

// check file size (limit to 100KB)
Expand Down Expand Up @@ -83,18 +85,18 @@ module.exports = async ({ core, exec }) => {

if (packageMatches) {
const invalidPackages = packageMatches.filter(
(pkg) => pkg !== '"@bigcommerce/catalyst-makeswift"'
(pkg) => pkg !== '"@bigcommerce/catalyst-b2b-makeswift"',
);

if (invalidPackages.length > 0) {
core.error(
`Invalid package found in changeset file. Only @bigcommerce/catalyst-makeswift is allowed.`,
{ file: filename }
`Invalid package found in changeset file. Only @bigcommerce/catalyst-b2b-makeswift is allowed.`,
{ file: filename },
);
core.setFailed(
`File ${filename} contains invalid packages: ${invalidPackages.join(
", "
)}`
", ",
)}`,
);
return;
}
Expand Down
58 changes: 58 additions & 0 deletions .github/scripts/sync-catalyst-version.mts
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
#!/usr/bin/env node
/* eslint-disable no-console */

import { readFileSync, writeFileSync } from "node:fs";
import { dirname, resolve } from "node:path";
import { fileURLToPath } from "node:url";

export interface CorePackageJson {
name: string;
version: string;
catalyst?: { version: string; ref: string };
[key: string]: unknown;
}

// `catalyst.version` mirrors the released version; `catalyst.ref` is the git tag
// (`@bigcommerce/catalyst-core@<version>`) the version corresponds to, consumed
// by the future `catalyst upgrade` command.
export function buildCatalystField(
pkg: Pick<CorePackageJson, "name" | "version">,
): { version: string; ref: string } {
return { version: pkg.version, ref: `${pkg.name}@${pkg.version}` };
}

// Returns the package.json text with its `catalyst` field synced to `version`.
// Re-serializes with the canonical 2-space + trailing-newline format, so a run
// where nothing changed produces no diff.
export function syncCatalystField(packageJsonText: string): string {
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
const pkg = JSON.parse(packageJsonText) as CorePackageJson;

pkg.catalyst = buildCatalystField(pkg);

return `${JSON.stringify(pkg, null, 2)}\n`;
}

function main(): void {
const corePackageJsonPath = resolve(
dirname(fileURLToPath(import.meta.url)),
"../../core/package.json",
);

const updated = syncCatalystField(readFileSync(corePackageJsonPath, "utf-8"));

writeFileSync(corePackageJsonPath, updated);

// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
const { catalyst } = JSON.parse(updated) as CorePackageJson;

console.log(
`Synced core/package.json catalyst field → ${catalyst?.version} (${catalyst?.ref})`,
);
}

const isMain = process.argv[1] === fileURLToPath(import.meta.url);

if (isMain) {
main();
}
62 changes: 61 additions & 1 deletion .github/workflows/changesets-release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,26 @@ on:
branches:
- canary
- integrations/makeswift
- integrations/b2b-makeswift

concurrency: ${{ github.workflow }}-${{ github.ref }}

permissions:
id-token: write
contents: write
packages: write
pull-requests: write

jobs:
changesets-release:
name: Changesets Release
runs-on: ubuntu-latest
steps:
- name: Checkout Repo
uses: actions/checkout@v4
with:
# Full history required for linear-release-action to scan commits.
fetch-depth: 0

- name: Setup pnpm
uses: pnpm/action-setup@v3
Expand All @@ -33,13 +43,63 @@ jobs:
env:
CLI_SEGMENT_WRITE_KEY: ${{ secrets.CLI_SEGMENT_WRITE_KEY }}

- name: Sync Linear release
uses: linear/linear-release-action@v0
with:
access_key: ${{ secrets.LINEAR_ACCESS_KEY }}
command: sync
# Only the storefront package ships as its own release; changes to
# other workspace packages (client, create-catalyst, the CLI) are
# released separately and shouldn't count toward this pipeline.
include_paths: core/**

- name: Create Release Pull Request or Publish to npm
id: changesets
uses: changesets/action@v1
with:
# Runs `changeset version`, then syncs core/package.json's `catalyst`
# field (version + git ref) to the freshly-bumped version.
version: pnpm changeset:version
publish: pnpm exec changeset publish
title: "Version Packages (`${{ github.ref_name }}`)"
commit: "Version Packages (`${{ github.ref_name }}`)"
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
NPM_TOKEN: ${{ secrets.NPM_TOKEN }}

- name: Resolve headline package
id: headline
if: steps.changesets.outputs.published == 'true'
run: |
PACKAGE_NAME="@bigcommerce/catalyst-core"
if [ "${{ github.ref_name }}" = "integrations/makeswift" ]; then
PACKAGE_NAME="@bigcommerce/catalyst-makeswift"
elif [ "${{ github.ref_name }}" = "integrations/b2b-makeswift" ]; then
PACKAGE_NAME="@bigcommerce/catalyst-b2b-makeswift"
fi
VERSION=$(echo '${{ steps.changesets.outputs.publishedPackages }}' | jq -r --arg name "$PACKAGE_NAME" '.[] | select(.name == $name) | .version')
if [ -z "$VERSION" ]; then
echo "found=false" >> "$GITHUB_OUTPUT"
else
echo "found=true" >> "$GITHUB_OUTPUT"
echo "tag=$PACKAGE_NAME@$VERSION" >> "$GITHUB_OUTPUT"
fi

- name: Fetch release notes
if: steps.headline.outputs.found == 'true'
run: gh release view "${{ steps.headline.outputs.tag }}" --json body -q .body > /tmp/release-notes.md
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}

- name: Complete Linear release
if: steps.headline.outputs.found == 'true'
uses: linear/linear-release-action@v0
with:
access_key: ${{ secrets.LINEAR_ACCESS_KEY }}
command: complete
# No `version`: the `catalyst-release` pipeline is a scheduled pipeline
# whose started release is unversioned (the accumulating `sync` steps
# above run without a version). Passing `version` makes `complete` look
# up an existing release with that exact version, which never exists and
# fails with `No release found with version "…"`. Omitting it completes
# the latest started release — the one sync has been accumulating into.
release_notes: /tmp/release-notes.md
4 changes: 2 additions & 2 deletions .github/workflows/prevent-invalid-changesets.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ name: Prevent invalid packages for Changesets
on:
pull_request:
branches:
- integrations/makeswift
- integrations/b2b-makeswift

permissions:
contents: read
Expand All @@ -19,7 +19,7 @@ jobs:
with:
fetch-depth: 0

- name: Validate changesets only target @bigcommerce/catalyst-makeswift
- name: Validate changesets only target @bigcommerce/catalyst-b2b-makeswift
uses: actions/github-script@v7
with:
script: |
Expand Down
8 changes: 4 additions & 4 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -68,11 +68,11 @@ To pull the latest code from `canary` into `integrations/makeswift`, follow the
> [!WARNING]
> There are a number of "gotchas" that you need to be aware of when merging `canary` into `integrations/makeswift`:
>
> - The `name` field in `core/package.json` should remain `@bigcommerce/catalyst-makeswift`
> - The `version` field in `core/package.json` should remain whatever the latest published `@bigcommerce/catalyst-makeswift` version was
> - The `.changeset/` directory should not include any files that reference the `"@bigcommerce/catalyst-core"` package. If these files are merged into `integrations/makeswift`, they will cause the `Changesets Release` GitHub Action in `.github/workflows/changesets-release.yml` to fail with the error: `Error: Found changeset for package @bigcommerce/catalyst-core which is not in the workspace`
> - The `name` field in `core/package.json` should remain `@bigcommerce/catalyst-b2b-makeswift`
> - The `version` field in `core/package.json` should remain whatever the latest published `@bigcommerce/catalyst-b2b-makeswift` version was
> - The `.changeset/` directory should only include files that reference the `"@bigcommerce/catalyst-b2b-makeswift"` package (not `"@bigcommerce/catalyst-core"` or `"@bigcommerce/catalyst-makeswift"`). If files referencing other packages are merged into `integrations/b2b-makeswift`, they will cause the `Changesets Release` GitHub Action in `.github/workflows/changesets-release.yml` to fail with an error like: `Error: Found changeset for package @bigcommerce/catalyst-core which is not in the workspace`
>
> _Note: A [GitHub Action is in place](.github/workflows/prevent-invalid-changesets.yml) to help prevent invalid changesets from being merged into `integrations/makeswift`. Do not merge your PR if this GitHub Action fails._
> _Note: A [GitHub Action is in place](.github/workflows/prevent-invalid-changesets.yml) to help prevent invalid changesets from being merged into `integrations/b2b-makeswift`. Do not merge your PR if this GitHub Action fails._

5. After resolving any merge conflicts, open a new PR in GitHub to merge your `{new-branch-name}` into `integrations/makeswift`. This PR should be code reviewed and approved before the next steps.

Expand Down
2 changes: 1 addition & 1 deletion core/package.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"name": "@bigcommerce/catalyst-makeswift",
"name": "@bigcommerce/catalyst-b2b-makeswift",
"description": "BigCommerce Catalyst is a Next.js starter kit for building headless BigCommerce storefronts.",
"version": "1.1.3",
"private": true,
Expand Down
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,8 @@
"build": "dotenv -e .env.local -- turbo run build",
"lint": "dotenv -e .env.local -- turbo lint",
"test": "turbo run test",
"typecheck": "turbo typecheck"
"typecheck": "turbo typecheck",
"changeset:version": "changeset version && node .github/scripts/sync-catalyst-version.mts"
},
"devDependencies": {
"@changesets/changelog-github": "^0.5.1",
Expand Down
Loading