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
2 changes: 1 addition & 1 deletion .github/workflows/codeql-analysis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ jobs:
- name: Initialize CodeQL
uses: github/codeql-action/init@v4
with:
languages: python
languages: python, actions

- name: Set up Python
uses: actions/setup-python@v6
Expand Down
125 changes: 40 additions & 85 deletions .github/workflows/release-homebrew.yml
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
---
name: Update Homebrew Formula

on:
"on":
release:
types: [published]
workflow_dispatch:
inputs:
version:
description: "Version to update (e.g., v0.6.5)"
description: "Version to update (e.g., v0.9.0)"
required: true
type: string

Expand All @@ -15,19 +16,20 @@ permissions:

env:
HOMEBREW_NO_AUTO_UPDATE: 1
TAP_REPO: docdyhr/homebrew-tap
FORMULA_PATH: Formula/macversiontracker.rb

jobs:
update-homebrew:
name: Update Homebrew Tap
runs-on: macos-latest
permissions:
contents: read
Comment on lines +26 to +27

Choose a reason for hiding this comment

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

P1 Badge Give the release job a writable token before git push

In .github/workflows/release-homebrew.yml, this job is configured with permissions: contents: read but later commits and runs git push origin main to update the tap, so the push path cannot succeed during release/dispatch runs using secrets.GITHUB_TOKEN. As written, the automation will stop at the final push step and never publish formula updates unless the workflow uses a token with write access for that repository.

Useful? React with 👍 / 👎.

if: startsWith(github.ref, 'refs/tags/v') || github.event_name == 'workflow_dispatch'

steps:
- name: Checkout repository
uses: actions/checkout@v6

- name: Set up environment
run: |
# Set version from tag or manual input
if [ "${{ github.event_name }}" = "workflow_dispatch" ]; then
VERSION="${{ github.event.inputs.version }}"
else
Expand All @@ -38,105 +40,58 @@ jobs:

- name: Download release tarball and calculate SHA256
run: |
# Download the source tarball for this release
curl -L -o versiontracker-${VERSION_NUMBER}.tar.gz \
curl -fSL -o release.tar.gz \
"https://github.com/docdyhr/versiontracker/archive/refs/tags/${VERSION}.tar.gz"

# Calculate SHA256 checksum
SHA256=$(shasum -a 256 versiontracker-${VERSION_NUMBER}.tar.gz | cut -d' ' -f1)
SHA256=$(shasum -a 256 release.tar.gz | cut -d' ' -f1)
echo "SHA256=${SHA256}" >> $GITHUB_ENV
echo "Tarball SHA256: ${SHA256}"

# Verify the download
ls -la versiontracker-${VERSION_NUMBER}.tar.gz
echo "Calculated SHA256: ${SHA256}"
- name: Clone tap repository
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
gh repo clone "${TAP_REPO}" homebrew-tap
cd homebrew-tap
echo "Current formula:"
head -10 "${FORMULA_PATH}"

- name: Update Homebrew formula
- name: Update formula version and checksum
run: |
set -euo pipefail
# Update the version URL line and sha256 in the formula deterministically
cd homebrew-tap
awk -v ver="${VERSION}" -v sha="${SHA256}" '
BEGIN{updated_url=0; updated_sha=0}
/archive\/refs\/tags\/v[0-9]+\.[0-9]+\.[0-9]+\.tar\.gz/ {
sub(/v[0-9]+\.[0-9]+\.[0-9]+/, ver)
updated_url=1
}
/sha256 "/ {
/^ sha256 "/ {
sub(/"[0-9a-f]+"/, "\"" sha "\"")
updated_sha=1
}
{ print }
END{
if (!updated_url) { exit 2 }
if (!updated_sha) { exit 3 }
}
' versiontracker.rb > versiontracker.rb.tmp
mv versiontracker.rb.tmp versiontracker.rb

echo "Updated formula preview:"
sed -n '1,20p' versiontracker.rb
' "${FORMULA_PATH}" > formula.tmp
mv formula.tmp "${FORMULA_PATH}"
Copy link
Contributor

Choose a reason for hiding this comment

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

suggestion (bug_risk): The awk update no longer validates that the URL and sha256 lines were actually updated, which can silently leave the formula stale.

Previously, the script tracked updated_url/updated_sha and exited non-zero if either wasn’t changed, so regex/format issues surfaced as failures. The new awk version always exits 0, even if nothing matched. Please add an END check (or similar guard) so we fail when no URL or sha256 was updated, avoiding silently stale or partially updated formulas.

echo "Updated formula:"
head -10 "${FORMULA_PATH}"

- name: Install and test formula
- name: Test formula installation
run: |
# Install from the local formula
brew install --build-from-source ./versiontracker.rb

# Test the installation
cd homebrew-tap
brew install --build-from-source "./${FORMULA_PATH}"
versiontracker --help
versiontracker --version
brew uninstall macversiontracker || true

# Test core functionality
echo "Testing core functionality..."
timeout 30s versiontracker list || echo "List command completed"

