diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 69c2da8..568db15 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -61,6 +61,23 @@ jobs: - name: Test run: ctest --test-dir "${{ env.BUILD_DIR }}" --output-on-failure + - name: Verify release tag matches project version + if: startsWith(github.ref, 'refs/tags/v') + shell: pwsh + env: + RELEASE_TAG: ${{ github.ref_name }} + run: | + $versionLine = Select-String -Path CMakeLists.txt -Pattern '^\s*VERSION\s+([0-9.]+)\s*$' | Select-Object -First 1 + if (-not $versionLine) { + throw 'Could not read the project version from CMakeLists.txt.' + } + + $projectVersion = $versionLine.Matches[0].Groups[1].Value + $tagVersion = $env:RELEASE_TAG -replace '^v', '' + if ($projectVersion -ne $tagVersion) { + throw "Tag $env:RELEASE_TAG does not match project version $projectVersion." + } + - name: Prepare Source Archive shell: pwsh run: | @@ -109,7 +126,7 @@ jobs: runs-on: ubuntu-24.04 needs: windows - if: github.repository == 'Leoncl2025/NotepadSharp' && github.event_name == 'push' && startsWith(github.ref, 'refs/tags/v') + if: github.repository == 'Leoncl2025/NotepadSharp' && startsWith(github.ref, 'refs/tags/v') && (github.event_name == 'push' || github.event_name == 'workflow_dispatch') permissions: contents: write @@ -123,11 +140,17 @@ jobs: - name: Create Draft Release and Upload Assets env: GH_TOKEN: ${{ github.token }} + GH_REPO: ${{ github.repository }} + RELEASE_TAG: ${{ github.ref_name }} run: | - if ! gh release view "${{ github.ref_name }}" >/dev/null 2>&1; then - gh release create "${{ github.ref_name }}" \ - --title "${{ github.ref_name }}" \ + if ! gh release view "${RELEASE_TAG}" >/dev/null 2>&1; then + gh release create "${RELEASE_TAG}" \ + --title "${RELEASE_TAG}" \ --generate-notes \ + --verify-tag \ --draft + elif [[ "$(gh release view "${RELEASE_TAG}" --json isDraft --jq '.isDraft')" != "true" ]]; then + echo "Refusing to replace assets on published release ${RELEASE_TAG}." >&2 + exit 1 fi - gh release upload "${{ github.ref_name }}" release-artifacts/* --clobber + gh release upload "${RELEASE_TAG}" release-artifacts/* --clobber diff --git a/.github/workflows/create_release.yml b/.github/workflows/create_release.yml index dde2380..c6b9868 100644 --- a/.github/workflows/create_release.yml +++ b/.github/workflows/create_release.yml @@ -5,38 +5,85 @@ on: workflow_dispatch: inputs: version: - description: 'New Version (do not include v)' + description: 'New numeric version greater than the current version (do not include v)' required: true + type: string + +concurrency: + group: create-release + cancel-in-progress: false jobs: release: runs-on: ubuntu-latest + permissions: + actions: write + contents: write + env: + RELEASE_VERSION: ${{ inputs.version }} steps: - name: Checkout repository uses: actions/checkout@v7 with: - token: ${{ secrets.CREATE_RELEASE_TOKEN }} + ref: main + fetch-depth: 0 + + - name: Validate release version + run: | + if [[ ! "${RELEASE_VERSION}" =~ ^[0-9]+\.[0-9]+(\.[0-9]+){0,2}$ ]]; then + echo "Version must contain two to four numeric components, for example 0.15 or 1.0.0." >&2 + exit 1 + fi + + current_version="$(sed -nE 's/^[[:space:]]*VERSION[[:space:]]+([0-9.]+).*/\1/p' CMakeLists.txt | head -n 1)" + if [[ -z "${current_version}" ]]; then + echo "Could not read the current project version from CMakeLists.txt." >&2 + exit 1 + fi + + highest_version="$(printf '%s\n%s\n' "${current_version}" "${RELEASE_VERSION}" | sort -V | tail -n 1)" + if [[ "${highest_version}" != "${RELEASE_VERSION}" || "${current_version}" == "${RELEASE_VERSION}" ]]; then + echo "Version ${RELEASE_VERSION} must be greater than current version ${current_version}." >&2 + exit 1 + fi + + if git show-ref --verify --quiet "refs/tags/v${RELEASE_VERSION}"; then + echo "Tag v${RELEASE_VERSION} already exists and must not be moved or reused." >&2 + exit 1 + fi - name: Update App Version run: | - sed -i 's/^\([[:space:]]*VERSION[[:space:]]*\).*/\1${{ github.event.inputs.version }}/' CMakeLists.txt + sed -i -E "s/^([[:space:]]*VERSION[[:space:]]+).*/\1${RELEASE_VERSION}/" CMakeLists.txt - name: Update Flatpak Version run: | - sed -i "s@@\n @" deploy/linux/io.github.leoncl2025.NotepadSharp.metainfo.xml + sed -i "s@@\n @" deploy/linux/io.github.leoncl2025.NotepadSharp.metainfo.xml + + - name: Verify release metadata + run: | + grep -Eq "^[[:space:]]*VERSION[[:space:]]+${RELEASE_VERSION}$" CMakeLists.txt + grep -Fq "