Skip to content
Merged
Show file tree
Hide file tree
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
39 changes: 29 additions & 10 deletions .github/workflows/build-exes.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,7 @@ name: Build Windows EXEs
on:
push:
branches:
- main
tags:
- 'v*'
- develop
pull_request:
workflow_dispatch:

Expand Down Expand Up @@ -87,8 +85,8 @@ jobs:
if-no-files-found: error

release:
name: Publish Release
if: startsWith(github.ref, 'refs/tags/v')
name: Publish Rolling Release
if: github.ref == 'refs/heads/develop'
Copy link

Copilot AI Feb 16, 2026

Choose a reason for hiding this comment

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

The condition github.ref == 'refs/heads/develop' will prevent the release job from running on pull_request and workflow_dispatch events, even when they target the develop branch. This is correct behavior for the rolling release, but consider documenting this in comments or the workflow name to make it clear that rolling releases only happen on pushes to develop, not on PRs or manual triggers. The current setup is correct, but adding a comment would improve clarity.

Copilot uses AI. Check for mistakes.
needs: build-windows-x64
runs-on: ubuntu-latest
permissions:
Expand All @@ -99,14 +97,35 @@ jobs:
uses: actions/download-artifact@v4
with:
name: fca-exes-windows-x64
path: dist/windows-x64

- name: Create Release and upload assets
- name: Remove existing rolling assets
shell: bash
run: |
if gh release view rolling --json assets -q '.assets[].name' > /tmp/rolling_assets.txt; then
cat /tmp/rolling_assets.txt | xargs -r -I {} gh release delete-asset rolling "{}" -y
Copy link

Copilot AI Feb 16, 2026

Choose a reason for hiding this comment

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

The asset cleanup step uses xargs -r which is specific to GNU xargs (commonly found on Linux). However, this workflow runs on ubuntu-latest, so this should work correctly. The -r flag prevents xargs from running the command if there is no input, which is good error handling. However, if the rolling release exists but has no assets, this will succeed silently without any output. Consider adding an echo statement to inform when assets are being deleted: cat /tmp/rolling_assets.txt | tee /dev/stderr | xargs -r -I {} gh release delete-asset rolling "{}" -y

Suggested change
cat /tmp/rolling_assets.txt | xargs -r -I {} gh release delete-asset rolling "{}" -y
cat /tmp/rolling_assets.txt | tee /dev/stderr | xargs -r -I {} gh release delete-asset rolling "{}" -y

Copilot uses AI. Check for mistakes.
else
echo "Rolling release not found yet; skipping asset cleanup."
fi
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
GH_REPO: ${{ github.repository }}
Comment on lines +102 to +112
Copy link

Copilot AI Feb 16, 2026

Choose a reason for hiding this comment

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

The asset cleanup step uses the gh CLI with GITHUB_TOKEN to delete assets. The workflow correctly specifies permissions: contents: write for the release job, which is necessary for deleting assets and creating releases. However, consider adding error handling for the case where the token doesn't have sufficient permissions, as this could lead to silent failures in the asset deletion step while the release creation succeeds.

Copilot uses AI. Check for mistakes.

- name: Create or update rolling release and upload assets
uses: softprops/action-gh-release@v2
with:
tag_name: ${{ github.ref_name }}
name: Release ${{ github.ref_name }}
tag_name: rolling
Copy link

Copilot AI Feb 16, 2026

Choose a reason for hiding this comment

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

The workflow uses 'rolling' as a tag name for the rolling release. Ensure that there is no branch or other reference named 'rolling' in the repository, as this could create conflicts. Tag names and branch names share the same namespace in git refs. If a branch named 'rolling' exists, it could cause confusion or errors in git operations.

Copilot uses AI. Check for mistakes.
name: Rolling Release
target_commitish: ${{ github.sha }}
body: |
Build from ${{ github.sha }}

${{ github.event.head_commit.message }}
Comment on lines +120 to +123
Copy link

Copilot AI Feb 16, 2026

Choose a reason for hiding this comment

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

The release body references github.event.head_commit.message which may be null or unavailable in certain contexts (e.g., when triggered via workflow_dispatch). Consider adding a fallback or checking if the commit message exists before including it in the body. Alternatively, use a more robust approach like fetching the commit message explicitly or providing a default message.

