Skip to content
Merged
Show file tree
Hide file tree
Changes from 36 commits
Commits
Show all changes
40 commits
Select commit Hold shift + click to select a range
09addeb
chore: add publish-providers workflow
cristiand391 Aug 26, 2025
6d79027
chore: skip code-analyzer provider
cristiand391 Aug 26, 2025
2951bec
fix: force provider-api pkg release
cristiand391 Aug 26, 2025
03c1b50
chore: manual dispach
cristiand391 Aug 26, 2025
fef2e12
chore: compact json
cristiand391 Aug 26, 2025
000991e
chore: fix version
cristiand391 Aug 26, 2025
a96331d
chore(release): mcp-provider-api@0.1.0 [skip ci]
svc-cli-bot Aug 26, 2025
3bdf7e9
chore: remove ref to provider-api alpha version
cristiand391 Aug 26, 2025
fcebe61
chore: bump in server after publishing a provider
cristiand391 Aug 26, 2025
e3f5ea5
fix: trigger initial dx provider release
cristiand391 Aug 26, 2025
c99a55e
fix: tmp skip linting
cristiand391 Aug 26, 2025
9722977
chore(release): mcp-provider-dx-core@0.1.0 [skip ci]
svc-cli-bot Aug 26, 2025
6d55b2e
chore: fix install
cristiand391 Aug 26, 2025
c457278
chore: bump provider
cristiand391 Aug 26, 2025
c2dc215
chore(release): mcp-provider-dx-core@0.1.1 [skip ci]
svc-cli-bot Aug 26, 2025
86ccc8e
chore: nuke node_modules to workaround dep issue
cristiand391 Aug 26, 2025
3ba1ede
chore(release): mcp-provider-dx-core@0.1.2 [skip ci]
svc-cli-bot Aug 26, 2025
50d7b17
chore: bump @salesforce/mcp-provider-dx-core to ^0.1.2 --no-verify
svc-cli-bot Aug 26, 2025
471fe5a
chore(release): mcp-provider-code-analyzer@0.0.1 [skip ci]
svc-cli-bot Aug 26, 2025
fbde171
chore: bump @salesforce/mcp-provider-code-analyzer to ^0.0.1 --no-verify
svc-cli-bot Aug 26, 2025
857f594
chore: publish-mcp-workflow
cristiand391 Aug 26, 2025
1a3f543
chore(release): 0.17.2-dev.0 [skip ci]
svc-cli-bot Aug 26, 2025
547eed5
chore: remove prepack script
cristiand391 Aug 26, 2025
5fccb5c
chore(release): 0.17.2-dev.1 [skip ci]
svc-cli-bot Aug 26, 2025
4358641
chore: nuke modules in publish-mcp-server workflow
cristiand391 Aug 27, 2025
43e2fef
chore(release): 0.17.2-dev.2 [skip ci]
svc-cli-bot Aug 27, 2025
c63f968
chore: skip publish-mcp if no providers were updated [skip ci]
cristiand391 Aug 27, 2025
bd58fe7
Merge remote-tracking branch 'origin/main' into cd/fix-publish-workflows
cristiand391 Aug 27, 2025
2959bb4
Update .github/workflows/publish-providers.yml
cristiand391 Aug 27, 2025
841e441
chore: move hardcoded pkgs to AUTO_PUBLISHABLE_PACKAGES arr
cristiand391 Aug 27, 2025
eeb66e4
chore: use env for npm token
cristiand391 Aug 27, 2025
166a7a9
chore: add linting script back
cristiand391 Aug 27, 2025
02ac285
chore: no caret when bumping
cristiand391 Aug 27, 2025
9ce04b9
Merge remote-tracking branch 'origin/main' into cd/fix-publish-workflows
cristiand391 Aug 27, 2025
8ec5738
chore: add release docs
cristiand391 Aug 27, 2025
b875f1e
Merge remote-tracking branch 'origin/main' into cd/fix-publish-workflows
cristiand391 Aug 27, 2025
3595f68
Update DEVELOPING.md
cristiand391 Aug 27, 2025
9efee53
Update DEVELOPING.md
cristiand391 Aug 27, 2025
c1a510b
Merge remote-tracking branch 'origin/main' into cd/fix-publish-workflows
cristiand391 Aug 28, 2025
1735e11
chore: pin provider modules
cristiand391 Aug 28, 2025
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
173 changes: 166 additions & 7 deletions .github/workflows/publish-mcp-server.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,13 +16,172 @@ on:
description: 'Name to use for the prerelease: beta, dev, etc.'

