Skip to content
Open
Changes from all commits
Commits
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
254 changes: 254 additions & 0 deletions .github/workflows/release.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,254 @@
#
# Copyright (C) 2022-2025 Red Hat, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
# SPDX-License-Identifier: Apache-2.0

name: release

on:
workflow_dispatch:
inputs:
version:
description: 'Version to release'
required: true
branch:
description: 'Branch to use for the release'
required: true
default: main
Comment on lines +26 to +29
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

🌐 Web query:

GitHub Actions workflow_dispatch who can trigger it, and are repository secrets available if the workflow checks out and executes code from another branch via actions/checkout ref?

💡 Result:

Who can trigger workflow_dispatch: Users with write access to the repository can trigger it manually via the GitHub UI (Actions tab), GitHub CLI, or REST API. The workflow file must be present on the default branch. Repository secrets availability: Yes, repository secrets are available in workflow_dispatch triggered workflows, regardless of whether actions/checkout uses a different ref/branch. Secrets are provided to the runner based on the repository and trigger event, not the checked-out code/branch. The checkout with ref only changes the working directory files and git context (e.g., GITHUB_SHA), but secrets like ${{ secrets.MY_SECRET }} remain accessible throughout the job steps.

Citations:


Restrict the release branch to prevent unreviewed code from being signed and published with release secrets.

The branch input accepts free-text input (lines 26–29), which is then checked out at line 50–53. However, repository secrets (KORTEX_BOT_TOKEN, Apple notarization, Azure Key Vault, Segment key) remain available throughout the workflow regardless of which branch is checked out (lines 147–205). This means a user with write access can trigger the workflow with an arbitrary unreviewed branch and publish it using production release secrets.

Instead, hard-fail unless branch matches an explicit allow-list (e.g., main, production or a semver tag pattern), or remove the input and dispatch from a fixed release branch only.

Applies to: lines 26–29, 50–53, 147–149, 165–205

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @.github/workflows/release.yaml around lines 26 - 29, The workflow currently
accepts a free-text input named "branch" and checks it out (the checkout step),
while release secrets (e.g., KORTEX_BOT_TOKEN, Apple notarization, Azure Key
Vault, Segment key) remain available to run, allowing an attacker to trigger
releases from arbitrary branches; add an early validation step that hard-fails
unless the input "branch" matches an explicit allow-list (for example: main,
production, or a tag pattern like v* or refs/tags/v*), or remove the "branch"
input entirely and dispatch only from a fixed branch; implement this by adding a
small run step before checkout that inspects inputs.branch or github.ref and
exits non-zero if it does not match the allowed values so the job never reaches
the checkout or secret-using steps (and update any dispatch logic accordingly).

env:
GITHUB_TOKEN: ${{secrets.GITHUB_TOKEN}}
DEBUG: electron-builder

permissions:
contents: read

jobs:

tag:
name: Tagging
runs-on: ubuntu-24.04
permissions:
contents: write
outputs:
githubTag: ${{ steps.TAG_UTIL.outputs.githubTag}}
kortexVersion: ${{ steps.TAG_UTIL.outputs.kortexVersion}}
releaseId: ${{ steps.create_release.outputs.id}}

steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
ref: ${{ github.event.inputs.branch }}
token: ${{ secrets.KORTEX_BOT_TOKEN }}
- name: Generate tag utilities
id: TAG_UTIL
run: |
TAG_PATTERN=${{ github.event.inputs.version }}
echo "githubTag=v$TAG_PATTERN" >> ${GITHUB_OUTPUT}
echo "kortexVersion=$TAG_PATTERN" >> ${GITHUB_OUTPUT}

- name: tag
run: |
git config --local user.name ${{ github.actor }}
git config --local user.email "${{ github.actor_id }}+${{ github.actor }}@users.noreply.github.com"