Copilot uses AI. Check for mistakes.
files: dist/windows-x64/*
generate_release_notes: true
allow_updates: true
generate_release_notes: false
overwrite_files: true
prerelease: true
make_latest: true
Copy link

Copilot AI Feb 16, 2026

Choose a reason for hiding this comment

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

Setting both prerelease: true and make_latest: true is unusual because it marks a prerelease (rolling build) as the "latest" release. This means users who download the "latest" release will get an unstable rolling build rather than the most recent stable release. While this may be intentional for providing easy access to bleeding edge builds, it could confuse users expecting "latest" to mean stable. Consider either: 1) using make_latest: 'false' and relying on the prerelease flag, or 2) documenting this behavior clearly in the repository's release documentation so users understand that "latest" refers to the rolling release.

Suggested change
make_latest: true
make_latest: false

Copilot uses AI. Check for mistakes.
fail_on_unmatched_files: true
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
135 changes: 135 additions & 0 deletions .github/workflows/manual-release.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,135 @@
name: Manual Release

on:
workflow_dispatch:
inputs:
release_tag:
description: "Release tag (e.g., v1.2.3)"
required: true
type: string
release_name:
description: "Release title"
required: true
type: string
release_notes:
description: "Release notes (optional; leave blank to auto-generate)"
required: false
type: string
prerelease:
description: "Mark this release as a prerelease"
required: true
type: boolean
default: false

jobs:
test:
name: Test (unittest + pytest)
runs-on: ubuntu-latest
timeout-minutes: 10

steps:
- name: Checkout
uses: actions/checkout@v4
with:
ref: ${{ github.ref }}
Copy link

Copilot AI Feb 16, 2026

Choose a reason for hiding this comment

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

The checkout action includes ref: ${{ github.ref }} which is redundant. The actions/checkout@v4 action already checks out the correct ref by default based on the workflow trigger. For workflow_dispatch, github.ref will be the branch or tag ref from which the workflow was manually triggered, which is the default behavior. This parameter can be safely removed to simplify the workflow configuration.

Copilot uses AI. Check for mistakes.

- name: Setup Python
uses: actions/setup-python@v5
with:
python-version: '3.12'

- name: Install dependencies
working-directory: python
run: |
python -m pip install --upgrade pip
pip install -r requirements-build.txt
pip install pytest

- name: Run unit tests
working-directory: python
run: python -m unittest discover -s tests -v

- name: Run pytest
working-directory: python
run: pytest tests/ -v

build-windows-x64:
name: Build (windows-x64)
needs: test
runs-on: windows-latest
timeout-minutes: 30

steps:
- name: Checkout
uses: actions/checkout@v4
with:
ref: ${{ github.ref }}
Copy link

Copilot AI Feb 16, 2026

Choose a reason for hiding this comment

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

The checkout action includes ref: ${{ github.ref }} which is redundant. The actions/checkout@v4 action already checks out the correct ref by default based on the workflow trigger. This parameter can be safely removed to simplify the workflow configuration.

Copilot uses AI. Check for mistakes.

- name: Setup Python
uses: actions/setup-python@v5
with:
python-version: '3.12'

- name: Install build dependencies
working-directory: python
run: |
python -m pip install --upgrade pip
python -m pip install -r requirements-build.txt

- name: Run parity smoke test
working-directory: python
run: |
python -m unittest tests.test_fca_unittest.TestFCAToolParity.test_tool_encode_decode_matches_standalone -v

- name: Ensure icon file exists
working-directory: python
run: |
if (!(Test-Path small-logo.ico)) {
python build_icon.py --input-file small-logo.png --output-file small-logo.ico
}

- name: Build executables
working-directory: python
run: |
python -m PyInstaller --clean --noconfirm --onefile --icon small-logo.ico --name fca-encode --distpath ../dist/windows-x64 fca_encode.py
python -m PyInstaller --clean --noconfirm --onefile --icon small-logo.ico --name fca-decode --distpath ../dist/windows-x64 fca_decode.py
python -m PyInstaller --clean --noconfirm --onefile --icon small-logo.ico --name fca-tool --distpath ../dist/windows-x64 fca_tool.py

- name: Upload artifacts
uses: actions/upload-artifact@v4
with:
name: fca-exes-windows-x64
path: dist/windows-x64
if-no-files-found: error

release:
name: Publish Release
needs: build-windows-x64
runs-on: ubuntu-latest
permissions:
contents: write

steps:
- name: Download windows-x64 artifacts
uses: actions/download-artifact@v4
with:
name: fca-exes-windows-x64
path: dist/windows-x64

- name: Create release and upload assets
uses: softprops/action-gh-release@v2
with:
tag_name: ${{ inputs.release_tag }}
name: ${{ inputs.release_name }}
target_commitish: ${{ github.sha }}
Comment on lines +122 to +124
Copy link

Copilot AI Feb 16, 2026

Choose a reason for hiding this comment

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

The manual release workflow creates a tag and release using target_commitish: ${{ github.sha }}, which references the commit SHA from the workflow run. For manual workflow_dispatch events, this will be the SHA of the commit at the head of the branch from which the workflow was triggered. However, there's no validation that the provided release_tag doesn't already exist. If a user provides a tag that already exists, the workflow may fail or behave unexpectedly. Consider adding a step to check if the tag exists, or document that the tag should not already exist.

Copilot uses AI. Check for mistakes.
body: ${{ inputs.release_notes }}
generate_release_notes: ${{ inputs.release_notes == '' }}
Copy link

Copilot AI Feb 16, 2026

Choose a reason for hiding this comment

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

The generate_release_notes parameter is set based on whether release_notes is an empty string. However, this check (inputs.release_notes == '') will be false if the user provides any whitespace (spaces, tabs, newlines). Consider trimming the input or using a more robust check to handle whitespace-only inputs. Alternatively, document that users should leave the field completely empty rather than entering whitespace.

Copilot uses AI. Check for mistakes.
files: dist/windows-x64/*
overwrite_files: true
make_latest: true
Copy link

Copilot AI Feb 16, 2026

Choose a reason for hiding this comment

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

The manual release workflow has make_latest: true set unconditionally. This means that when a manual release is created with prerelease: true, it will still be marked as the latest release, which conflicts with the typical expectation that prereleases should not be the "latest" release. Consider making make_latest conditional on the prerelease flag: make_latest: ${{ !inputs.prerelease }} to ensure prereleases are not marked as latest.

Suggested change
make_latest: true
make_latest: ${{ !inputs.prerelease }}

Copilot uses AI. Check for mistakes.
prerelease: ${{ inputs.prerelease }}
fail_on_unmatched_files: true
# Placeholder for custom changelog input:
# append_body: true
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
Loading