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
22 changes: 22 additions & 0 deletions .claude-plugin/marketplace.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
{
"name": "b2c-developer-tooling",
"description": "B2C Developer Tooling plugins for enhanced development workflows.",
"version": "0.0.1",
"owner": {
"name": "Salesforce Agentforce Commerce",
"email": "clavery@salesforce.com"
},
"plugins": [
{
"name": "b2c-cli",
"description": "B2C CLI Skills for Salesforce Commerce Cloud development.",
"author": {
"name": "Salesforce"
},
"license": "Apache-2.0",
"source": "./plugins/b2c-cli",
"category": "productivity",
"strict": false
}
]
}
74 changes: 74 additions & 0 deletions .github/scripts/create-preview-release.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
// @ts-check

/**
* Creates a GitHub preview release and uploads tgz assets.
*
* @param {Object} params
* @param {import('@octokit/rest').Octokit} params.github - Octokit instance
* @param {Object} params.context - GitHub Actions context
* @param {string} params.version - Version string (e.g., "0.0.1-preview.1")
* @param {string} params.distDir - Directory containing tgz files
*/
export async function createPreviewRelease({ github, context, version, distDir }) {
const fs = await import('fs');
const path = await import('path');

const tagName = `v${version}`;

const releaseBody = `## Preview Release ${tagName}

### Installation

Download both tgz files and install them together:

\`\`\`bash
npm install ./salesforce-b2c-tooling-sdk-${version}.tgz \\
./salesforce-b2c-cli-${version}.tgz
\`\`\`

Or install globally:

\`\`\`bash
npm install -g ./salesforce-b2c-tooling-sdk-${version}.tgz \\
./salesforce-b2c-cli-${version}.tgz
\`\`\`

> **Note:** Both packages must be installed together since the CLI depends on the SDK.
`;

// Create the release
const release = await github.rest.repos.createRelease({
owner: context.repo.owner,
repo: context.repo.repo,
tag_name: tagName,
name: tagName,
prerelease: true,
generate_release_notes: true,
body: releaseBody,
});

console.log(`Created release: ${release.data.html_url}`);

// Upload all tgz files from dist/
const files = fs.readdirSync(distDir).filter((f) => f.endsWith('.tgz'));

for (const file of files) {
const filePath = path.join(distDir, file);
const fileData = fs.readFileSync(filePath);

console.log(`Uploading ${file}...`);

await github.rest.repos.uploadReleaseAsset({
owner: context.repo.owner,
repo: context.repo.repo,
release_id: release.data.id,
name: file,
data: fileData,
});

console.log(`Uploaded ${file}`);
}

console.log(`Release complete: ${release.data.html_url}`);
return release.data.html_url;
}
79 changes: 79 additions & 0 deletions .github/workflows/preview-release.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
name: Preview Release

on:
push:
tags:
- 'v*-preview*'

permissions:
contents: write

jobs:
release:
runs-on: ubuntu-latest

steps:
- name: Checkout code
uses: actions/checkout@v4

- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: 22.x

- name: Setup pnpm
uses: pnpm/action-setup@v4
with:
version: 10.17.1

- name: Get pnpm store directory
shell: bash
run: |
echo "STORE_PATH=$(pnpm store path --silent)" >> $GITHUB_ENV

- name: Setup pnpm cache
uses: actions/cache@v4
with:
path: ${{ env.STORE_PATH }}
key: ${{ runner.os }}-pnpm-store-${{ hashFiles('**/pnpm-lock.yaml') }}
restore-keys: |
${{ runner.os }}-pnpm-store-

- name: Extract version from tag
run: |
VERSION=${GITHUB_REF#refs/tags/v}
echo "VERSION=$VERSION" >> $GITHUB_ENV
echo "Releasing version: $VERSION"

- name: Update package versions
run: |
pnpm -r exec -- npm pkg set version=${{ env.VERSION }}

- name: Install dependencies
run: pnpm install --frozen-lockfile

- name: Build packages
run: pnpm -r run build

- name: Run tests
run: pnpm -r run test:unit

- name: Pack all packages
run: |
mkdir -p dist
pnpm pack -r --pack-destination ./dist

- name: List packed files
run: ls -la dist/

- name: Create Release and Upload Assets
uses: actions/github-script@v7
with:
script: |
const { createPreviewRelease } = await import('${{ github.workspace }}/.github/scripts/create-preview-release.js');
await createPreviewRelease({
github,
context,
version: process.env.VERSION,
distDir: './dist'
});
41 changes: 41 additions & 0 deletions plugins/b2c-cli/skills/b2c-ods/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
---
name: b2c-ods
description: Salesforce B2C Commerce On-demand sandbox (ODS) management Skill
---

# B2C ODS Skill

Use the `b2c` CLI plugin to manage Salesforce B2C Commerce On-demand sandboxes (ODS). Only create or delete a sandbox if explicitly asked as this may be a billable or destructible action.

## Examples

### List ODS Sandboxes

```bash
b2c ods list

# for realm zzpq with JSON output
b2c ods list --realm zzpq --output json

# filter by status and those created by a specific user, only print the columns id,state,hostname
b2c ods list --filter-params 'state=started,creating&createdBy=clavery@salesforce.com' --realm zzpq --columns id,state,hostname
```

### Create ODS Sandbox

Only create a sandbox if explicitly asked as this may be a billable action.

```bash
# create in realm zzpq with 4 hour TTL (0 = infinite); json output and wait for completion (this may take 5-10 minutes; timeout is 10 minutes)
b2c ods create --realm zzpq --ttl 4 --json --wait

# create in realm zzpq with large profile (medium is default)
b2c ods create --realm zzpq --profile large

# get full log trace output to debug
b2c ods create --realm zzpq --log-level trace
```

### More Commands

See `b2c ods --help` for a full list of available commands and options in the `ods` topic.
Loading