# Add the new version in package.json file
sed -i "s#version\":\ \"\(.*\)\",#version\":\ \"${{ steps.TAG_UTIL.outputs.kortexVersion }}\",#g" package.json
find packages/* -maxdepth 1 -name "package.json" | xargs -I {} sed -i "s#version\":\ \"\(.*\)\",#version\":\ \"${{ steps.TAG_UTIL.outputs.kortexVersion }}\",#g" {}
find extensions/* -maxdepth 3 -name "package.json" | xargs -I {} sed -i "s#version\":\ \"\(.*\)\",#version\":\ \"${{ steps.TAG_UTIL.outputs.kortexVersion }}\",#g" {}
git add package.json extensions/*/package.json extensions/*/packages/*/package.json packages/*/package.json

# Update the issue template with the new version and move old version below
nextVersionLineNumber=$(grep -n "next (development version)" .github/ISSUE_TEMPLATE/bug_report.yml | cut -d ":" -f 1 | head -n 1)
currentVersionItem=$(sed "$(expr ${nextVersionLineNumber} - 1)q;d" .github/ISSUE_TEMPLATE/bug_report.yml)
newVersionItem=$(echo "$currentVersionItem" | sed -r -e "s|\".*\"|\"${{ steps.TAG_UTIL.outputs.kortexVersion }}\"|")
# delete the lines before the next version line
sed -i "$(expr ${nextVersionLineNumber} - 1)d" .github/ISSUE_TEMPLATE/bug_report.yml
# insert the version being tagged
sed -i "$(expr ${nextVersionLineNumber} - 1)i\\${newVersionItem}" .github/ISSUE_TEMPLATE/bug_report.yml
sed -i "$(expr ${nextVersionLineNumber} + 1)i\\${currentVersionItem}" .github/ISSUE_TEMPLATE/bug_report.yml
Comment on lines +73 to +80
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Fix the off-by-one when rotating the bug-report versions.

Line 74 currently reads the line above next (development version). In the current .github/ISSUE_TEMPLATE/bug_report.yml, that line is options:, so this block duplicates options: and breaks the YAML instead of moving the previous release entry.

🐛 Possible fix
-          currentVersionItem=$(sed "$(expr ${nextVersionLineNumber} - 1)q;d" .github/ISSUE_TEMPLATE/bug_report.yml)
+          currentVersionItem=$(sed "$((nextVersionLineNumber + 1))q;d" .github/ISSUE_TEMPLATE/bug_report.yml)
           newVersionItem=$(echo "$currentVersionItem" | sed -r -e "s|\".*\"|\"${{ steps.TAG_UTIL.outputs.kortexVersion }}\"|")
-          # delete the lines before the next version line
-          sed -i "$(expr ${nextVersionLineNumber} - 1)d" .github/ISSUE_TEMPLATE/bug_report.yml
-          # insert the version being tagged
-          sed -i "$(expr ${nextVersionLineNumber} - 1)i\\${newVersionItem}" .github/ISSUE_TEMPLATE/bug_report.yml
-          sed -i "$(expr ${nextVersionLineNumber} + 1)i\\${currentVersionItem}" .github/ISSUE_TEMPLATE/bug_report.yml
+          sed -i "$((nextVersionLineNumber + 1))d" .github/ISSUE_TEMPLATE/bug_report.yml
+          sed -i "${nextVersionLineNumber}i\\${newVersionItem}" .github/ISSUE_TEMPLATE/bug_report.yml
+          sed -i "$((nextVersionLineNumber + 2))i\\${currentVersionItem}" .github/ISSUE_TEMPLATE/bug_report.yml
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
nextVersionLineNumber=$(grep -n "next (development version)" .github/ISSUE_TEMPLATE/bug_report.yml | cut -d ":" -f 1 | head -n 1)
currentVersionItem=$(sed "$(expr ${nextVersionLineNumber} - 1)q;d" .github/ISSUE_TEMPLATE/bug_report.yml)
newVersionItem=$(echo "$currentVersionItem" | sed -r -e "s|\".*\"|\"${{ steps.TAG_UTIL.outputs.kortexVersion }}\"|")
# delete the lines before the next version line
sed -i "$(expr ${nextVersionLineNumber} - 1)d" .github/ISSUE_TEMPLATE/bug_report.yml
# insert the version being tagged
sed -i "$(expr ${nextVersionLineNumber} - 1)i\\${newVersionItem}" .github/ISSUE_TEMPLATE/bug_report.yml
sed -i "$(expr ${nextVersionLineNumber} + 1)i\\${currentVersionItem}" .github/ISSUE_TEMPLATE/bug_report.yml
nextVersionLineNumber=$(grep -n "next (development version)" .github/ISSUE_TEMPLATE/bug_report.yml | cut -d ":" -f 1 | head -n 1)
currentVersionItem=$(sed "$((nextVersionLineNumber + 1))q;d" .github/ISSUE_TEMPLATE/bug_report.yml)
newVersionItem=$(echo "$currentVersionItem" | sed -r -e "s|\".*\"|\"${{ steps.TAG_UTIL.outputs.kortexVersion }}\"|")
sed -i "$((nextVersionLineNumber + 1))d" .github/ISSUE_TEMPLATE/bug_report.yml
sed -i "${nextVersionLineNumber}i\\${newVersionItem}" .github/ISSUE_TEMPLATE/bug_report.yml
sed -i "$((nextVersionLineNumber + 2))i\\${currentVersionItem}" .github/ISSUE_TEMPLATE/bug_report.yml
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @.github/workflows/release.yaml around lines 73 - 80, The rotation is
off-by-one: currentVersionItem and the delete/insert positions target the line
immediately above "next (development version)" (which is `options:`) instead of
the previous release entry. Update the three places that use "$(expr
${nextVersionLineNumber} - 1)" for reading/deleting/inserting the release item
to "$(expr ${nextVersionLineNumber} - 2)" (i.e., change currentVersionItem and
the deletion/first insert to use -2), and change the final insert which
currently uses "$(expr ${nextVersionLineNumber} + 1)" to "$(expr
${nextVersionLineNumber} - 1)" so the newVersionItem and currentVersionItem end
up in the correct order; references: nextVersionLineNumber, currentVersionItem,
newVersionItem and the three sed lines.

# add the changes
git add .github/ISSUE_TEMPLATE/bug_report.yml

# Add the new version in the appdata.xml file
xmlReleasesLineNumber=$(grep -n "<releases>" .flatpak-appdata.xml | cut -d ":" -f 1 | head -n 1)
newFlatpakReleaseItem=" <release version=\"${{ steps.TAG_UTIL.outputs.kortexVersion }}\" date=\"$(date +%Y-%m-%d)\"/>"
sed -i "$(expr ${xmlReleasesLineNumber} + 1)i\\${newFlatpakReleaseItem}" .flatpak-appdata.xml
git add .flatpak-appdata.xml

# commit the changes
git commit -m "chore: 🥁 tagging ${{ steps.TAG_UTIL.outputs.githubTag }} 🥳"
echo "Tagging with ${{ steps.TAG_UTIL.outputs.githubTag }}"
git tag ${{ steps.TAG_UTIL.outputs.githubTag }}
git push origin ${{ steps.TAG_UTIL.outputs.githubTag }}
Comment on lines +91 to +94
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

If you keep non-main releases, push the release commit back to that branch.

Only the tag is pushed here. For any non-main run, the updated package.json, .flatpak-appdata.xml, and .github/ISSUE_TEMPLATE/bug_report.yml live only on the tagged commit, so the next release from that branch starts from stale metadata unless someone manually fast-forwards it.

🐛 Possible fix
           git commit -m "chore: 🥁 tagging ${{ steps.TAG_UTIL.outputs.githubTag }} 🥳"
           echo "Tagging with ${{ steps.TAG_UTIL.outputs.githubTag }}"
           git tag ${{ steps.TAG_UTIL.outputs.githubTag }}
+          if [ "${{ github.event.inputs.branch }}" != "main" ]; then
+            git push origin HEAD:${{ github.event.inputs.branch }}
+          fi
           git push origin ${{ steps.TAG_UTIL.outputs.githubTag }}
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
git commit -m "chore: 🥁 tagging ${{ steps.TAG_UTIL.outputs.githubTag }} 🥳"
echo "Tagging with ${{ steps.TAG_UTIL.outputs.githubTag }}"
git tag ${{ steps.TAG_UTIL.outputs.githubTag }}
git push origin ${{ steps.TAG_UTIL.outputs.githubTag }}
git commit -m "chore: 🥁 tagging ${{ steps.TAG_UTIL.outputs.githubTag }} 🥳"
echo "Tagging with ${{ steps.TAG_UTIL.outputs.githubTag }}"
git tag ${{ steps.TAG_UTIL.outputs.githubTag }}
if [ "${{ github.event.inputs.branch }}" != "main" ]; then
git push origin HEAD:${{ github.event.inputs.branch }}
fi
git push origin ${{ steps.TAG_UTIL.outputs.githubTag }}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @.github/workflows/release.yaml around lines 91 - 94, The workflow only
pushes the tag (git tag ...; git push origin <tag>) so the release commit never
gets pushed back to the source branch; update the step that runs git commit and
tagging to also push the commit to the branch (for example run git push origin
HEAD:${{ github.ref_name }} or git push origin HEAD:${{ github.ref }}), gated so
it doesn't push to main if you don't want that, so that updated files
(package.json, .flatpak-appdata.xml, .github/ISSUE_TEMPLATE/bug_report.yml) live
on the branch as well as the tag.

- name: Create Release
id: create_release
uses: ncipollo/release-action@339a81892b84b4eeb0f6e744e4574d79d0d9b8dd # v1.21.0
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
tag: ${{ steps.TAG_UTIL.outputs.githubTag }}
name: ${{ steps.TAG_UTIL.outputs.githubTag }}
draft: true
prerelease: true
- name: Create the PR to bump the version in the main branch (only if we're tagging from main branch)
if: ${{ github.event.inputs.branch == 'main' }}
run: |
git config --local user.name ${{ github.actor }}
git config --local user.email "${{ github.actor_id }}+${{ github.actor }}@users.noreply.github.com"
CURRENT_VERSION=$(echo "${{ steps.TAG_UTIL.outputs.kortexVersion }}")
tmp=${CURRENT_VERSION%.*}
minor=${tmp#*.}
bumpedVersion=${CURRENT_VERSION%%.*}.$((minor + 1)).0
bumpedBranchName="bump-to-${bumpedVersion}"
git checkout -b "${bumpedBranchName}"
sed -i "s#version\":\ \"\(.*\)\",#version\":\ \"${bumpedVersion}-next\",#g" package.json
find extensions/* -maxdepth 3 -name "package.json" | xargs -I {} sed -i "s#version\":\ \"\(.*\)\",#version\":\ \"${bumpedVersion}-next\",#g" {}
find packages/* -maxdepth 1 -name "package.json" | xargs -I {} sed -i "s#version\":\ \"\(.*\)\",#version\":\ \"${bumpedVersion}-next\",#g" {}
git add package.json extensions/*/package.json extensions/*/packages/*/package.json packages/*/package.json

git commit -s --amend -m "chore: bump version to ${bumpedVersion}"
git push origin "${bumpedBranchName}"
echo -e "📢 Bump version to ${bumpedVersion}\n\n${{ steps.TAG_UTIL.outputs.kortexVersion }} has been released.\n\n Time to switch to the new ${bumpedVersion} version 🥳" > /tmp/pr-title
pullRequestUrl=$(gh pr create --title "chore: 📢 Bump version to ${bumpedVersion}" --body-file /tmp/pr-title --head "${bumpedBranchName}" --base "main")
echo "📢 Pull request created: ${pullRequestUrl}"
echo "➡️ Flag the PR as being ready for review"
gh pr ready "${pullRequestUrl}"
echo "🔅 Mark the PR as being ok to be merged automatically"
gh pr merge "${pullRequestUrl}" --auto --rebase
Comment on lines +105 to +129
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Gate the version-bump PR on a successful release.

This block runs inside tag, before build and release. If a later matrix leg fails, main is already bumped and the repo metadata now references a release that never shipped. Move it to a separate post-release job that depends on release.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @.github/workflows/release.yaml around lines 105 - 129, The version-bump PR
creation currently runs inside the tag job (the step named "Create the PR to
bump the version in the main branch") which can run before downstream matrix
legs finish; move this entire script into a new post-release job (e.g.,
"post_release_bump") that has needs: release and an if condition requiring
needs.release.result == 'success' && github.event.inputs.branch == 'main' so the
bump only happens after a successful release; ensure
steps.TAG_UTIL.outputs.kortexVersion is made available to the new job (either by
calling TAG_UTIL again or by exposing the value as a workflow output) and keep
the same git/sed/gh commands and branch naming logic when copying the step into
the new job.

env:
GITHUB_TOKEN: ${{ secrets.KORTEX_BOT_TOKEN }}

build:
name: Build / ${{ matrix.os }}
needs: tag
permissions:
contents: write
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
os: [windows-2025, ubuntu-24.04, macos-15]
timeout-minutes: 60
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
ref: ${{ needs.tag.outputs.githubTag}}

- uses: pnpm/action-setup@fc06bc1257f339d1d5d8b3a19a8cae5388b55320 # v4.4.0
name: Install pnpm
with:
run_install: false

- uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v6.3.0
with:
node-version: 24
cache: 'pnpm'

- uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0
with:
python-version: "3.x"

- name: setup telemetry key for production
run: |
jq --arg key "${{ secrets.SEGMENT_WRITE_KEY }}" '.telemetry.key = $key' product.json > product.json.tmp && rm product.json && mv product.json.tmp product.json

- name: Execute pnpm
run: pnpm install

- name: Install flatpak on Linux
if: ${{ matrix.os=='ubuntu-24.04' }}
run: |
sudo apt-get update
sudo apt-get install flatpak -y
sudo apt-get install flatpak-builder -y
sudo apt-get install elfutils -y
flatpak remote-add --if-not-exists flathub --user https://flathub.org/repo/flathub.flatpakrepo
flatpak install flathub --no-static-deltas --user -y org.freedesktop.Platform//25.08 org.freedesktop.Sdk//25.08
- name: Set macOS environment variables
if: startsWith(matrix.os, 'macos')
run: |
echo "CSC_LINK=${{secrets.CSC_LINK}}" >> $GITHUB_ENV
echo "CSC_KEY_PASSWORD=${{secrets.CSC_KEY_PASSWORD}}" >> $GITHUB_ENV
echo "APPLE_ID=${{secrets.APPLE_ID}}" >> $GITHUB_ENV
echo "APPLE_APP_SPECIFIC_PASSWORD=${{secrets.APPLE_APP_SPECIFIC_PASSWORD}}" >> $GITHUB_ENV
echo "APPLE_TEAM_ID=${{secrets.APPLE_TEAM_ID}}" >> $GITHUB_ENV

- name: Install Azure SignTool on Windows
if: startsWith(matrix.os, 'windows')
run: |
dotnet tool install --global AzureSignTool --version 3.0.0
echo "AZURE_KEY_VAULT_CERTIFICATE=${{secrets.AZURE_KEY_VAULT_CERTIFICATE}}" | Out-File -FilePath $env:GITHUB_ENV -Append
echo "AZURE_KEY_VAULT_CLIENT_ID=${{secrets.AZURE_KEY_VAULT_CLIENT_ID}}" | Out-File -FilePath $env:GITHUB_ENV -Append
echo "AZURE_KEY_VAULT_SECRET=${{secrets.AZURE_KEY_VAULT_SECRET}}" | Out-File -FilePath $env:GITHUB_ENV -Append
echo "AZURE_KEY_VAULT_TENANT_ID=${{secrets.AZURE_KEY_VAULT_TENANT_ID}}" | Out-File -FilePath $env:GITHUB_ENV -Append
echo "AZURE_KEY_VAULT_URL=${{secrets.AZURE_KEY_VAULT_URL}}" | Out-File -FilePath $env:GITHUB_ENV -Append

- name: Build & Publish artifacts
timeout-minutes: 40
run: pnpm compile:next
env:
GITHUB_TOKEN: ${{ secrets.KORTEX_BOT_TOKEN }}

release:
needs: [tag, build]
name: Release
permissions:
contents: write
runs-on: ubuntu-24.04
steps:
- name: id
run: echo the release id is ${{ needs.tag.outputs.releaseId}}

- name: Publish release
uses: StuYarrow/publish-release@01f2a1365bacd77bad861873a7fdf274ab49eefd # v1.1.2
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
id: ${{ needs.tag.outputs.releaseId}}

# publish the pnpm store for flathub builds
pnpm-store:
needs: [tag, release]
name: pnpm-store-${{ matrix.arch }}
runs-on: ubuntu-24.04
permissions:
contents: write
strategy:
matrix:
arch: [amd64, arm64]

steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
ref: ${{ needs.tag.outputs.githubTag}}

- name: Set up QEMU
uses: docker/setup-qemu-action@ce360397dd3f832beb865e1373c09c0e9f86d70a # v4.0.0
- name: create the pnpm store from the dependencies
run: |
podman run --platform linux/${{ matrix.arch }} -v $(pwd):/project --rm -it --entrypoint=sh node:24 -c "cd /project && npm install -g corepack@latest && corepack enable pnpm && COREPACK_ENABLE_DOWNLOAD_PROMPT=0 pnpm install --frozen-lockfile --store-dir pnpm-store"
# now the store is in the pnpm-store directory
# create a tarball of the store
echo "Creating the archive store-cache-pnpm-${{ matrix.arch }}.tgz"
tar -czf store-cache-pnpm-${{ matrix.arch }}.tgz pnpm-store

- name: Upload binaries to release
uses: svenstaro/upload-release-action@29e53e917877a24fad85510ded594ab3c9ca12de # v2
with:
repo_token: ${{ secrets.GITHUB_TOKEN }}
file: store-cache-pnpm-${{ matrix.arch }}.tgz
tag: ${{ needs.tag.outputs.githubTag }}
Loading