1- name : VS Code Extension - Release
1+ name : Extensions - Release
22
33on :
44 push :
1616 required : false
1717 default : true
1818 type : boolean
19+ vs_only :
20+ description : ' Build and publish only the Visual Studio extension (uses existing tag/release, skips VS Code steps)'
21+ required : false
22+ default : false
23+ type : boolean
1924
2025permissions :
2126 contents : read
@@ -126,6 +131,7 @@ jobs:
126131 echo "---"
127132
128133 - name : Update CHANGELOG.md for VSIX packaging
134+ if : inputs.vs_only != true
129135 run : |
130136 VERSION="${{ steps.extract_version.outputs.tag_version }}"
131137 node -e "
@@ -145,7 +151,7 @@ jobs:
145151 " "$VERSION"
146152
147153 - name : Create changelog branch and commit
148- if : steps.trigger_type.outputs.is_manual == 'true'
154+ if : steps.trigger_type.outputs.is_manual == 'true' && inputs.vs_only != true
149155 id : changelog_branch
150156 env :
151157 GITHUB_TOKEN : ${{ secrets.GITHUB_TOKEN }}
@@ -159,10 +165,8 @@ jobs:
159165
160166 # Check if branch already exists on remote
161167 if git ls-remote --exit-code --heads origin "refs/heads/$BRANCH" >/dev/null 2>&1; then
162- MSG="❌ Branch $BRANCH already exists on remote! Delete it or bump the version before re-running."
163- echo "$MSG"
164- echo "$MSG" > /tmp/changelog_error.txt
165- exit 1
168+ echo "ℹ️ Branch $BRANCH already exists on remote — skipping changelog commit"
169+ exit 0
166170 fi
167171
168172 if git diff --quiet vscode-extension/CHANGELOG.md; then
@@ -177,7 +181,7 @@ jobs:
177181 echo "✅ Pushed vscode-extension/CHANGELOG.md update to $BRANCH"
178182
179183 - name : Create tag for manual trigger
180- if : steps.trigger_type.outputs.is_manual == 'true' && inputs.create_tag == true
184+ if : steps.trigger_type.outputs.is_manual == 'true' && inputs.create_tag == true && inputs.vs_only != true
181185 env :
182186 GITHUB_TOKEN : ${{ secrets.GITHUB_TOKEN }}
183187 run : |
@@ -186,9 +190,8 @@ jobs:
186190
187191 # Check if tag already exists on remote using exit code
188192 if git ls-remote --exit-code --tags origin "refs/tags/$VERSION" >/dev/null 2>&1; then
189- echo "❌ Tag $VERSION already exists on remote!"
190- echo "Please update the version in package.json or delete the existing tag."
191- exit 1
193+ echo "ℹ️ Tag $VERSION already exists on remote — skipping tag creation"
194+ exit 0
192195 fi
193196
194197 # Create and push the tag
@@ -212,38 +215,47 @@ jobs:
212215 exit 1
213216
214217 - name : Install dependencies
218+ if : inputs.vs_only != true
215219 working-directory : vscode-extension
216220 run : npm ci
217221
218222 - name : Run linting
223+ if : inputs.vs_only != true
219224 working-directory : vscode-extension
220225 run : npm run lint
221226
222227 - name : Run type checking
228+ if : inputs.vs_only != true
223229 working-directory : vscode-extension
224230 run : npm run check-types
225231
226232 - name : Compile extension
233+ if : inputs.vs_only != true
227234 working-directory : vscode-extension
228235 run : npm run compile
229236
230237 - name : Build production package
238+ if : inputs.vs_only != true
231239 working-directory : vscode-extension
232240 run : npm run package
233241
234242 - name : Compile tests
243+ if : inputs.vs_only != true
235244 working-directory : vscode-extension
236245 run : npm run compile-tests
237246
238247 - name : Run tests
248+ if : inputs.vs_only != true
239249 working-directory : vscode-extension
240250 run : xvfb-run -s "-screen 0 1024x768x24" npm test
241251
242252 - name : Create VSIX package
253+ if : inputs.vs_only != true
243254 working-directory : vscode-extension
244255 run : npx vsce package
245256
246257 - name : Get VSIX filename
258+ if : inputs.vs_only != true
247259 id : vsix_filename
248260 working-directory : vscode-extension
249261 run : |
@@ -252,13 +264,15 @@ jobs:
252264 echo "VSIX file: $VSIX_FILE"
253265
254266 - name : Upload VSIX as workflow artifact
267+ if : inputs.vs_only != true
255268 uses : actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0
256269 with :
257270 name : vsix-package
258271 path : vscode-extension/${{ steps.vsix_filename.outputs.vsix_file }}
259272 retention-days : 90
260273
261274 - name : Create Release
275+ if : inputs.vs_only != true
262276 id : create_release
263277 shell : bash
264278 env :
@@ -268,17 +282,31 @@ jobs:
268282 set -o pipefail
269283 echo "Creating release for tag: ${{ steps.tag_name.outputs.tag_name }}"
270284
271- # Create release with auto-generated notes and upload VSIX file
272- gh release create "${{ steps.tag_name.outputs.tag_name }}" \
273- --title "VS Code Extension v${{ steps.extract_version.outputs.tag_version }}" \
274- --notes-file /tmp/release_notes.md \
275- vscode-extension/${{ steps.vsix_filename.outputs.vsix_file }} 2>&1 | tee /tmp/release_output.txt
285+ # Create release (skip if it already exists — e.g. re-running after a downstream job failure)
286+ TAG="${{ steps.tag_name.outputs.tag_name }}"
287+ if gh release view "$TAG" --repo "${{ github.repository }}" >/dev/null 2>&1; then
288+ echo "ℹ️ Release $TAG already exists — uploading VSIX with --clobber"
289+ gh release upload "$TAG" \
290+ vscode-extension/${{ steps.vsix_filename.outputs.vsix_file }} --clobber 2>&1 | tee /tmp/release_output.txt
291+ else
292+ gh release create "$TAG" \
293+ --title "VS Code Extension v${{ steps.extract_version.outputs.tag_version }}" \
294+ --notes-file /tmp/release_notes.md \
295+ vscode-extension/${{ steps.vsix_filename.outputs.vsix_file }} 2>&1 | tee /tmp/release_output.txt
296+ fi
276297
277298 - name : Release Summary
278299 if : always()
279300 shell : bash
280301 run : |
281- if [ "${{ steps.create_release.outcome }}" == "success" ]; then
302+ if [ "${{ steps.create_release.outcome }}" == "skipped" ]; then
303+ {
304+ echo "# ⏭️ VS Code Release Skipped (vs_only mode)"
305+ echo ""
306+ echo "Version: ${{ steps.extract_version.outputs.tag_version }}"
307+ echo "The Visual Studio extension job will build and upload to the existing release."
308+ } >> "$GITHUB_STEP_SUMMARY"
309+ elif [ "${{ steps.create_release.outcome }}" == "success" ]; then
282310 {
283311 echo "# ✅ Release Created Successfully"
284312 echo ""
@@ -311,7 +339,7 @@ jobs:
311339 publish :
312340 needs : release
313341 name : Publish VS Code Extension
314- if : github.event_name == 'workflow_dispatch' && inputs.publish_marketplace
342+ if : github.event_name == 'workflow_dispatch' && inputs.publish_marketplace && inputs.vs_only != true
315343 runs-on : ubuntu-latest
316344 permissions :
317345 contents : read
@@ -536,6 +564,44 @@ jobs:
536564
537565 # ── (Optional) Publish to VS Marketplace ──────────────────────────────
538566
567+ - name : Check Visual Studio Marketplace version
568+ if : github.event_name == 'workflow_dispatch' && inputs.publish_marketplace == true
569+ id : vs_version_check
570+ shell : pwsh
571+ run : |
572+ # Read local version from the vsixmanifest
573+ $manifestPath = "visualstudio-extension/src/CopilotTokenTracker/source.extension.vsixmanifest"
574+ [xml]$manifest = Get-Content $manifestPath
575+ $localVersion = $manifest.PackageManifest.Metadata.Identity.Version
576+ $extensionId = $manifest.PackageManifest.Metadata.Identity.Id # AIEngineeringFluency.VS.RobBos
577+ Write-Host "Local version : $localVersion"
578+ Write-Host "Extension Id : $extensionId"
579+
580+ $body = @{
581+ filters = @(@{ criteria = @(@{ filterType = 7; value = "RobBos.$extensionId" }) })
582+ flags = 512
583+ } | ConvertTo-Json -Depth 10
584+
585+ try {
586+ $r = Invoke-RestMethod -Method Post `
587+ -Uri "https://marketplace.visualstudio.com/_apis/public/gallery/extensionquery?api-version=3.0-preview.1" `
588+ -Headers @{ "Content-Type" = "application/json"; "Accept" = "application/json;api-version=3.0-preview.1" } `
589+ -Body $body
590+ $marketplaceVersion = $r.results[0].extensions[0].versions[0].version
591+ if (-not $marketplaceVersion) {
592+ Write-Host "⚠️ Extension not found on VS Marketplace — proceeding with first publish."
593+ exit 0
594+ }
595+ Write-Host "Marketplace version: $marketplaceVersion"
596+ if ($localVersion -eq $marketplaceVersion) {
597+ Write-Error "❌ Version $localVersion is already published on the Visual Studio Marketplace. Bump the version before publishing."
598+ exit 1
599+ }
600+ Write-Host "✅ Version check passed: $localVersion is newer than marketplace $marketplaceVersion"
601+ } catch {
602+ Write-Warning "⚠️ Could not query VS Marketplace — proceeding with publish. Error: $_"
603+ }
604+
539605 - name : Publish to Visual Studio Marketplace
540606 if : github.event_name == 'workflow_dispatch' && inputs.publish_marketplace == true
541607 shell : pwsh
0 commit comments