Skip to content

fix: remove site.yml workflow and fix cargo fmt #56

fix: remove site.yml workflow and fix cargo fmt

fix: remove site.yml workflow and fix cargo fmt #56

Workflow file for this run

name: Release
on:
push:
branches:
- "main"
tags:
- "v*"
workflow_dispatch:
permissions:
contents: write
env:
CARGO_TERM_COLOR: always
HOMEBREW_TAP_REPO: hanbu97/homebrew-tap
jobs:
prepare-release:
name: Prepare release context
runs-on: ubuntu-latest
outputs:
should_release: ${{ steps.rel.outputs.should_release }}
release_tag: ${{ steps.rel.outputs.release_tag }}
release_version: ${{ steps.rel.outputs.release_version }}
steps:
- name: Checkout
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Determine release version/tag
id: rel
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
set -euxo pipefail
cargo_version=$(grep -E '^version[[:space:]]*=[[:space:]]*\"' Cargo.toml | head -n1 | cut -d'"' -f2)
tag="v${cargo_version}"
should_release=false
if [[ "${GITHUB_REF}" == refs/tags/v* ]]; then
test "${GITHUB_REF_NAME}" = "${tag}"
should_release=true
elif [[ "${GITHUB_REF}" == "refs/heads/main" ]]; then
if git ls-remote --tags origin "refs/tags/${tag}" | grep -q "refs/tags/${tag}$"; then
# If the tag exists but no GitHub release exists yet, continue publishing.
# This can happen when the tag was created by GITHUB_TOKEN in a workflow run.
if curl -sfL \
-H "Authorization: Bearer ${GITHUB_TOKEN}" \
-H "Accept: application/vnd.github+json" \
"https://api.github.com/repos/${GITHUB_REPOSITORY}/releases/tags/${tag}" >/dev/null; then
should_release=false
else
should_release=true
fi
else
git config user.name "github-actions[bot]"
git config user.email "github-actions[bot]@users.noreply.github.com"
git tag "${tag}"
git push origin "refs/tags/${tag}"
# Continue publishing in this run; tag push via GITHUB_TOKEN won't retrigger workflows.
should_release=true
fi
fi
echo "should_release=${should_release}" >> "${GITHUB_OUTPUT}"
echo "release_tag=${tag}" >> "${GITHUB_OUTPUT}"
echo "release_version=${cargo_version}" >> "${GITHUB_OUTPUT}"
build:
name: Build (${{ matrix.target }})
needs: prepare-release
if: needs.prepare-release.outputs.should_release == 'true'
strategy:
fail-fast: false
matrix:
include:
- os: ubuntu-latest
target: x86_64-unknown-linux-gnu
# Build both macOS targets on macos-14 to avoid flaky macos-13 runner availability.
- os: macos-14
target: x86_64-apple-darwin
- os: macos-14
target: aarch64-apple-darwin
- os: windows-latest
target: x86_64-pc-windows-msvc
runs-on: ${{ matrix.os }}
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Install Rust toolchain
uses: dtolnay/rust-toolchain@stable
with:
targets: ${{ matrix.target }}
- name: Cache Rust build
uses: Swatinem/rust-cache@v2
- name: Build release binary
run: cargo build --release --target ${{ matrix.target }} --bin tu
- name: Package archive (Unix)
if: runner.os != 'Windows'
env:
RELEASE_TAG: ${{ needs.prepare-release.outputs.release_tag }}
run: |
set -euxo pipefail
ASSET_NAME="tu-${RELEASE_TAG}-${{ matrix.target }}"
mkdir -p "dist/${ASSET_NAME}"
cp "target/${{ matrix.target }}/release/tu" "dist/${ASSET_NAME}/"
cp README.md LICENSE "dist/${ASSET_NAME}/"
tar -C dist -czf "dist/${ASSET_NAME}.tar.gz" "${ASSET_NAME}"
cp "target/${{ matrix.target }}/release/tu" "dist/${ASSET_NAME}"
chmod +x "dist/${ASSET_NAME}"
rm -rf "dist/${ASSET_NAME}"
- name: Package archive (Windows)
if: runner.os == 'Windows'
shell: pwsh
env:
RELEASE_TAG: ${{ needs.prepare-release.outputs.release_tag }}
run: |
$assetName = "tu-${env:RELEASE_TAG}-${{ matrix.target }}"
New-Item -ItemType Directory -Force -Path "dist/$assetName" | Out-Null
Copy-Item "target/${{ matrix.target }}/release/tu.exe" "dist/$assetName/"
Copy-Item "README.md","LICENSE" "dist/$assetName/"
Compress-Archive -Path "dist/$assetName/*" -DestinationPath "dist/$assetName.zip" -Force
Copy-Item "target/${{ matrix.target }}/release/tu.exe" "dist/$assetName.exe"
Remove-Item "dist/$assetName" -Recurse -Force
- name: Upload build artifact
uses: actions/upload-artifact@v4
with:
name: tu-${{ matrix.target }}
path: dist/*
if-no-files-found: error
checksums:
name: Checksums
runs-on: ubuntu-latest
needs: [prepare-release, build]
if: needs.prepare-release.outputs.should_release == 'true'
steps:
- name: Download all artifacts
uses: actions/download-artifact@v4
with:
pattern: tu-*
path: dist
merge-multiple: true
- name: Generate SHA256SUMS
run: |
set -euxo pipefail
cd dist
shopt -s nullglob
files=( *.tar.gz *.zip tu-* tu-*.exe )
sha256sum "${files[@]}" > SHA256SUMS.txt
- name: Upload release bundle
uses: actions/upload-artifact@v4
with:
name: tu-release-bundle
path: dist/*
if-no-files-found: error
publish:
name: Publish GitHub Release
runs-on: ubuntu-latest
needs: [prepare-release, checksums]
if: needs.prepare-release.outputs.should_release == 'true'
steps:
- name: Download release bundle
uses: actions/download-artifact@v4
with:
name: tu-release-bundle
path: dist
- name: Publish release
uses: softprops/action-gh-release@v2
with:
tag_name: ${{ needs.prepare-release.outputs.release_tag }}
target_commitish: ${{ github.sha }}
files: dist/*
generate_release_notes: true
publish-crates:
name: Publish crates.io
runs-on: ubuntu-latest
needs: [prepare-release, checksums]
if: needs.prepare-release.outputs.should_release == 'true'
env:
CRATES_IO_TOKEN: ${{ secrets.CRATES_IO_TOKEN }}
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Install Rust toolchain
uses: dtolnay/rust-toolchain@stable
- name: Publish crate
env:
RELEASE_VERSION: ${{ needs.prepare-release.outputs.release_version }}
run: |
set -euxo pipefail
if [ -z "${CRATES_IO_TOKEN}" ]; then
echo "CRATES_IO_TOKEN is not configured; refusing release publish."
exit 1
fi
cargo_version=$(grep -E '^version[[:space:]]*=[[:space:]]*\"' Cargo.toml | head -n1 | cut -d'"' -f2)
test "${RELEASE_VERSION}" = "$cargo_version"
cargo publish --token "${CRATES_IO_TOKEN}"
publish-npm:
name: Publish npm package
runs-on: ubuntu-latest
needs: [prepare-release, publish]
if: needs.prepare-release.outputs.should_release == 'true'
env:
NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Setup Node
uses: actions/setup-node@v4
with:
node-version: "20"
registry-url: "https://registry.npmjs.org"
- name: Publish npm package
env:
RELEASE_VERSION: ${{ needs.prepare-release.outputs.release_version }}
run: |
set -euxo pipefail
if [ -z "${NPM_TOKEN}" ]; then
echo "NPM_TOKEN is not configured; refusing release publish."
exit 1
fi
cargo_version=$(grep -E '^version[[:space:]]*=[[:space:]]*\"' Cargo.toml | head -n1 | cut -d'"' -f2)
test "${RELEASE_VERSION}" = "$cargo_version"
./scripts/sync-npm-version.sh
./scripts/sync-npm-readme.sh
cd npm/tu
npm_version=$(node -p "require('./package.json').version")
test "${npm_version}" = "${cargo_version}"
NODE_AUTH_TOKEN="${NPM_TOKEN}" npm publish --access public
publish-pypi:
name: Publish PyPI package
runs-on: ubuntu-latest
needs: [prepare-release, publish]
if: needs.prepare-release.outputs.should_release == 'true'
env:
PYPI_TOKEN: ${{ secrets.PYPI_TOKEN }}
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Setup Python
uses: actions/setup-python@v5
with:
python-version: "3.12"
- name: Install build tools
run: pip install --upgrade build twine
- name: Build and publish PyPI package
env:
RELEASE_VERSION: ${{ needs.prepare-release.outputs.release_version }}
run: |
set -euxo pipefail
if [ -z "${PYPI_TOKEN}" ]; then
echo "PYPI_TOKEN is not configured; skipping PyPI publish."
exit 0
fi
cargo_version=$(grep -E '^version[[:space:]]*=[[:space:]]*\"' Cargo.toml | head -n1 | cut -d'"' -f2)
test "${RELEASE_VERSION}" = "$cargo_version"
./scripts/sync-pypi-version.sh
./scripts/sync-pypi-readme.sh
cd pypi/tu
pypi_version=$(python3 -c "from tokenusage import __version__; print(__version__)")
test "${pypi_version}" = "${cargo_version}"
python3 -m build
twine upload dist/* -u __token__ -p "${PYPI_TOKEN}"
publish-homebrew-tap:
name: Publish Homebrew tap formula
runs-on: ubuntu-latest
needs: [prepare-release, checksums]
if: needs.prepare-release.outputs.should_release == 'true'
env:
HOMEBREW_TAP_PAT: ${{ secrets.HOMEBREW_TAP_PAT }}
steps:
- name: Download release bundle
uses: actions/download-artifact@v4
with:
name: tu-release-bundle
path: dist
- name: Generate Formula
env:
RELEASE_TAG: ${{ needs.prepare-release.outputs.release_tag }}
RELEASE_VERSION: ${{ needs.prepare-release.outputs.release_version }}
run: |
set -euxo pipefail
version="${RELEASE_VERSION}"
linux_sha=$(sha256sum "dist/tu-${RELEASE_TAG}-x86_64-unknown-linux-gnu.tar.gz" | awk '{print $1}')
mac_arm_sha=$(sha256sum "dist/tu-${RELEASE_TAG}-aarch64-apple-darwin.tar.gz" | awk '{print $1}')
mac_x64_sha=$(sha256sum "dist/tu-${RELEASE_TAG}-x86_64-apple-darwin.tar.gz" | awk '{print $1}')
mkdir -p out/Formula
cat > out/Formula/tu.rb <<RUBY
class Tu < Formula
desc "Blazing-fast Rust token usage tracker for Codex and Claude Code"
homepage "https://github.com/hanbu97/tokenusage"
license "MIT"
version "${version}"
on_macos do
if Hardware::CPU.arm?
url "https://github.com/hanbu97/tokenusage/releases/download/v${version}/tu-v${version}-aarch64-apple-darwin.tar.gz"
sha256 "${mac_arm_sha}"
else
url "https://github.com/hanbu97/tokenusage/releases/download/v${version}/tu-v${version}-x86_64-apple-darwin.tar.gz"
sha256 "${mac_x64_sha}"
end
end
on_linux do
url "https://github.com/hanbu97/tokenusage/releases/download/v${version}/tu-v${version}-x86_64-unknown-linux-gnu.tar.gz"
sha256 "${linux_sha}"
end
def install
bin.install "tu"
prefix.install "README.md", "LICENSE"
end
test do
assert_match "tokenusage", shell_output("#{bin}/tu --version")
end
end
RUBY
- name: Update tap repository
env:
RELEASE_TAG: ${{ needs.prepare-release.outputs.release_tag }}
run: |
set -euxo pipefail
if [ -z "${HOMEBREW_TAP_PAT}" ]; then
echo "HOMEBREW_TAP_PAT is not configured; skipping Homebrew publish."
exit 0
fi
git clone "https://x-access-token:${HOMEBREW_TAP_PAT}@github.com/${HOMEBREW_TAP_REPO}.git" tap
mkdir -p tap/Formula
cp out/Formula/tu.rb tap/Formula/tu.rb
cd tap
git config user.name "github-actions[bot]"
git config user.email "github-actions[bot]@users.noreply.github.com"
git add Formula/tu.rb
if git diff --cached --quiet; then
echo "No formula changes."
exit 0
fi
git commit -m "chore: update tu formula for ${RELEASE_TAG}"
git push origin HEAD:main