Release - Marketplace #23
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: Release - Marketplace | |
| on: | |
| workflow_dispatch: | |
| inputs: | |
| nightly_tag: | |
| description: "Nightly tag to promote (e.g. nightly/1.2.3.456)" | |
| required: true | |
| release_title: | |
| description: "Optional GitHub Release title (default: v<version>)" | |
| required: false | |
| default: "" | |
| prerelease: | |
| description: "Create GitHub Release as prerelease?" | |
| required: false | |
| type: boolean | |
| default: false | |
| draft_release: | |
| description: "Create GitHub Release as draft?" | |
| required: false | |
| type: boolean | |
| default: true | |
| dry_run: | |
| description: "Dry run: build, stage, and optionally create draft release, but do NOT publish to Marketplace" | |
| required: false | |
| type: boolean | |
| default: false | |
| permissions: | |
| contents: write # create tag + GitHub release | |
| actions: read | |
| concurrency: | |
| group: release-marketplace | |
| cancel-in-progress: false | |
| env: | |
| CONFIGURATION: "Release" | |
| SOLUTION_PATH: "src/XrmTools.slnx" | |
| VSIX_PROJECT_DIR: "src/XrmTools/" | |
| VSIX_MANIFEST_PATH: "src/XrmTools/source.extension.vsixmanifest" | |
| VSIX_MANIFEST_SOURCE_PATH: "src/XrmTools/source.extension.cs" | |
| VSIX_STAGING_DIR: "artifacts/vsix" | |
| jobs: | |
| list_nightlies: | |
| name: List recent nightlies | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: Show latest nightly/* tags in summary | |
| uses: actions/github-script@v7 | |
| with: | |
| script: | | |
| const tags = await github.paginate(github.rest.repos.listTags, { | |
| owner: context.repo.owner, | |
| repo: context.repo.repo, | |
| per_page: 100 | |
| }); | |
| const nightly = tags | |
| .map(t => t.name) | |
| .filter(n => n.startsWith('nightly/vsix/')) | |
| .slice(0, 30); | |
| let body = `### Recent nightly tags (top ${nightly.length})\n`; | |
| body += nightly.length ? nightly.map(t => `- \`${t}\``).join('\n') : 'No nightly tags found.'; | |
| await core.summary.addRaw(body + '\n').write(); | |
| release: | |
| name: Promote nightly to Marketplace | |
| needs: list_nightlies | |
| runs-on: windows-latest | |
| environment: vs-marketplace | |
| steps: | |
| - name: Derive version from nightly tag | |
| id: derive | |
| shell: pwsh | |
| run: | | |
| $tag = "${{ inputs.nightly_tag }}".Trim() | |
| if (-not $tag.StartsWith("nightly/vsix/")) { | |
| throw "nightly_tag must start with 'nightly/vsix/'. Got: '$tag'" | |
| } | |
| $version = $tag.Substring("nightly/vsix/".Length).Trim() | |
| if ([string]::IsNullOrWhiteSpace($version)) { throw "Nightly tag has no version segment: '$tag'" } | |
| "version=$version" >> $env:GITHUB_OUTPUT | |
| "nightly_tag=$tag" >> $env:GITHUB_OUTPUT | |
| - name: Checkout nightly tag | |
| uses: actions/checkout@v4 | |
| with: | |
| ref: ${{ steps.derive.outputs.nightly_tag }} | |
| fetch-depth: 0 | |
| - name: Guard - nightly tag must exist | |
| shell: pwsh | |
| run: | | |
| git fetch --tags --force | |
| $t = "${{ steps.derive.outputs.nightly_tag }}" | |
| if (-not (git tag -l $t)) { throw "Nightly tag '$t' does not exist. Aborting." } | |
| - name: Guard - release tag must not already exist | |
| shell: pwsh | |
| run: | | |
| git fetch --tags --force | |
| $releaseTag = "vsix/${{ steps.derive.outputs.version }}" | |
| if (git tag -l $releaseTag) { | |
| throw "Release tag '$releaseTag' already exists. Refusing to publish same version twice." | |
| } | |
| - name: Setup build tooling (MSBuild + .NET) | |
| uses: timheuer/bootstrap-dotnet@v1 | |
| with: | |
| msbuild: "true" | |
| sdk: "true" | |
| nuget: "false" | |
| - name: Stamp VSIX version (exact) | |
| id: vsix_version | |
| uses: timheuer/vsix-version-stamp@v2 | |
| with: | |
| manifest-file: ${{ env.VSIX_MANIFEST_PATH }} | |
| vsix-token-source-file: ${{ env.VSIX_MANIFEST_SOURCE_PATH }} | |
| version-number: ${{ steps.derive.outputs.version }} | |
| - name: Build (after stamping) | |
| run: msbuild "${{ env.SOLUTION_PATH }}" /v:m -restore /p:Configuration=${{ env.CONFIGURATION }} | |
| - name: Stage VSIX (deterministic) | |
| id: stage_vsix | |
| shell: pwsh | |
| run: | | |
| New-Item -ItemType Directory -Force -Path "${{ env.VSIX_STAGING_DIR }}" | Out-Null | |
| $searchRoot = Join-Path $env:GITHUB_WORKSPACE "${{ env.VSIX_PROJECT_DIR }}" | |
| $files = Get-ChildItem -Path $searchRoot -Recurse -Filter *.vsix | | |
| Where-Object { $_.FullName -notmatch '\\obj\\' } | |
| if ($files.Count -eq 0) { throw "No .vsix produced under: $searchRoot" } | |
| if ($files.Count -gt 1) { | |
| $files | ForEach-Object { Write-Host $_.FullName } | |
| throw "Multiple .vsix files produced under: $searchRoot. Narrow by name if needed." | |
| } | |
| $vsix = $files[0] | |
| $dest = Join-Path $env:GITHUB_WORKSPACE "${{ env.VSIX_STAGING_DIR }}\$($vsix.Name)" | |
| Copy-Item $vsix.FullName -Destination $dest -Force | |
| "vsix=$dest" | Out-File -Append $env:GITHUB_OUTPUT | |
| Write-Host "Staged VSIX: $dest" | |
| - name: Publish to Visual Studio Marketplace | |
| if: ${{ !inputs.dry_run }} | |
| uses: cezarypiatek/VsixPublisherAction@1.0 | |
| with: | |
| extension-file: ${{ steps.stage_vsix.outputs.vsix }} | |
| publish-manifest-file: "vs-publish.json" | |
| personal-access-code: ${{ secrets.VS_PUBLISHER_ACCESS_TOKEN }} | |
| - name: Create GitHub Release (tag = vsix/<version>) | |
| uses: softprops/action-gh-release@v2 | |
| with: | |
| tag_name: vsix/${{ steps.derive.outputs.version }} | |
| name: ${{ inputs.release_title != '' && inputs.release_title || format('Xrm Tools v{0}', steps.derive.outputs.version) }} | |
| prerelease: ${{ inputs.prerelease }} | |
| draft: ${{ inputs.draft_release }} | |
| generate_release_notes: true | |
| files: ${{ steps.stage_vsix.outputs.vsix }} | |
| - name: Summary | |
| shell: pwsh | |
| run: | | |
| $nightly = "${{ steps.derive.outputs.nightly_tag }}" | |
| $version = "${{ steps.derive.outputs.version }}" | |
| "### Marketplace release published" | Out-File -Append $env:GITHUB_STEP_SUMMARY | |
| "- Nightly: **$nightly**" | Out-File -Append $env:GITHUB_STEP_SUMMARY | |
| "- Release tag: **vsix/$version**" | Out-File -Append $env:GITHUB_STEP_SUMMARY |