Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
96 commits
Select commit Hold shift + click to select a range
c5ac8e1
feat: add VS Code extension CI/CD infrastructure
madhur310 May 22, 2026
020ae46
test: add workflows to test vscode-extension-ci integration
madhur310 May 26, 2026
f8ef7e5
chore: update .gitignore to exclude build artifacts
madhur310 May 26, 2026
b029563
chore: remove dist/ files from git tracking
madhur310 May 26, 2026
931c627
fix: only run test workflows on manual dispatch
madhur310 May 26, 2026
584c48e
fix: move VS Code workflows to top level and enable push triggers
madhur310 May 26, 2026
16d809d
fix: replace complex test workflows with simple package test
madhur310 May 26, 2026
796aa10
fix: make package tsconfig self-contained
madhur310 May 26, 2026
bd3b60f
test: add integration test workflow for VS Code workflows
madhur310 May 26, 2026
1d47312
fix: simplify integration test workflow
madhur310 May 26, 2026
8c9abd7
fix: add push trigger to integration test workflow
madhur310 May 26, 2026
d5825ca
fix: correct path indentation in checkout action
madhur310 May 26, 2026
7d59595
fix: replace require() with ES module imports
madhur310 May 26, 2026
a6b6ae0
fix: use correct package script name
madhur310 May 26, 2026
5095df2
Fix nested workflow calls to use absolute paths
madhur310 May 26, 2026
4b3a8a9
Fix composite action references to use absolute paths
madhur310 May 26, 2026
bcf753e
Add prepare script to build package on install
madhur310 May 26, 2026
1fa3c3b
Add prepare script to root to build workspaces on install
madhur310 May 26, 2026
0854729
Use full path to CLI instead of npx
madhur310 May 26, 2026
2ae1e37
fix: try adding dist to access crop repo
madhur310 Jun 18, 2026
f77a38d
fix: remove prepare script
madhur310 Jun 18, 2026
5180a14
fix: remove prepare script
madhur310 Jun 18, 2026
7aa6624
chore: add .npmrc to skip devDependencies for git dep consumers
madhur310 Jun 18, 2026
d7602bc
fix: flattened structure
madhur310 Jun 18, 2026
6516b15
fix: remove devD
madhur310 Jun 18, 2026
e9d0549
feat: add vscode-nightly-release reusable workflow
madhur310 Jun 22, 2026
12eaaa2
fix: multi-line json
madhur310 Jun 23, 2026
793778d
feat: add configurable package-command input
madhur310 Jun 23, 2026
02fda2c
fix: compile extensions before packaging
madhur310 Jun 23, 2026
a74e99d
debug: add step to list compiled files
madhur310 Jun 23, 2026
327cc6d
fix: add vscode:bundle step to create dist files
madhur310 Jun 23, 2026
6003a7f
fix: extract bundling
madhur310 Jun 23, 2026
1f3333a
feat: make bundle command optional and check for script existence
madhur310 Jun 23, 2026
f559123
fix: array fix
madhur310 Jun 23, 2026
d9d4f74
fix: add / fix
madhur310 Jun 23, 2026
147f48d
fix: add changes
madhur310 Jun 23, 2026
45546ef
feat: add vscode-release-explicit workflow for JSON array inputs
madhur310 Jun 24, 2026
9d28b39
fix: delete code
madhur310 Jun 24, 2026
1896249
fix delete code
madhur310 Jun 25, 2026
8f3eab2
fix: delete unused code
madhur310 Jun 25, 2026
798f1a1
fix: adds service and test-env
iowillhoit Jun 6, 2025
0709330
feat: allow npm for publish and install (#142)
mshanemc Jul 23, 2025
f165f16
fix: check for vuln packages
iowillhoit Sep 9, 2025
d7e4662
chore: more supply chain attacks
iowillhoit Sep 16, 2025
19876d7
chore: dont open ctc for prereleases
iowillhoit Oct 6, 2025
448f3cd
feat: monorepo publishing
mshanemc Oct 29, 2025
9655f50
chore: publish check is pkg-aware
mshanemc Oct 29, 2025
84a1566
refactor: use npm ci, timeout flag is invalid for npm
mshanemc Oct 29, 2025
a226b8d
test: temporarily use branch
mshanemc Oct 29, 2025
d8a194a
chore: wrong config
mshanemc Oct 29, 2025
c18f4c7
chore: revert branch
mshanemc Oct 29, 2025
9e8ef9c
test: revert to do not-dry-run
mshanemc Oct 29, 2025
05d2676
chore: revert branch name
mshanemc Oct 30, 2025
ddd3197
Upload required file(s) for compliance
sfdc-ospo-bot Nov 7, 2025
acdd1c1
Upload required file(s) for compliance
jimjag Nov 10, 2025
bec37d4
feat: announce release skip
iowillhoit Feb 13, 2026
3d56962
fix: if logic
iowillhoit Feb 13, 2026
4b460cd
chore: events not on workflow_call
iowillhoit Feb 13, 2026
b9eaf4b
chore: skip red
iowillhoit Feb 13, 2026
9e266c7
chore: dont post if dependabot was skipped
iowillhoit Feb 16, 2026
c26bc9b
chore: inheriting secrets
iowillhoit Feb 25, 2026
4a3e09d
chore: define secrets
iowillhoit Feb 25, 2026
cc062d1
chore: check for slack webhook
iowillhoit Feb 25, 2026
e0f9653
fix: new check for dependabot
iowillhoit Mar 3, 2026
61fc317
chore: shell bash
iowillhoit Mar 23, 2026
d98dda3
chore: remove retry wrapper to properly set ctc value
iowillhoit Apr 15, 2026
d7ecdbf
fix: handle no-op case
soridalac May 7, 2026
cd01334
fix: remove echo and use OR
soridalac May 11, 2026
a610f80
Upload required SECURITY.md file for compliance
sfdc-ospo-bot Jun 2, 2026
8c119d2
fix: remove npm cache from CTC workflows to support pnpm/yarn repos (…
mohanraj-r Jun 8, 2026
5261337
chore: remove unused workflows and actions
madhur310 Jun 26, 2026
740a956
refactor: replace redundant vscode/npm-install-with-retries with exis…
madhur310 Jun 26, 2026
539b3b1
docs: restore original README and append VS Code workflow docs
madhur310 Jun 26, 2026
9661fbb
fix: clean up gitignore
madhur310 Jun 26, 2026
0dba560
fix: clean up gitignore
madhur310 Jun 26, 2026
227f9a6
feat: restore vscode-promote-prerelease workflow for apex-language-su…
madhur310 Jun 26, 2026
184689d
fix: inline v bump
madhur310 Jun 26, 2026
0bb5858
fix: prevent git release for dry run
madhur310 Jun 26, 2026
164d73c
fix: add nightly - pre-release workflow
madhur310 Jun 29, 2026
90ac1a0
fix: revert branch references to feature branch
madhur310 Jun 29, 2026
f8bdbda
feat: add extensions-root parameter to support non-monorepo structures
madhur310 Jun 29, 2026
992a919
feat: make VS Code workflows generic and remove hardcoded apex-specif…
madhur310 Jun 29, 2026
801805c
fix: show instead of skip
madhur310 Jun 29, 2026
34de3c2
fix: log instead of skip all workflow steps in dry-run and nightly modes
madhur310 Jun 29, 2026
b39b0eb
fix: extract manual publish and promote release
madhur310 Jun 29, 2026
6ec5d5e
fix: address PR review feedback for VS Code workflow reusability
madhur310 Jul 9, 2026
e2027f9
fix: improve workflow consistency and completeness
madhur310 Jul 9, 2026
7113487
fix: extract changed extension logic
madhur310 Jul 13, 2026
50cd51a
fix: update workflow and action references to use feat branch for tes…
madhur310 Jul 13, 2026
8a30ebb
fix: wrap top-level await in async IIFE for tsx compatibility
madhur310 Jul 13, 2026
b60967a
fix: update all workflow references from feat branch to @main
madhur310 Jul 13, 2026
44de178
fix: address critical code review issues
madhur310 Jul 13, 2026
1c42814
fix: prfb
madhur310 Jul 13, 2026
07ac225
fix: update ref for testing
madhur310 Jul 13, 2026
d5d1acb
Revert "fix: update ref for testing"
madhur310 Jul 13, 2026
de81087
Merge branch 'main' into feat/add-vscode-extension-ci
madhur310 Jul 14, 2026
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
2 changes: 1 addition & 1 deletion .github/actions/ctcOpen/action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ inputs:
description: Github token
required: true
githubTag:
description: 'The semver tag of the GitHub Release'
description: "The semver tag of the GitHub Release"
required: false
nodeVersion:
description: version of node to use. It's better to specify latest, lts/* or lts/-1 than to hardcode numbers
Expand Down
100 changes: 100 additions & 0 deletions .github/actions/vscode/check-ci-status/action.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
name: Check CI Status
description: >
Verifies that CI checks passed for a given commit SHA before promotion.
Fails if any required check did not succeed.
inputs:
commit-sha:
description: 'Commit SHA to check CI status for'
required: true
token:
description: 'GitHub token with repo read access'
required: true
required-checks:
description: >
Comma-separated list of check names that must have succeeded.
If empty, all non-skipped check-runs must have conclusion "success".
required: false
default: ''

runs:
using: composite
steps:
- name: Verify CI checks passed
shell: bash
env:
GH_TOKEN: ${{ inputs.token }}
COMMIT_SHA: ${{ inputs.commit-sha }}
REQUIRED_CHECKS: ${{ inputs.required-checks }}
REPO: ${{ github.repository }}
run: |
echo "Checking CI status for commit $COMMIT_SHA in $REPO..."
# Fetch all check-runs for the commit (paginate up to 100)
CHECK_RUNS=$(gh api \
"repos/$REPO/commits/$COMMIT_SHA/check-runs" \
--paginate \
--jq '.check_runs[] | {name: .name, status: .status, conclusion: .conclusion}' \
2>&1)
if [ -z "$CHECK_RUNS" ]; then
echo "No check-runs found for commit $COMMIT_SHA"
echo "Cannot verify CI status — failing to prevent untested promotion"
exit 1
fi
echo "Check-runs found:"
echo "$CHECK_RUNS" | jq -r '" \(.name): status=\(.status) conclusion=\(.conclusion)"'
FAILED=0
if [ -n "$REQUIRED_CHECKS" ]; then
# Only validate the specified checks
IFS=',' read -ra CHECKS <<< "$REQUIRED_CHECKS"
for CHECK in "${CHECKS[@]}"; do
CHECK=$(echo "$CHECK" | xargs) # trim whitespace
CONCLUSION=$(echo "$CHECK_RUNS" | jq -r --arg name "$CHECK" \
'select(.name == $name) | .conclusion' | head -1)
if [ "$CONCLUSION" != "success" ]; then
echo "FAIL: required check '$CHECK' has conclusion '$CONCLUSION' (expected 'success')"
FAILED=1
else
echo "PASS: required check '$CHECK' succeeded"
fi
done
else
# Validate all non-skipped check-runs
while IFS= read -r RUN; do
NAME=$(echo "$RUN" | jq -r '.name')
STATUS=$(echo "$RUN" | jq -r '.status')
CONCLUSION=$(echo "$RUN" | jq -r '.conclusion')
# Skip queued/in-progress (treat as not-yet-run, which is a failure)
if [ "$STATUS" != "completed" ]; then
echo "FAIL: check '$NAME' is not completed (status=$STATUS)"
FAILED=1
continue
fi
# Allow skipped checks (neutral conclusion)
if [ "$CONCLUSION" = "skipped" ] || [ "$CONCLUSION" = "neutral" ]; then
echo "SKIP: check '$NAME' was skipped — ignoring"
continue
fi
if [ "$CONCLUSION" != "success" ]; then
echo "FAIL: check '$NAME' has conclusion '$CONCLUSION'"
FAILED=1
fi
done < <(echo "$CHECK_RUNS" | jq -c '.')
fi
if [ "$FAILED" -eq 1 ]; then
echo ""
echo "CI quality gate FAILED for commit $COMMIT_SHA"
echo "Promotion blocked. Fix failing checks before retrying."
exit 1
fi
echo ""
echo "CI quality gate PASSED for commit $COMMIT_SHA"
147 changes: 147 additions & 0 deletions .github/actions/vscode/publish-vsix/action.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,147 @@
name: "Publish VSIX"
description: "Publishes VSIX files to a marketplace with dry-run support"

inputs:
vsix-path:
description: "Path to the VSIX file to publish"
required: true
publish-tool:
description: "Publishing tool to use"
required: true
pre-release:
description: "Publish as pre-release version"
required: false
default: "false"
dry-run:
description: "Run in dry-run mode"
required: false
default: "false"

runs:
using: composite
steps:
- name: Validate inputs
shell: bash
run: |
# Validate VSIX path exists
if [ ! -f "${{ inputs.vsix-path }}" ]; then
echo "❌ Error: VSIX file not found at ${{ inputs.vsix-path }}"
exit 1
fi

# Validate VSIX file extension
if [[ ! "${{ inputs.vsix-path }}" =~ \.vsix$ ]]; then
echo "❌ Error: File must have .vsix extension"
exit 1
fi

# Validate publish tool
if [[ ! "${{ inputs.publish-tool }}" =~ ^(ovsx|vsce)$ ]]; then
echo "❌ Error: Invalid publish tool: ${{ inputs.publish-tool }}"
exit 1
fi

echo "✅ Input validation passed"

- name: Audit publish attempt
shell: bash
run: |
# Create audit log entry
AUDIT_LOG="/tmp/publish_audit.log"
TIMESTAMP=$(date -u +"%Y-%m-%dT%H:%M:%SZ")
ACTOR="${{ github.actor }}"
REPO="${{ github.repository }}"
RUN_ID="${{ github.run_id }}"
WORKFLOW="${{ github.workflow }}"

# Get file info for audit
FILE_SIZE=$(stat -c%s "${{ inputs.vsix-path }}" 2>/dev/null || stat -f%z "${{ inputs.vsix-path }}" 2>/dev/null || echo "unknown")
FILE_HASH=$(sha256sum "${{ inputs.vsix-path }}" 2>/dev/null | cut -d' ' -f1 || echo "unknown")

# Log audit information
echo "[$TIMESTAMP] PUBLISH_ATTEMPT: actor=$ACTOR, repo=$REPO, run_id=$RUN_ID, workflow=$WORKFLOW, tool=${{ inputs.publish-tool }}, file=${{ inputs.vsix-path }}, size=$FILE_SIZE, hash=$FILE_HASH, pre_release=${{ inputs.pre-release }}, dry_run=${{ inputs.dry-run }}" >> "$AUDIT_LOG"

# Also log to GitHub Actions output for visibility
echo "🔍 AUDIT: Publish attempt logged - $TIMESTAMP"
echo " Actor: $ACTOR"
echo " Repository: $REPO"
echo " Run ID: $RUN_ID"
echo " Workflow: $WORKFLOW"
echo " Tool: ${{ inputs.publish-tool }}"
echo " File: ${{ inputs.vsix-path }}"
echo " Size: $FILE_SIZE bytes"
echo " Hash: $FILE_HASH"
echo " Pre-release: ${{ inputs.pre-release }}"
echo " Dry-run: ${{ inputs.dry-run }}"

- name: Publish VSIX
shell: bash
run: |
echo "Publishing ${{ inputs.vsix-path }}"

# Calculate marketplace name based on publish tool
if [ "${{ inputs.publish-tool }}" = "ovsx" ]; then
MARKETPLACE_NAME="Open VSX Registry"
TOKEN_ENV="OVSX_PAT"
else
MARKETPLACE_NAME="Visual Studio Marketplace"
TOKEN_ENV="VSCE_PERSONAL_ACCESS_TOKEN"
fi

PRE_RELEASE_FLAG=""
if [ "${{ inputs.pre-release }}" = "true" ]; then
PRE_RELEASE_FLAG="--pre-release"
echo "Would publish as pre-release version"
fi

# Mask token in logs for security
TOKEN_MASK="***"

if [ "${{ inputs.dry-run }}" = "true" ]; then
echo "🔍 DRY RUN MODE - Would publish to $MARKETPLACE_NAME:"
echo " VSIX: ${{ inputs.vsix-path }}"
echo " Pre-release: ${{ inputs.pre-release }}"

if [ "${{ inputs.publish-tool }}" = "ovsx" ]; then
echo " Command: npx ovsx publish \"${{ inputs.vsix-path }}\" -p $TOKEN_MASK $PRE_RELEASE_FLAG"
else
echo " Command: npx @vscode/vsce publish --packagePath \"${{ inputs.vsix-path }}\" --skip-duplicate $PRE_RELEASE_FLAG"
fi
echo "✅ Dry run completed - no actual publish performed"
else
echo "Publishing VSIX: ${{ inputs.vsix-path }}"

# Verify token is available
if [ -z "${!TOKEN_ENV}" ]; then
echo "❌ Error: $TOKEN_ENV environment variable is not set"
exit 1
fi

if [ "${{ inputs.publish-tool }}" = "vsce" ]; then
export VSCE_PAT="${!TOKEN_ENV}" # ensure the expected env var is set
npx @vscode/vsce publish --packagePath "${{ inputs.vsix-path }}" --skip-duplicate $PRE_RELEASE_FLAG
else
npx ovsx publish "${{ inputs.vsix-path }}" -p "${!TOKEN_ENV}" --skip-duplicate $PRE_RELEASE_FLAG
fi

echo "✅ Successfully published to $MARKETPLACE_NAME"
fi

- name: Audit publish result
shell: bash
if: inputs.dry-run != 'true'
run: |
# Log the result of the publish attempt
AUDIT_LOG="/tmp/publish_audit.log"
TIMESTAMP=$(date -u +"%Y-%m-%dT%H:%M:%SZ")
ACTOR="${{ github.actor }}"
REPO="${{ github.repository }}"
RUN_ID="${{ github.run_id }}"

if [ $? -eq 0 ]; then
echo "[$TIMESTAMP] PUBLISH_SUCCESS: actor=$ACTOR, repo=$REPO, run_id=$RUN_ID, tool=${{ inputs.publish-tool }}, file=${{ inputs.vsix-path }}" >> "$AUDIT_LOG"
echo "✅ AUDIT: Publish successful - $TIMESTAMP"
else
echo "[$TIMESTAMP] PUBLISH_FAILURE: actor=$ACTOR, repo=$REPO, run_id=$RUN_ID, tool=${{ inputs.publish-tool }}, file=${{ inputs.vsix-path }}" >> "$AUDIT_LOG"
echo "❌ AUDIT: Publish failed - $TIMESTAMP"
fi
79 changes: 79 additions & 0 deletions .github/scripts/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
# GitHub Workflows Scripts

This directory contains TypeScript scripts used by the reusable workflows in this repository.

## Scripts

### ext-change-detector.ts

Detects which VS Code extensions have changed since their last release and determines the appropriate version bump type.

**Features:**
- Discovers all VS Code extensions in the `packages/` directory (packages with a `publisher` field)
- Supports special values for extension selection:
- `'all'` - selects all available extensions
- `'changed'` - detects extensions with changes via git diff against per-extension tags
- `'none'` - skips all extensions
- Specific names - validates and uses the specified extensions
- Git-based change detection:
- Finds last release tag per extension (pattern: `{extension-name}-v{version}`)
- Runs `git diff {lastTag}..HEAD -- {extensionPath}`
- Returns extensions with changes since their last tag
- Conventional commit analysis for `version-bump: 'auto'`:
- Detects `BREAKING CHANGE` → major bump
- Detects `feat:` → minor bump
- Default → patch bump

**Usage in workflows:**
```yaml
- name: Detect changes and version bumps
id: changes
env:
IS_NIGHTLY: 'true'
VERSION_BUMP: 'auto'
PRE_RELEASE: 'true'
IS_PROMOTION: 'false'
SELECTED_EXTENSIONS: 'changed' # or 'all', 'none', or comma-separated names
run: |
npx tsx .github/scripts/index.ts ext-change-detector
```

**Outputs:**
- `selected-extensions` - Comma-separated list of extensions to release
- `version-bumps` - Determined version bump type (major, minor, patch)

## Dependencies

The scripts require the following npm packages:
- `simple-git` - Git operations
- `chalk` - Terminal output formatting
- `semver` - Semantic version parsing and comparison
- `zod` - Schema validation
- `tsx` - TypeScript execution

## Local Development

Install dependencies:
```bash
npm install
```

Run a script:
```bash
npm run ext-change-detector
```

Or directly with tsx:
```bash
npx tsx .github/scripts/index.ts ext-change-detector
```

## Integration with Consuming Repositories

These scripts are automatically downloaded and executed by the reusable workflows in this repository. Consuming repositories do not need to copy these scripts - they are fetched at runtime from the main branch of this repository.

The `vscode-publish-extensions.yml` workflow automatically:
1. Downloads the scripts from GitHub
2. Installs required dependencies
3. Executes the change detection
4. Uses the outputs to determine which extensions to publish
Loading