From b1d92ad71758d4222261b78582aeb0d4a327d04b Mon Sep 17 00:00:00 2001 From: Will Date: Sun, 3 May 2026 03:51:05 +0800 Subject: [PATCH 1/6] Add Windows arm64 binary packages --- .github/workflows/binary-dev-release.yml | 36 ++++++++++++++++++------ .github/workflows/binary-release.yml | 36 ++++++++++++++++++------ 2 files changed, 54 insertions(+), 18 deletions(-) diff --git a/.github/workflows/binary-dev-release.yml b/.github/workflows/binary-dev-release.yml index 897a386e..dc91a4c4 100644 --- a/.github/workflows/binary-dev-release.yml +++ b/.github/workflows/binary-dev-release.yml @@ -188,8 +188,24 @@ jobs: if-no-files-found: error binary-dev-windows: - runs-on: windows-latest + runs-on: ${{ matrix.runs_on }} needs: resolve-dev-name + strategy: + fail-fast: false + matrix: + include: + - goarch: amd64 + asset_arch: amd64 + runs_on: windows-latest + msystem: UCRT64 + install: mingw-w64-ucrt-x86_64-gcc + cc: gcc + - goarch: arm64 + asset_arch: arm64 + runs_on: windows-11-arm + msystem: CLANGARM64 + install: mingw-w64-clang-aarch64-gcc + cc: gcc steps: - name: Checkout repository uses: actions/checkout@v6 @@ -210,10 +226,10 @@ jobs: - name: Set up MSYS2 uses: msys2/setup-msys2@v2 with: - msystem: UCRT64 + msystem: ${{ matrix.msystem }} update: true path-type: inherit - install: mingw-w64-ucrt-x86_64-gcc + install: ${{ matrix.install }} - name: Install frontend dependencies shell: bash @@ -228,15 +244,16 @@ jobs: env: PACKAGE_SUFFIX: ${{ needs.resolve-dev-name.outputs.specific_name }} GOOS: windows - GOARCH: amd64 - ASSET_ARCH: amd64 + GOARCH: ${{ matrix.goarch }} + ASSET_ARCH: ${{ matrix.asset_arch }} + CC: ${{ matrix.cc }} run: | set -euo pipefail package_name="cpa-usage-keeper_dev_${PACKAGE_SUFFIX}_${GITHUB_SHA::7}_${GOOS}_${ASSET_ARCH}" package_dir="dist/${package_name}" mkdir -p "${package_dir}/web" "${package_dir}/data" - CGO_ENABLED=1 GOOS="${GOOS}" GOARCH="${GOARCH}" CC=gcc \ + CGO_ENABLED=1 GOOS="${GOOS}" GOARCH="${GOARCH}" CC="${CC}" \ go build -trimpath -ldflags="-s -w" -o "${package_dir}/cpa-usage-keeper.exe" ./cmd/server/main.go cp -R web/dist "${package_dir}/web/dist" @@ -246,16 +263,17 @@ jobs: shell: pwsh env: PACKAGE_SUFFIX: ${{ needs.resolve-dev-name.outputs.specific_name }} + ASSET_ARCH: ${{ matrix.asset_arch }} run: | $shortSha = "${env:GITHUB_SHA}".Substring(0, 7) - $packageName = "cpa-usage-keeper_dev_${env:PACKAGE_SUFFIX}_${shortSha}_windows_amd64" + $packageName = "cpa-usage-keeper_dev_${env:PACKAGE_SUFFIX}_${shortSha}_windows_${env:ASSET_ARCH}" Compress-Archive -Path "dist/$packageName" -DestinationPath "dist/$packageName.zip" - name: Upload binary package artifact uses: actions/upload-artifact@v4 with: - name: cpa-usage-keeper-dev-${{ needs.resolve-dev-name.outputs.specific_name }}-windows-amd64 - path: dist/cpa-usage-keeper_dev_${{ needs.resolve-dev-name.outputs.specific_name }}_*_windows_amd64.zip + name: cpa-usage-keeper-dev-${{ needs.resolve-dev-name.outputs.specific_name }}-windows-${{ matrix.asset_arch }} + path: dist/cpa-usage-keeper_dev_${{ needs.resolve-dev-name.outputs.specific_name }}_*_windows_${{ matrix.asset_arch }}.zip if-no-files-found: error publish-dev-artifacts: diff --git a/.github/workflows/binary-release.yml b/.github/workflows/binary-release.yml index 8e40953f..b82b069a 100644 --- a/.github/workflows/binary-release.yml +++ b/.github/workflows/binary-release.yml @@ -140,7 +140,23 @@ jobs: if-no-files-found: error binary-release-windows: - runs-on: windows-latest + runs-on: ${{ matrix.runs_on }} + strategy: + fail-fast: false + matrix: + include: + - goarch: amd64 + asset_arch: amd64 + runs_on: windows-latest + msystem: UCRT64 + install: mingw-w64-ucrt-x86_64-gcc + cc: gcc + - goarch: arm64 + asset_arch: arm64 + runs_on: windows-11-arm + msystem: CLANGARM64 + install: mingw-w64-clang-aarch64-gcc + cc: gcc steps: - name: Checkout repository uses: actions/checkout@v6 @@ -161,10 +177,10 @@ jobs: - name: Set up MSYS2 uses: msys2/setup-msys2@v2 with: - msystem: UCRT64 + msystem: ${{ matrix.msystem }} update: true path-type: inherit - install: mingw-w64-ucrt-x86_64-gcc + install: ${{ matrix.install }} - name: Install frontend dependencies shell: bash @@ -179,15 +195,16 @@ jobs: env: VERSION: ${{ github.ref_name }} GOOS: windows - GOARCH: amd64 - ASSET_ARCH: amd64 + GOARCH: ${{ matrix.goarch }} + ASSET_ARCH: ${{ matrix.asset_arch }} + CC: ${{ matrix.cc }} run: | set -euo pipefail package_name="cpa-usage-keeper_${VERSION}_${GOOS}_${ASSET_ARCH}" package_dir="dist/${package_name}" mkdir -p "${package_dir}/web" "${package_dir}/data" - CGO_ENABLED=1 GOOS="${GOOS}" GOARCH="${GOARCH}" CC=gcc \ + CGO_ENABLED=1 GOOS="${GOOS}" GOARCH="${GOARCH}" CC="${CC}" \ go build -trimpath -ldflags="-s -w" -o "${package_dir}/cpa-usage-keeper.exe" ./cmd/server/main.go cp -R web/dist "${package_dir}/web/dist" @@ -197,15 +214,16 @@ jobs: shell: pwsh env: VERSION: ${{ github.ref_name }} + ASSET_ARCH: ${{ matrix.asset_arch }} run: | - $packageName = "cpa-usage-keeper_${env:VERSION}_windows_amd64" + $packageName = "cpa-usage-keeper_${env:VERSION}_windows_${env:ASSET_ARCH}" Compress-Archive -Path "dist/$packageName" -DestinationPath "dist/$packageName.zip" - name: Upload binary package artifact uses: actions/upload-artifact@v4 with: - name: cpa-usage-keeper-${{ github.ref_name }}-windows-amd64 - path: dist/cpa-usage-keeper_${{ github.ref_name }}_windows_amd64.zip + name: cpa-usage-keeper-${{ github.ref_name }}-windows-${{ matrix.asset_arch }} + path: dist/cpa-usage-keeper_${{ github.ref_name }}_windows_${{ matrix.asset_arch }}.zip if-no-files-found: error publish-release: From d94568c466376ab6602b2078f6c0861399b5bb2d Mon Sep 17 00:00:00 2001 From: Will Date: Sun, 3 May 2026 03:54:43 +0800 Subject: [PATCH 2/6] Update binary workflow tool versions --- .github/workflows/binary-dev-release.yml | 25 +++++++++++++----------- .github/workflows/binary-release.yml | 25 +++++++++++++----------- 2 files changed, 28 insertions(+), 22 deletions(-) diff --git a/.github/workflows/binary-dev-release.yml b/.github/workflows/binary-dev-release.yml index dc91a4c4..a0c6bb27 100644 --- a/.github/workflows/binary-dev-release.yml +++ b/.github/workflows/binary-dev-release.yml @@ -77,13 +77,14 @@ jobs: - name: Set up Go uses: actions/setup-go@v6 with: - go-version: '1.22' + go-version: stable + check-latest: true cache: true - name: Set up Node.js uses: actions/setup-node@v6 with: - node-version: '22' + node-version: '24' cache: npm cache-dependency-path: web/package-lock.json @@ -117,7 +118,7 @@ jobs: tar -czf "dist/${package_name}.tar.gz" -C dist "${package_name}" - name: Upload binary package artifact - uses: actions/upload-artifact@v4 + uses: actions/upload-artifact@v6 with: name: cpa-usage-keeper-dev-${{ needs.resolve-dev-name.outputs.specific_name }}-${{ matrix.goos }}-${{ matrix.asset_arch }} path: dist/cpa-usage-keeper_dev_${{ needs.resolve-dev-name.outputs.specific_name }}_*_${{ matrix.goos }}_${{ matrix.asset_arch }}.tar.gz @@ -145,13 +146,14 @@ jobs: - name: Set up Go uses: actions/setup-go@v6 with: - go-version: '1.22' + go-version: stable + check-latest: true cache: true - name: Set up Node.js uses: actions/setup-node@v6 with: - node-version: '22' + node-version: '24' cache: npm cache-dependency-path: web/package-lock.json @@ -181,7 +183,7 @@ jobs: tar -czf "dist/${package_name}.tar.gz" -C dist "${package_name}" - name: Upload binary package artifact - uses: actions/upload-artifact@v4 + uses: actions/upload-artifact@v6 with: name: cpa-usage-keeper-dev-${{ needs.resolve-dev-name.outputs.specific_name }}-${{ matrix.goos }}-${{ matrix.asset_arch }} path: dist/cpa-usage-keeper_dev_${{ needs.resolve-dev-name.outputs.specific_name }}_*_${{ matrix.goos }}_${{ matrix.asset_arch }}.tar.gz @@ -213,13 +215,14 @@ jobs: - name: Set up Go uses: actions/setup-go@v6 with: - go-version: '1.22' + go-version: stable + check-latest: true cache: true - name: Set up Node.js uses: actions/setup-node@v6 with: - node-version: '22' + node-version: '24' cache: npm cache-dependency-path: web/package-lock.json @@ -270,7 +273,7 @@ jobs: Compress-Archive -Path "dist/$packageName" -DestinationPath "dist/$packageName.zip" - name: Upload binary package artifact - uses: actions/upload-artifact@v4 + uses: actions/upload-artifact@v6 with: name: cpa-usage-keeper-dev-${{ needs.resolve-dev-name.outputs.specific_name }}-windows-${{ matrix.asset_arch }} path: dist/cpa-usage-keeper_dev_${{ needs.resolve-dev-name.outputs.specific_name }}_*_windows_${{ matrix.asset_arch }}.zip @@ -285,7 +288,7 @@ jobs: - binary-dev-windows steps: - name: Download binary package artifacts - uses: actions/download-artifact@v4 + uses: actions/download-artifact@v6 with: path: dist merge-multiple: true @@ -297,7 +300,7 @@ jobs: sha256sum *.tar.gz *.zip > checksums.txt - name: Upload dev binary packages - uses: actions/upload-artifact@v4 + uses: actions/upload-artifact@v6 with: name: cpa-usage-keeper-dev-binaries-${{ github.run_id }} path: | diff --git a/.github/workflows/binary-release.yml b/.github/workflows/binary-release.yml index b82b069a..4ae1967d 100644 --- a/.github/workflows/binary-release.yml +++ b/.github/workflows/binary-release.yml @@ -30,13 +30,14 @@ jobs: - name: Set up Go uses: actions/setup-go@v6 with: - go-version: '1.22' + go-version: stable + check-latest: true cache: true - name: Set up Node.js uses: actions/setup-node@v6 with: - node-version: '22' + node-version: '24' cache: npm cache-dependency-path: web/package-lock.json @@ -70,7 +71,7 @@ jobs: tar -czf "dist/${package_name}.tar.gz" -C dist "${package_name}" - name: Upload binary package artifact - uses: actions/upload-artifact@v4 + uses: actions/upload-artifact@v6 with: name: cpa-usage-keeper-${{ github.ref_name }}-${{ matrix.goos }}-${{ matrix.asset_arch }} path: dist/cpa-usage-keeper_${{ github.ref_name }}_${{ matrix.goos }}_${{ matrix.asset_arch }}.tar.gz @@ -97,13 +98,14 @@ jobs: - name: Set up Go uses: actions/setup-go@v6 with: - go-version: '1.22' + go-version: stable + check-latest: true cache: true - name: Set up Node.js uses: actions/setup-node@v6 with: - node-version: '22' + node-version: '24' cache: npm cache-dependency-path: web/package-lock.json @@ -133,7 +135,7 @@ jobs: tar -czf "dist/${package_name}.tar.gz" -C dist "${package_name}" - name: Upload binary package artifact - uses: actions/upload-artifact@v4 + uses: actions/upload-artifact@v6 with: name: cpa-usage-keeper-${{ github.ref_name }}-${{ matrix.goos }}-${{ matrix.asset_arch }} path: dist/cpa-usage-keeper_${{ github.ref_name }}_${{ matrix.goos }}_${{ matrix.asset_arch }}.tar.gz @@ -164,13 +166,14 @@ jobs: - name: Set up Go uses: actions/setup-go@v6 with: - go-version: '1.22' + go-version: stable + check-latest: true cache: true - name: Set up Node.js uses: actions/setup-node@v6 with: - node-version: '22' + node-version: '24' cache: npm cache-dependency-path: web/package-lock.json @@ -220,7 +223,7 @@ jobs: Compress-Archive -Path "dist/$packageName" -DestinationPath "dist/$packageName.zip" - name: Upload binary package artifact - uses: actions/upload-artifact@v4 + uses: actions/upload-artifact@v6 with: name: cpa-usage-keeper-${{ github.ref_name }}-windows-${{ matrix.asset_arch }} path: dist/cpa-usage-keeper_${{ github.ref_name }}_windows_${{ matrix.asset_arch }}.zip @@ -234,7 +237,7 @@ jobs: - binary-release-windows steps: - name: Download binary package artifacts - uses: actions/download-artifact@v4 + uses: actions/download-artifact@v6 with: path: dist merge-multiple: true @@ -246,7 +249,7 @@ jobs: sha256sum *.tar.gz *.zip > checksums.txt - name: Upload release assets - uses: softprops/action-gh-release@v2 + uses: softprops/action-gh-release@v3 with: files: | dist/*.tar.gz From 505b5c82afd6877a0adf425470c8fec7039e1821 Mon Sep 17 00:00:00 2001 From: Will Date: Sun, 3 May 2026 03:57:04 +0800 Subject: [PATCH 3/6] Fix usage hook dependencies --- web/src/pages/UsagePage.tsx | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/web/src/pages/UsagePage.tsx b/web/src/pages/UsagePage.tsx index 5b41e757..24af3cfd 100644 --- a/web/src/pages/UsagePage.tsx +++ b/web/src/pages/UsagePage.tsx @@ -556,7 +556,7 @@ export function UsagePage({ onAuthRequired }: { onAuthRequired?: () => void }) { analysisRequestControllerRef.current = null; } } - }, [customTimeRange.end, customTimeRange.start, onAuthRequired, timeRange]); + }, [customTimeRange, onAuthRequired, timeRange]); const hourWindowHours = useMemo( () => getOverviewHourWindowHours({ timeRange, filterWindow }), [filterWindow, timeRange] @@ -669,7 +669,7 @@ export function UsagePage({ onAuthRequired }: { onAuthRequired?: () => void }) { return { valid: false, start: undefined, end: undefined }; } return buildCustomDateRangeQuery(customTimeRange); - }, [customTimeRange.end, customTimeRange.start, timeRange]); + }, [customTimeRange, timeRange]); const loadEventFilterOptions = useCallback(async () => { const queryWindow = getEventQueryWindow(); @@ -855,7 +855,7 @@ export function UsagePage({ onAuthRequired }: { onAuthRequired?: () => void }) { credentialsRequestControllerRef.current = null; } } - }, [customTimeRange.end, customTimeRange.start, onAuthRequired, timeRange]); + }, [customTimeRange, onAuthRequired, timeRange]); const refreshActiveTab = useCallback(async () => { if (activeTab === 'events') { From a2aa20cc622da3c511a6c548f53fb28c7ba8b21b Mon Sep 17 00:00:00 2001 From: Will Date: Sun, 3 May 2026 03:59:43 +0800 Subject: [PATCH 4/6] Keep usage hook dependencies primitive --- web/src/pages/UsagePage.tsx | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/web/src/pages/UsagePage.tsx b/web/src/pages/UsagePage.tsx index 24af3cfd..dd9b8dad 100644 --- a/web/src/pages/UsagePage.tsx +++ b/web/src/pages/UsagePage.tsx @@ -531,7 +531,7 @@ export function UsagePage({ onAuthRequired }: { onAuthRequired?: () => void }) { setAnalysisError(''); setAnalysisData({ apis: [], models: [] }); try { - const queryWindow = timeRange === 'custom' ? buildCustomDateRangeQuery(customTimeRange) : { start: undefined, end: undefined }; + const queryWindow = timeRange === 'custom' ? buildCustomDateRangeQuery({ start: customTimeRange.start, end: customTimeRange.end }) : { start: undefined, end: undefined }; const response = await fetchUsageAnalysis(timeRange, queryWindow.start, queryWindow.end, controller.signal); if (analysisRequestControllerRef.current !== controller) { return; @@ -556,7 +556,7 @@ export function UsagePage({ onAuthRequired }: { onAuthRequired?: () => void }) { analysisRequestControllerRef.current = null; } } - }, [customTimeRange, onAuthRequired, timeRange]); + }, [customTimeRange.end, customTimeRange.start, onAuthRequired, timeRange]); const hourWindowHours = useMemo( () => getOverviewHourWindowHours({ timeRange, filterWindow }), [filterWindow, timeRange] @@ -668,8 +668,8 @@ export function UsagePage({ onAuthRequired }: { onAuthRequired?: () => void }) { if (startMs === undefined || endMs === undefined || startMs > endMs) { return { valid: false, start: undefined, end: undefined }; } - return buildCustomDateRangeQuery(customTimeRange); - }, [customTimeRange, timeRange]); + return buildCustomDateRangeQuery({ start: customTimeRange.start, end: customTimeRange.end }); + }, [customTimeRange.end, customTimeRange.start, timeRange]); const loadEventFilterOptions = useCallback(async () => { const queryWindow = getEventQueryWindow(); @@ -831,7 +831,7 @@ export function UsagePage({ onAuthRequired }: { onAuthRequired?: () => void }) { setCredentialsError(''); setCredentialsData([]); try { - const queryWindow = timeRange === 'custom' ? buildCustomDateRangeQuery(customTimeRange) : { start: undefined, end: undefined }; + const queryWindow = timeRange === 'custom' ? buildCustomDateRangeQuery({ start: customTimeRange.start, end: customTimeRange.end }) : { start: undefined, end: undefined }; const response = await fetchUsageCredentials(timeRange, queryWindow.start, queryWindow.end, controller.signal); if (credentialsRequestControllerRef.current !== controller) { return; @@ -855,7 +855,7 @@ export function UsagePage({ onAuthRequired }: { onAuthRequired?: () => void }) { credentialsRequestControllerRef.current = null; } } - }, [customTimeRange, onAuthRequired, timeRange]); + }, [customTimeRange.end, customTimeRange.start, onAuthRequired, timeRange]); const refreshActiveTab = useCallback(async () => { if (activeTab === 'events') { From 867f50750f42604bab320dff9ba099ba0e733033 Mon Sep 17 00:00:00 2001 From: Will Date: Sun, 3 May 2026 04:13:48 +0800 Subject: [PATCH 5/6] Use supported Intel macOS runner for binaries --- .github/workflows/binary-dev-release.yml | 2 +- .github/workflows/binary-release.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/binary-dev-release.yml b/.github/workflows/binary-dev-release.yml index a0c6bb27..f4b0d833 100644 --- a/.github/workflows/binary-dev-release.yml +++ b/.github/workflows/binary-dev-release.yml @@ -134,7 +134,7 @@ jobs: - goos: darwin goarch: amd64 asset_arch: amd64 - runs_on: macos-13 + runs_on: macos-15-intel - goos: darwin goarch: arm64 asset_arch: arm64 diff --git a/.github/workflows/binary-release.yml b/.github/workflows/binary-release.yml index 4ae1967d..9cf51301 100644 --- a/.github/workflows/binary-release.yml +++ b/.github/workflows/binary-release.yml @@ -86,7 +86,7 @@ jobs: - goos: darwin goarch: amd64 asset_arch: amd64 - runs_on: macos-13 + runs_on: macos-15-intel - goos: darwin goarch: arm64 asset_arch: arm64 From 0fa7330ad5279a75530dd360e96bd63ece763552 Mon Sep 17 00:00:00 2001 From: Will Date: Sun, 3 May 2026 04:16:09 +0800 Subject: [PATCH 6/6] Use current stable hosted runners for binaries --- .github/workflows/binary-dev-release.yml | 10 +++++----- .github/workflows/binary-release.yml | 8 ++++---- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/.github/workflows/binary-dev-release.yml b/.github/workflows/binary-dev-release.yml index f4b0d833..0ccfc7fb 100644 --- a/.github/workflows/binary-dev-release.yml +++ b/.github/workflows/binary-dev-release.yml @@ -13,7 +13,7 @@ permissions: jobs: resolve-dev-name: - runs-on: ubuntu-latest + runs-on: ubuntu-24.04 outputs: specific_name: ${{ steps.dev_name.outputs.specific_name }} steps: @@ -56,7 +56,7 @@ jobs: echo "Using specific binary package name: $specific_name" binary-dev-linux: - runs-on: ubuntu-latest + runs-on: ubuntu-24.04 needs: resolve-dev-name strategy: fail-fast: false @@ -138,7 +138,7 @@ jobs: - goos: darwin goarch: arm64 asset_arch: arm64 - runs_on: macos-14 + runs_on: macos-15 steps: - name: Checkout repository uses: actions/checkout@v6 @@ -198,7 +198,7 @@ jobs: include: - goarch: amd64 asset_arch: amd64 - runs_on: windows-latest + runs_on: windows-2025 msystem: UCRT64 install: mingw-w64-ucrt-x86_64-gcc cc: gcc @@ -280,7 +280,7 @@ jobs: if-no-files-found: error publish-dev-artifacts: - runs-on: ubuntu-latest + runs-on: ubuntu-24.04 needs: - resolve-dev-name - binary-dev-linux diff --git a/.github/workflows/binary-release.yml b/.github/workflows/binary-release.yml index 9cf51301..9c193214 100644 --- a/.github/workflows/binary-release.yml +++ b/.github/workflows/binary-release.yml @@ -10,7 +10,7 @@ permissions: jobs: binary-release-linux: - runs-on: ubuntu-latest + runs-on: ubuntu-24.04 strategy: fail-fast: false matrix: @@ -90,7 +90,7 @@ jobs: - goos: darwin goarch: arm64 asset_arch: arm64 - runs_on: macos-14 + runs_on: macos-15 steps: - name: Checkout repository uses: actions/checkout@v6 @@ -149,7 +149,7 @@ jobs: include: - goarch: amd64 asset_arch: amd64 - runs_on: windows-latest + runs_on: windows-2025 msystem: UCRT64 install: mingw-w64-ucrt-x86_64-gcc cc: gcc @@ -230,7 +230,7 @@ jobs: if-no-files-found: error publish-release: - runs-on: ubuntu-latest + runs-on: ubuntu-24.04 needs: - binary-release-linux - binary-release-darwin