diff --git a/azure-pipelines/pre-release.yml b/azure-pipelines/pre-release.yml new file mode 100644 index 0000000..f0faf05 --- /dev/null +++ b/azure-pipelines/pre-release.yml @@ -0,0 +1,85 @@ +parameters: + - name: NpmPublishTag + displayName: 'Tag' + type: string + default: 'preview' + - name: NpmPublishDryRun + displayName: 'Dry Run' + type: boolean + default: true + +trigger: none +pr: none + +resources: + repositories: + - repository: 1es + type: git + name: 1ESPipelineTemplates/1ESPipelineTemplates + ref: refs/tags/release + +extends: + template: v1/1ES.Official.PipelineTemplate.yml@1es + parameters: + sdl: + sourceAnalysisPool: + name: 1es-pool-azfunc + image: 1es-windows-2022 + os: windows + codeql: + runSourceLanguagesInSourceAnalysis: true + pool: + name: 1es-pool-azfunc + image: 1es-windows-2022 + os: windows + + stages: + - stage: Build + jobs: + - template: /azure-pipelines/templates/build.yml@self + parameters: + # Version to be published is specified in branch + IsPrerelease: false + - stage: Release + dependsOn: Build + jobs: + - job: Release + steps: + - task: DownloadPipelineArtifact@2 + inputs: + artifact: drop + path: $(Pipeline.Workspace)/drop + displayName: 'Download artifact' + - template: /azure-pipelines/templates/npm-publish-steps.yml@self + parameters: + tgzPath: '$(Pipeline.Workspace)/drop' + NpmPublishTag: ${{ parameters.NpmPublishTag }} + NpmPublishDryRun: ${{ parameters.NpmPublishDryRun }} + - stage: GitHubTagAndRelease + dependsOn: Release + jobs: + - job: GitHubTagAndRelease + steps: + - task: DownloadPipelineArtifact@2 + inputs: + artifact: drop + path: $(Pipeline.Workspace)/drop + displayName: 'Download drop artifact' + - powershell: | + $files = Get-ChildItem "$(Pipeline.Workspace)\drop" -Filter "azure-functions-*.tgz" + if ($files.Count -ne 1) { + Write-Error "Expected one .tgz file, found $($files.Count)" + exit 1 + } + $file = $files[0].Name + if ($file -match 'azure-functions-(.+)\.tgz') { + $version = $Matches[1] + Write-Host "Parsed version: $version" + Write-Host "##vso[task.setvariable variable=version]$version" + } else { + Write-Error "Filename did not match expected pattern" + exit 1 + } + displayName: 'Extract version from .tgz filename' + - template: /azure-pipelines/templates/github-release.yml@self + diff --git a/azure-pipelines/release.yml b/azure-pipelines/release.yml index 348b254..a078616 100644 --- a/azure-pipelines/release.yml +++ b/azure-pipelines/release.yml @@ -44,22 +44,8 @@ extends: - job: Release steps: - download: officialBuild - - task: NodeTool@0 - displayName: 'Install Node.js' - inputs: - versionSpec: 18.x - - script: npm ci - displayName: 'npm ci' - - script: 'npm run validateRelease -- --publishTag ${{ parameters.NpmPublishTag }} --dropPath "$(Pipeline.Workspace)/officialBuild/drop"' - displayName: 'validate release' - - script: mv *.tgz package.tgz - displayName: 'Rename tgz file' # because the publish command below requires an exact path - workingDirectory: '$(Pipeline.Workspace)/officialBuild/drop' - - task: Npm@1 - displayName: 'npm publish' - inputs: - command: custom - workingDir: '$(Pipeline.Workspace)/officialBuild/drop' - verbose: true - customCommand: 'publish package.tgz --tag ${{ parameters.NpmPublishTag }} --dry-run ${{ lower(parameters.NpmPublishDryRun) }}' - customEndpoint: nodejs-library-npm + - template: /azure-pipelines/templates/npm-publish-steps.yml@self + parameters: + tgzPath: '$(Pipeline.Workspace)/officialBuild/drop' + NpmPublishTag: ${{ parameters.NpmPublishTag }} + NpmPublishDryRun: ${{ parameters.NpmPublishDryRun }} diff --git a/azure-pipelines/templates/github-release.yml b/azure-pipelines/templates/github-release.yml new file mode 100644 index 0000000..d0f8307 --- /dev/null +++ b/azure-pipelines/templates/github-release.yml @@ -0,0 +1,47 @@ + steps: + - powershell: | + $githubToken = "$(GithubPat)" + $newLibraryVersion = "$(version)" + Write-Host "Debug: Version from pipeline variable is '$newLibraryVersion'" + + # Create GitHub credential + git config --global user.name "AzureFunctionsNodeJS" + git config --global user.email "azfunc@microsoft.com" + + # Clone Repository + git clone https://$githubToken@github.com/Azure/azure-functions-nodejs-library + Write-Host "Cloned azure-functions-nodejs-library into local" + Set-Location "azure-functions-nodejs-library" + git checkout "origin/release/$newLibraryVersion" + + # Create release tag X.Y.Z + Write-Host "Creating release tag $newLibraryVersion" + git tag -a "$newLibraryVersion" -m "$newLibraryVersion" + + # Push tag to remote + git push origin $newLibraryVersion + + displayName: 'Create and push release tag x.y.z' + - powershell: | + $githubUser = "$(GithubUser)" + $githubToken = "$(GithubPat)" + $newLibraryVersion = "$(version)" + + # Create GitHub credential + $credential = [System.Convert]::ToBase64String([System.Text.Encoding]::ASCII.GetBytes("${githubUser}:${githubToken}")) + + # Create Release Note + Write-Host "Creating release note in GitHub" + $body = (@{tag_name="$newLibraryVersion";name="Release $newLibraryVersion";body="- Fill in Release Note Here";draft=$true} | ConvertTo-Json -Compress) + $response = Invoke-WebRequest -Headers @{"Cache-Control"="no-cache";"Content-Type"="application/json";"Authorization"="Basic $credential"} -Method Post -Body "$body" -Uri "https://api.github.com/repos/Azure/azure-functions-nodejs-library/releases" + + # Return Value + if ($response.StatusCode -ne 201) { + Write-Host "Failed to create release note in GitHub" + exit -1 + } + + $draftUrl = $response | ConvertFrom-Json | Select -expand url + Write-Host "Release draft created in $draftUrl" + + displayName: 'Create GitHub release draft' diff --git a/azure-pipelines/templates/npm-publish-steps.yml b/azure-pipelines/templates/npm-publish-steps.yml new file mode 100644 index 0000000..90bb948 --- /dev/null +++ b/azure-pipelines/templates/npm-publish-steps.yml @@ -0,0 +1,30 @@ +parameters: + tgzPath: '' + NpmPublishTag: '' + NpmPublishDryRun: false + +steps: + - task: NodeTool@0 + displayName: 'Install Node.js' + inputs: + versionSpec: 18.x + + - script: npm ci + displayName: 'npm ci' + + - script: 'npm run validateRelease -- --publishTag ${{ parameters.NpmPublishTag }} --dropPath "${{ parameters.tgzPath }}"' + displayName: 'Validate release' + name: validateReleaseStep + + - script: mv *.tgz package.tgz + displayName: 'Rename tgz file' + workingDirectory: '${{ parameters.tgzPath }}' + + - task: Npm@1 + displayName: 'npm publish' + inputs: + command: custom + workingDir: '${{ parameters.tgzPath }}' + verbose: true + customCommand: 'publish package.tgz --tag ${{ parameters.NpmPublishTag }} --dry-run ${{ lower(parameters.NpmPublishDryRun) }}' + customEndpoint: nodejs-library-npm