kd_clients Preview Release #43
This file contains 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 | |
run-name: ${{ vars.PROJECT_NAME }} ${{ inputs.release-type }} Release ${{ inputs.dry-run == true && '(Dry Run)' || '' }} | |
defaults: | |
run: | |
shell: pwsh | |
on: | |
workflow_dispatch: | |
inputs: | |
release-type: | |
description: The type of release. Choose 'Preview' or 'Production'. | |
required: true | |
type: choice | |
options: [Preview, Production] | |
dry-run: | |
required: false | |
description: If true, the release will not be created. | |
default: false | |
type: boolean | |
jobs: | |
construct_infrastructure_url: | |
name: Construct Infrastructure URL | |
runs-on: ubuntu-latest | |
outputs: | |
url: ${{ steps.construct-url.outputs.base-url }} | |
steps: | |
- name: Create URL | |
id: construct-url | |
run: | | |
$trimChars = @("`n", "`r", " "); | |
$ownerName = "${{ vars.ORGANIZATION_NAME }}".ToLower().Trim($trimChars); | |
$scriptBaseUrl = "${{ vars.SCRIPT_BASE_URL }}".ToLower().Trim($trimChars); | |
$relativeScriptDirPath = "${{ vars.SCRIPT_RELATIVE_DIR_PATH }}".ToLower().Replace("\", "/"); | |
$relativeScriptDirPath = $relativeScriptDirPath.Trim($trimChars).Trim("/"); | |
$cicdScriptsVersion = "${{ vars.CICD_SCRIPTS_VERSION }}".ToLower().Trim($trimChars); | |
$fullBaseScriptUrl = "$scriptBaseUrl/$cicdScriptsVersion/$relativeScriptDirPath"; | |
if ($ownerName -eq "") { | |
Write-Host "::error::The 'OWNER_NAME' organization variable is not set."; | |
exit 1; | |
} | |
# Validate that the url is not empty | |
if ($scriptBaseUrl -eq "") { | |
Write-Host "::error::The 'SCRIPT_BASE_URL' organization variable is not set."; | |
exit 1; | |
} | |
# Validate that the URL is a basic URL | |
if ($scriptBaseUrl -notmatch "https:\/\/.+\..+") { | |
Write-Host "::error::The 'SCRIPT_BASE_URL' organization variable is not a valid URL."; | |
exit 1; | |
} | |
if ($cicdScriptsVersion -eq "") { | |
Write-Host "::error::The 'CICD_SCRIPTS_VERSION' repository variable is not set."; | |
exit 1; | |
} | |
$versionRegex = "^v([1-9]\d*|0)\.([1-9]\d*|0)\.([1-9]\d*|0)(-preview\.([1-9]\d*))?$"; | |
# Validate that the script version is a valid prod or preview version that follows semantic versioning | |
if ($cicdScriptsVersion -notmatch $versionRegex) { | |
$errorMsg = "::error::The 'CICD_SCRIPTS_VERSION' repository variable is not a valid preview or production version."; | |
$errorMsg += "`n`tThe version must match the following regex: $versionRegex"; | |
Write-Host $errorMsg; | |
exit 1; | |
} | |
Write-Host "::notice::Base Repo Script URL: $fullBaseScriptUrl"; | |
"base-url=$fullBaseScriptUrl" >> $env:GITHUB_OUTPUT; | |
get_version: | |
name: Get Version | |
runs-on: ubuntu-latest | |
outputs: | |
version: ${{ steps.get_version.outputs.version }} | |
steps: | |
- name: Setup Deno | |
uses: denoland/setup-deno@v1 | |
with: | |
deno-version: ${{ vars.DENO_VERSION }} | |
- name: Checkout Repository | |
uses: actions/checkout@v4 | |
- name: Get Version | |
id: get_version | |
run: | | |
$scriptPath = "${{ github.workspace }}/.github/cicd/scripts/get-version.ts"; | |
deno run --allow-read --allow-write --allow-env "$scriptPath"; | |
validate_release: | |
name: Validate Workflow Inputs | |
runs-on: ubuntu-latest | |
needs: get_version | |
steps: | |
- name: Validate Workflow Inputs | |
run: | | |
$branch = "${{ github.ref }}".TrimStart('refs/heads/'); | |
$expectedPrevBranch = "${{ vars.PREV_RELEASE_BRANCH }}".Trim(); | |
$expectedProdBranch = "${{ vars.PROD_RELEASE_BRANCH }}".Trim(); | |
if ($expectedPrevBranch -eq "") { | |
Write-Host "::error::The PREV_RELEASE_BRANCH variable is not set."; | |
exit 1; | |
} | |
if ($expectedProdBranch -eq "") { | |
Write-Host "::error::The PROD_RELEASE_BRANCH variable is not set."; | |
exit 1; | |
} | |
if ($branch -ne $expectedPrevBranch -and $branch -ne $expectedProdBranch) { | |
Write-Host "::error::Releases are only allowed to be run on '$expectedPrevBranch' or '$expectedProdBranch' branches."; | |
exit 1; | |
} | |
- name: Setup Deno | |
uses: denoland/setup-deno@v1 | |
with: | |
deno-version: ${{ vars.DENO_VERSION }} | |
- name: Checkout Repository | |
uses: actions/checkout@v4 | |
- name: Version Does Not Exist | |
run: | | |
$scriptPath = "${{ github.workspace }}/.github/cicd/scripts/version-checker.ts"; | |
deno run ` | |
--allow-net ` | |
--allow-read ` | |
"$scriptPath" ` | |
"${{ vars.ORGANIZATION_NAME }}" ` | |
"${{ vars.PROJECT_NAME }}" ` | |
"${{ inputs.release-type }}" ` | |
"${{ needs.get_version.outputs.version }}" ` | |
"${{ secrets.CICD_TOKEN }}"; | |
- name: Release Notes Exist | |
run: | | |
$scriptPath = "${{ github.workspace }}/.github/cicd/scripts/check-release-notes.ts"; | |
deno run ` | |
--allow-read ` | |
"$scriptPath" ` | |
"${{ inputs.release-type }}" ` | |
"${{ needs.get_version.outputs.version }}"; | |
release: | |
name: Run ${{ inputs.release-type }} Release | |
runs-on: ubuntu-latest | |
needs: [get_version, validate_release, construct_infrastructure_url] | |
steps: | |
- name: Setup Deno (${{ vars.DENO_VERSION }}) | |
uses: denoland/setup-deno@v1 | |
with: | |
deno-version: ${{ vars.DENO_VERSION }} | |
- name: Checkout Repository (${{ github.repository }}) | |
uses: actions/checkout@v4 | |
- name: Deno Check | |
id: deno-check | |
continue-on-error: true | |
run: deno run --allow-read --allow-run ./.github/cicd/scripts/deno-check.ts | |
- name: Deno Lint | |
id: deno-lint | |
continue-on-error: true | |
run: deno lint | |
- name: Deno Format | |
id: deno-format | |
continue-on-error: true | |
run: deno fmt --check | |
- name: Deno Tests | |
id: deno-tests | |
continue-on-error: true | |
run: deno test --allow-read ./tests/*Tests.ts; | |
- name: Validate Checks | |
run: | | |
$lintFailed = "${{ steps.deno-lint.outcome }}" -eq "failure"; | |
$formatFailed = "${{ steps.deno-format.outcome }}" -eq "failure"; | |
$checkFailed = "${{ steps.deno-check.outcome }}" -eq "failure"; | |
$testsFailed = "${{ steps.deno-tests.outcome }}" -eq "failure"; | |
if ($lintFailed) { | |
Write-Host "::error::The lint check has failed."; | |
} | |
if ($formatFailed) { | |
Write-Host "::error::The format has failed."; | |
} | |
if ($checkFailed) { | |
Write-Host "::error::The check has failed."; | |
} | |
if ($testsFailed) { | |
Write-Host "::error::The tests have failed."; | |
} | |
if ($lintFailed -or $formatFailed -or $checkFailed -or $testsFailed) { | |
exit "${{ inputs.dry-run }}" -eq "true" ? 0 : 1; | |
} | |
- name: Creating ${{ inputs.release-type }} GitHub Release | |
if: ${{ inputs.dry-run == false }} | |
uses: softprops/action-gh-release@v2 | |
with: | |
name: "🚀${{ inputs.release-type }} Release - ${{ needs.get_version.outputs.version }}" | |
body_path: "${{ github.workspace }}/ReleaseNotes/${{ inputs.release-type }}Releases/Release-Notes-${{ needs.get_version.outputs.version }}.md" | |
files: "${{ github.workspace }}/ReleaseNotes/${{ inputs.release-type }}Releases/Release-Notes-${{ needs.get_version.outputs.version }}.md" | |
tag_name: "${{ needs.get_version.outputs.version }}" | |
prerelease: ${{ inputs.release-type == 'Preview' }} | |
draft: false | |
- name: Close Milestone ${{ needs.get_version.outputs.version }} | |
if: ${{ inputs.dry-run == false }} | |
run: | | |
$baseScriptUrl = "${{ needs.construct_infrastructure_url.outputs.url }}"; | |
$scriptUrl = "$baseScriptUrl/close-milestone.ts"; | |
Write-Host "::notice::Close milestone script URL: $scriptUrl"; | |
<# Deno Args: | |
1. Project name | |
2. Milestone name - This is the version | |
3. PAT | |
#> | |
deno run ` | |
--allow-read --allow-net ` | |
"$scriptUrl" ` | |
"${{ vars.ORGANIZATION_NAME }}" ` | |
"${{ vars.PROJECT_NAME }}" ` | |
"${{ needs.get_version.outputs.version }}" ` | |
"${{ secrets.CICD_TOKEN }}"; | |
- name: Send X Announcement | |
if: ${{ inputs.dry-run == false }} | |
run: | | |
$baseScriptUrl = "${{ needs.construct_infrastructure_url.outputs.url }}"; | |
$scriptUrl = "$baseScriptUrl/send-release-tweet.ts"; | |
<# Deno Args: | |
1. Repo owner | |
2. Project name | |
3. Version | |
4. Twitter consumer api key | |
5. Twitter consumer api secret | |
6. Twitter access token | |
7. Twitter access token secret | |
8. PAT | |
#> | |
deno run ` | |
--allow-read --allow-net --allow-env ` | |
"$scriptUrl" ` | |
"${{ vars.ORGANIZATION_NAME }}" ` | |
"${{ vars.PROJECT_NAME }}" ` | |
"${{ needs.get_version.outputs.version }}" ` | |
"${{ secrets.TWITTER_CONSUMER_API_KEY }}" ` | |
"${{ secrets.TWITTER_CONSUMER_API_SECRET }}" ` | |
"${{ secrets.TWITTER_ACCESS_TOKEN }}" ` | |
"${{ secrets.TWITTER_ACCESS_TOKEN_SECRET }}" ` | |
"${{ secrets.CICD_TOKEN }}"; |