- name: Clean up test installation
run: |
brew uninstall versiontracker || true

- name: Commit and open PR
- name: Push updated formula to tap
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
set -euo pipefail
git config --local user.email "action@github.com"
git config --local user.name "GitHub Action"

if git diff --quiet versiontracker.rb; then
echo "No changes to commit"
cd homebrew-tap
if git diff --quiet "${FORMULA_PATH}"; then
echo "Formula already up to date"
exit 0
fi

BRANCH="homebrew/update-${VERSION}"
git checkout -b "$BRANCH"
git add versiontracker.rb
git commit -m "Update Homebrew formula to ${VERSION}\n\n- Updated URL to ${VERSION}\n- Updated SHA256 to ${SHA256}\n- Verified installation and CLI availability"
git push -u origin "$BRANCH"
gh pr create --fill --base master --head "$BRANCH" || echo "PR creation skipped (gh not available)"

- name: Create or update release notes
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
# Add Homebrew installation instructions to release notes if this is a new release
if [ "${{ github.event_name }}" = "release" ]; then
echo "
## Homebrew Installation

This version is now available via Homebrew:

\`\`\`bash
brew tap thomas/versiontracker
brew install versiontracker
\`\`\`

### Installation Verification

\`\`\`bash
versiontracker --version
versiontracker --help
\`\`\`

The formula has been tested and verified to work correctly." > homebrew_notes.md

# Note: In a real implementation, you would append this to the release notes
echo "Homebrew installation notes prepared for release ${VERSION}"
fi
git config user.email "action@github.com"
git config user.name "GitHub Action"
git add "${FORMULA_PATH}"
git commit -m "Update macversiontracker to ${VERSION}"
git push origin main
echo "Tap updated to ${VERSION}"
46 changes: 22 additions & 24 deletions TODO.md
Original file line number Diff line number Diff line change
@@ -1,20 +1,30 @@
# VersionTracker TODO

## Current Status (February 2026)
## Current Status (March 2026)

### Project Health

- **Version**: 0.9.0
- **Tests**: 1,962+ passing, 16 skipped
- **Coverage**: ~78% overall (up from 61%)
- **CI/CD**: All 11 workflows passing on master (all green)
- **Tests**: 1,993 collected, 16 skipped
- **Coverage**: ~78% overall
- **CI/CD**: All workflows passing on master (all green)
- **Python Support**: 3.12+ (with 3.13 compatibility)
- **Security**: 0 dependabot alerts, 0 secret scanning alerts; CodeQL alerts resolved
- **Security**: 0 dependabot alerts, 0 secret scanning alerts, 0 CodeQL findings
- **Linting**: ruff clean, mypy clean
- **Open Issues**: 0
- **Open PRs**: 0

### Recent Completions (v0.9.0)
### Recent Completions

- ~~PR #108~~ **CodeQL security fixes** — 3 high-severity URL sanitization
alerts resolved in `verify_badges.py` (strict scheme+hostname allowlist);
12 medium-severity missing-workflow-permissions alerts resolved across
`ci.yml`, `lint.yml`, `performance.yml`, `release.yml`, `security.yml`
(job-level `permissions:` blocks added to all jobs)
- ~~PR #106~~ **Dependency update** — `actions/upload-artifact` v6→v7,
`actions/download-artifact` v7→v8 across all workflows

### Previous Completions (v0.9.0)

- ~~P10~~ **Async Homebrew wiring** — `check_brew_install_candidates()` and
`check_brew_update_candidates()` now route through async Homebrew API by
Expand Down Expand Up @@ -51,26 +61,14 @@ All skips are environment-specific or CI-specific — no action needed for most.

---

## Homebrew Release Preparation (v0.9.0)

### Phase 1: Pre-Release Validation
## Homebrew Release (v0.9.0) — Complete

- [x] Bump version to 0.9.0 in `__init__.py` and `pyproject.toml`
- [x] Update CHANGELOG.md with v0.9.0 entry
- [ ] Run full test suite locally: `pytest`
- [ ] Validate packaging: `python -m build && twine check dist/*`

### Phase 2: Formula Creation

- [ ] Download canonical GitHub tag archive
- [ ] Compute SHA256 checksum
- [ ] Update `versiontracker.rb` formula with new version/checksum
- [ ] Run: `brew audit --new-formula --strict ./versiontracker.rb`

### Phase 3: Tap Repository

- [ ] Update `homebrew-versiontracker` repository
- [ ] Test tap: `brew tap docdyhr/versiontracker && brew install versiontracker`
- [x] Formula created at `docdyhr/homebrew-tap` with verified SHA256
- [x] `brew install docdyhr/tap/macversiontracker` tested and working
- [x] Legacy root `versiontracker.rb` removed (superseded by tap formula)
- [x] `release-homebrew.yml` workflow updated to push to tap repo

---

Expand Down Expand Up @@ -127,5 +125,5 @@ For detailed strategic planning see `docs/future_roadmap.md`.

---

**Last Updated**: February 2026
**Last Updated**: March 2026
**Maintainer**: @docdyhr
Loading
Loading