diff --git a/.claude-plugin/marketplace.json b/.claude-plugin/marketplace.json new file mode 100644 index 00000000..a62b81cc --- /dev/null +++ b/.claude-plugin/marketplace.json @@ -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 + } + ] +} diff --git a/.github/scripts/create-preview-release.js b/.github/scripts/create-preview-release.js new file mode 100644 index 00000000..79f36e0c --- /dev/null +++ b/.github/scripts/create-preview-release.js @@ -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; +} diff --git a/.github/workflows/preview-release.yml b/.github/workflows/preview-release.yml new file mode 100644 index 00000000..eca53762 --- /dev/null +++ b/.github/workflows/preview-release.yml @@ -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' + }); diff --git a/plugins/b2c-cli/skills/b2c-ods/SKILL.md b/plugins/b2c-cli/skills/b2c-ods/SKILL.md new file mode 100644 index 00000000..0eb06b8b --- /dev/null +++ b/plugins/b2c-cli/skills/b2c-ods/SKILL.md @@ -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.