jobs:
placeholder:
update-dependencies:
if: inputs.update-providers
runs-on: ubuntu-latest
outputs:
has-updates: ${{ steps.update-deps.outputs.has-updates }}
steps:
- name: Placeholder job
- uses: actions/checkout@v4
with:
token: ${{ secrets.SVC_CLI_BOT_GITHUB_TOKEN }}

- name: Get Github user info
id: github-user-info
uses: salesforcecli/github-workflows/.github/actions/getGithubUserInfo@main
with:
SVC_CLI_BOT_GITHUB_TOKEN: ${{ secrets.SVC_CLI_BOT_GITHUB_TOKEN }}

- uses: actions/setup-node@v4
with:
node-version: 'lts/*'
cache: yarn

- name: Update provider dependencies
id: update-deps
run: |
cd packages/mcp

# Define all provider packages
ALL_PROVIDERS=("@salesforce/mcp-provider-api" "@salesforce/mcp-provider-dx-core" "@salesforce/mcp-provider-code-analyzer")

# Determine which providers to update
if [ -n "${{ inputs.providers-to-update }}" ]; then
IFS=',' read -ra PROVIDERS_TO_UPDATE <<< "${{ inputs.providers-to-update }}"
# Add @salesforce/ prefix if not present
for i in "${!PROVIDERS_TO_UPDATE[@]}"; do
if [[ "${PROVIDERS_TO_UPDATE[i]}" != @salesforce/* ]]; then
PROVIDERS_TO_UPDATE[i]="@salesforce/${PROVIDERS_TO_UPDATE[i]}"
fi
done
else
PROVIDERS_TO_UPDATE=("${ALL_PROVIDERS[@]}")
fi

HAS_UPDATES=false
UPDATED_PACKAGES=()

# Update each specified provider
for provider in "${PROVIDERS_TO_UPDATE[@]}"; do
echo "Checking for updates to $provider..."

# Get current version
CURRENT_VERSION=$(node -p "require('./package.json').dependencies['$provider']")

# Get latest version from npm
LATEST_VERSION=$(npm show "$provider" version)

if [ "$CURRENT_VERSION" != "$LATEST_VERSION" ]; then
echo "Updating $provider from $CURRENT_VERSION to $LATEST_VERSION"

# Update using jq (similar to provider workflow)
jq --arg pkg "$provider" --arg ver "$LATEST_VERSION" \
'.dependencies[$pkg] = $ver' package.json > package.json.tmp
mv package.json.tmp package.json

UPDATED_PACKAGES+=("$provider")
HAS_UPDATES=true
else
echo "$provider is already at latest version ($LATEST_VERSION)"
fi
done

echo "has-updates=$HAS_UPDATES" >> "$GITHUB_OUTPUT"

# Update lockfile and commit changes if any updates were made
if [ "$HAS_UPDATES" = true ]; then
cd ../../
# TODO(cristian): need to nuke all `node_modules` to cleanup some dep, running `yarn install` 2 times fails at the second run.
git clean -fdx
yarn install

git config user.name "${{ steps.github-user-info.outputs.username }}"
git config user.email "${{ steps.github-user-info.outputs.email }}"
git add packages/mcp/package.json yarn.lock
git commit -m "chore: update provider dependencies

Updated packages:
$(printf '%s\n' "${UPDATED_PACKAGES[@]}")"
git push
fi

publish-server:
needs: [update-dependencies]
# Skip publishing if update-providers=true but no provider updates were needed
# Logic: Run if (manual release) OR (provider updates were requested AND updates were found)
if: always() && (needs.update-dependencies.result == 'success' || needs.update-dependencies.result == 'skipped') && (!inputs.update-providers || needs.update-dependencies.outputs.has-updates == 'true')
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
token: ${{ secrets.SVC_CLI_BOT_GITHUB_TOKEN }}
fetch-depth: 0

- name: Get Github user info
id: github-user-info
uses: salesforcecli/github-workflows/.github/actions/getGithubUserInfo@main
with:
SVC_CLI_BOT_GITHUB_TOKEN: ${{ secrets.SVC_CLI_BOT_GITHUB_TOKEN }}

- uses: actions/setup-node@v4
with:
node-version: 'lts/*'
cache: yarn

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

- name: Build package
run: |
cd packages/mcp
yarn build

- name: Conventional Changelog Action
id: changelog
uses: TriPSs/conventional-changelog-action@3a392e9aa44a72686b0fc13259a90d287dd0877c
with:
git-user-name: ${{ steps.github-user-info.outputs.username }}
git-user-email: ${{ steps.github-user-info.outputs.email }}
github-token: ${{ secrets.SVC_CLI_BOT_GITHUB_TOKEN }}
tag-prefix: ""
release-count: "0"
skip-on-empty: false
git-path: "packages/mcp"
version-file: "packages/mcp/package.json"
output-file: "packages/mcp/CHANGELOG.md"
pre-release: ${{ inputs.prerelease && 'true' || 'false' }}
pre-release-identifier: ${{ inputs.prerelease || '' }}

- name: Create Github Release
id: release
uses: ncipollo/release-action@2c591bcc8ecdcd2db72b97d6147f871fcd833ba5
if: ${{ steps.changelog.outputs.skipped == 'false' }}
with:
name: "${{ steps.changelog.outputs.version }}"
tag: "${{ steps.changelog.outputs.version }}"
commit: ${{ github.sha }}
body: |
## Changes in @salesforce/mcp

${{ steps.changelog.outputs.clean_changelog }}
token: ${{ secrets.SVC_CLI_BOT_GITHUB_TOKEN }}
skipIfReleaseExists: true
prerelease: ${{ inputs.prerelease && 'true' || 'false' }}

- name: Publish to npm
if: ${{ steps.changelog.outputs.skipped == 'false' && steps.release.outputs.id != '' }}
run: |
echo "This is a placeholder workflow. The actual implementation is in feature branches."
echo "Update providers to latest: ${{ inputs.update-providers }}"
echo "Providers to update: ${{ inputs.providers-to-update }}"
echo "Prerelease tag: ${{ inputs.prerelease }}"
echo "This workflow will be replaced when the feature branch is merged to main."
cd packages/mcp
echo "//registry.npmjs.org/:_authToken=${{ secrets.NPM_TOKEN }}" > ~/.npmrc

# Determine npm dist-tag
if [ -n "${{ inputs.prerelease }}" ]; then
NPM_TAG="${{ inputs.prerelease }}"
echo "Publishing prerelease to npm tag: $NPM_TAG"
npm publish --access public --tag "$NPM_TAG"
else
echo "Publishing to latest tag"
npm publish --access public
fi
env:
NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
181 changes: 175 additions & 6 deletions .github/workflows/publish-providers.yml
Original file line number Diff line number Diff line change
@@ -1,6 +1,13 @@
name: publish-providers

on:
push:
branches:
- main
paths:
- 'packages/mcp-provider-api/**'
- 'packages/mcp-provider-dx-core/**'
# - 'packages/mcp-provider-code-analyzer/**'
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could we change this to 'packages/mcp-provider-*/**? That way new teams do not need to add new paths here

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, nevermind. Down below we have an array of packages. So instead we need to uncomment - 'packages/mcp-provider-code-analyzer/** here and then add some documentation on adding a new provider

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So instead we need to uncomment - 'packages/mcp-provider-code-analyzer/** here and then add some documentation on adding a new provider

it's commented out on purpose, the automated release is only enabled for the provider-api and dx-core modules because we own them but code-analyzer might want to have their own release cadence (manual release).

For instance, CA folks might be working on features for 2 weeks and merging stuff into main but without releasing that package, so if we need to trigger a server release during that time they are safe because @salesforce/mcp will be referring to their last published npm pkg.

workflow_dispatch:
inputs:
packages:
Expand All @@ -13,12 +20,174 @@ on:
default: true

jobs:
placeholder:
detect-changes:
runs-on: ubuntu-latest
outputs:
changed-packages: ${{ steps.detect.outputs.packages }}
has-changes: ${{ steps.detect.outputs.has-changes }}
steps:
- name: Placeholder job
- uses: actions/checkout@v4
with:
fetch-depth: 0

- name: Detect changed packages
id: detect
run: |
echo "This is a placeholder workflow. The actual implementation is in feature branches."
echo "Packages requested: ${{ inputs.packages }}"
echo "Skip on empty: ${{ inputs.skip-on-empty }}"
echo "This workflow will be replaced when the feature branch is merged to main."
# Packages that auto-publish on push to main
AUTO_PUBLISHABLE_PACKAGES=("mcp-provider-api" "mcp-provider-dx-core")

# All available provider packages
ALL_PACKAGES=("mcp-provider-api" "mcp-provider-dx-core" "mcp-provider-code-analyzer")

# Initialize packages array
PACKAGES='[]'
HAS_CHANGES=false

if [ "${{ github.event_name }}" = "workflow_dispatch" ]; then
echo "Manual workflow dispatch detected"

if [ -n "${{ inputs.packages }}" ]; then
# Parse comma-separated input
IFS=',' read -ra SPECIFIED_PACKAGES <<< "${{ inputs.packages }}"
for pkg in "${SPECIFIED_PACKAGES[@]}"; do
# Trim whitespace
pkg=$(echo "$pkg" | xargs)
# Validate package exists
if [[ " ${ALL_PACKAGES[@]} " =~ " ${pkg} " ]]; then
PACKAGES=$(echo "$PACKAGES" | jq -c --arg pkg "$pkg" '. += [$pkg]')
HAS_CHANGES=true
echo "Manual publish requested for: $pkg"
else
echo "Warning: Unknown package '$pkg' specified, skipping"
fi
done
else
# No packages specified, publish auto-publishable packages only
# code-analyzer is excluded from bulk operations and must be specified explicitly
for pkg in "${AUTO_PUBLISHABLE_PACKAGES[@]}"; do
PACKAGES=$(echo "$PACKAGES" | jq -c --arg pkg "$pkg" '. += [$pkg]')
HAS_CHANGES=true
echo "Manual publish requested for: $pkg"
done
fi
else
echo "Push event detected, checking for changed files"
# Get changed files in the last commit
CHANGED_FILES=$(git diff --name-only HEAD~1 HEAD)

# Check each provider package for changes (only auto-publish enabled packages)
for pkg in "${AUTO_PUBLISHABLE_PACKAGES[@]}"; do
if echo "$CHANGED_FILES" | grep -q "^packages/$pkg/"; then
PACKAGES=$(echo "$PACKAGES" | jq -c --arg pkg "$pkg" '. += [$pkg]')
HAS_CHANGES=true
echo "Detected changes in: $pkg"
fi
done
fi

echo "packages=$PACKAGES" >> "$GITHUB_OUTPUT"
echo "has-changes=$HAS_CHANGES" >> "$GITHUB_OUTPUT"
echo "Final packages to process: $PACKAGES"

publish-package:
needs: detect-changes
if: needs.detect-changes.outputs.has-changes == 'true'
runs-on: ubuntu-latest
strategy:
matrix:
package: ${{ fromJson(needs.detect-changes.outputs.changed-packages) }}
steps:
- uses: actions/checkout@v4
with:
token: ${{ secrets.SVC_CLI_BOT_GITHUB_TOKEN }}
fetch-depth: 0

- name: Get Github user info
id: github-user-info
uses: salesforcecli/github-workflows/.github/actions/getGithubUserInfo@main
with:
SVC_CLI_BOT_GITHUB_TOKEN: ${{ secrets.SVC_CLI_BOT_GITHUB_TOKEN }}

- uses: actions/setup-node@v4
with:
node-version: 'lts/*'
cache: yarn

- name: Install dependencies
run: yarn install --frozen-lockfile
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note for the future: We may want to use https://github.com/salesforcecli/github-workflows/blob/main/.github/actions/yarnInstallWithRetries/action.yml

We could add a --frozen-lockfile input


- name: Build package
run: |
cd packages/${{ matrix.package }}
yarn build

- name: Conventional Changelog Action
id: changelog
uses: TriPSs/conventional-changelog-action@3a392e9aa44a72686b0fc13259a90d287dd0877c
with:
git-user-name: ${{ steps.github-user-info.outputs.username }}
git-user-email: ${{ steps.github-user-info.outputs.email }}
github-token: ${{ secrets.SVC_CLI_BOT_GITHUB_TOKEN }}
tag-prefix: "${{ matrix.package }}@"
release-count: "0"
skip-on-empty: ${{ github.event_name == 'push' || inputs.skip-on-empty }}
git-path: "packages/${{ matrix.package }}"
version-file: "packages/${{ matrix.package }}/package.json"
output-file: "packages/${{ matrix.package }}/CHANGELOG.md"

- name: Create Github Release
id: release
uses: ncipollo/release-action@2c591bcc8ecdcd2db72b97d6147f871fcd833ba5
if: ${{ steps.changelog.outputs.skipped == 'false' }}
with:
name: "${{ matrix.package }}@${{ steps.changelog.outputs.version }}"
tag: "${{ matrix.package }}@${{ steps.changelog.outputs.version }}"
commit: ${{ github.sha }}
body: |
## Changes in ${{ matrix.package }}

${{ steps.changelog.outputs.clean_changelog }}
token: ${{ secrets.SVC_CLI_BOT_GITHUB_TOKEN }}
skipIfReleaseExists: true

- name: Publish to npm
if: ${{ steps.changelog.outputs.skipped == 'false' && steps.release.outputs.id != '' }}
run: |
cd packages/${{ matrix.package }}
echo "//registry.npmjs.org/:_authToken=$NPM_TOKEN" > ~/.npmrc
npm publish --access public
env:
NPM_TOKEN: ${{ secrets.NPM_TOKEN }}

- name: Update main server dependency
if: ${{ steps.changelog.outputs.skipped == 'false' && steps.release.outputs.id != '' }}
run: |
# Get the published version
PUBLISHED_VERSION="${{ steps.changelog.outputs.version }}"
PACKAGE_NAME="@salesforce/${{ matrix.package }}"

echo "Updating $PACKAGE_NAME to version $PUBLISHED_VERSION in main MCP server"

# Update the dependency in main server's package.json using jq
cd packages/mcp
jq --arg pkg "$PACKAGE_NAME" --arg ver "$PUBLISHED_VERSION" \
'.dependencies[$pkg] = $ver' package.json > package.json.tmp
mv package.json.tmp package.json
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does this mv need a -f?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nope, I see the release commits are right after this file rename.
fwiw, this is just a workaround due to a dependency issue that blocks us from doing yarn add ... (it fails due to eslint v8 and v9 issues)


# Go back to root and update yarn.lock
cd ../../
# TODO(cristian): need to nuke all `node_modules` to cleanup some dep, running `yarn install` 2 times fails at the second run.
git clean -fdx
yarn install
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note for the future: We may want to add a npx yarn-deduplicate && yarn install here


# Commit the changes
git add packages/mcp/package.json yarn.lock
git config user.name "${{ steps.github-user-info.outputs.username }}"
git config user.email "${{ steps.github-user-info.outputs.email }}"
# TODO(cristian): remove `--no-verify` after linting issues are solved
git commit -m "chore: bump $PACKAGE_NAME to $PUBLISHED_VERSION --no-verify

Auto-update dependency after provider package publish.

Related release: ${{ matrix.package }}@${{ steps.changelog.outputs.version }}"
git push
Loading
Loading