Skip to content
Open
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
184 changes: 184 additions & 0 deletions .github/workflows/cli-release.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,184 @@
name: CLI Release

on:
push:
tags:
- "cli/v*"

env:
PROJECT_FILE: apps/cli/src/BitFinance.Cli.csproj
TEST_PROJECT: apps/cli/tests/BitFinance.Cli.UnitTests/BitFinance.Cli.UnitTests.csproj

permissions:
contents: read

jobs:
validate:
runs-on: ubuntu-latest
outputs:
version: ${{ steps.version.outputs.version }}

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

- name: Set release version
id: version
env:
REF_NAME: ${{ github.ref_name }}
run: |
set -euo pipefail
VERSION="${REF_NAME#cli/v}"

if ! printf '%s' "$VERSION" | grep -Eq '^[0-9]+\.[0-9]+\.[0-9]+(-[0-9A-Za-z.-]+)?$'; then
echo "::error::Version must be semver without the v prefix. Received '$VERSION'."
exit 1
fi

echo "version=$VERSION" >> "$GITHUB_OUTPUT"

- name: Validate project version
env:
RELEASE_VERSION: ${{ steps.version.outputs.version }}
run: |
set -euo pipefail
PROJECT_VERSION="$(sed -n 's:.*<Version>\(.*\)</Version>.*:\1:p' "$PROJECT_FILE" | head -n 1)"

if [ -z "$PROJECT_VERSION" ]; then
echo "::error::$PROJECT_FILE must define a <Version> value."
exit 1
fi

if [ "$RELEASE_VERSION" != "$PROJECT_VERSION" ]; then
echo "::error::Version mismatch: CLI release '$RELEASE_VERSION' does not match project version '$PROJECT_VERSION'."
exit 1
fi

- name: Set up .NET
uses: actions/setup-dotnet@v5
with:
dotnet-version: "10.0.x"

- name: Cache NuGet packages
uses: actions/cache@v5
with:
path: ~/.nuget/packages
key: ${{ runner.os }}-nuget-cli-${{ hashFiles('apps/cli/**/*.csproj') }}
restore-keys: |
${{ runner.os }}-nuget-cli-

- name: Test CLI
run: dotnet test "$TEST_PROJECT" -c Release --disable-build-servers -v:minimal

build:
needs: validate
strategy:
fail-fast: false
matrix:
include:
- rid: linux-x64
runner: ubuntu-latest
- rid: linux-arm64
runner: ubuntu-24.04-arm
runs-on: ${{ matrix.runner }}

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

- name: Set up .NET
uses: actions/setup-dotnet@v5
with:
dotnet-version: "10.0.x"

- name: Cache NuGet packages
uses: actions/cache@v5
with:
path: ~/.nuget/packages
key: ${{ runner.os }}-${{ matrix.rid }}-nuget-cli-${{ hashFiles('apps/cli/**/*.csproj') }}
restore-keys: |
${{ runner.os }}-${{ matrix.rid }}-nuget-cli-

- name: Publish single-file executable
env:
RID: ${{ matrix.rid }}
run: |
set -euo pipefail
dotnet publish "$PROJECT_FILE" \
-c Release \
-r "$RID" \
--self-contained true \
-p:PublishSingleFile=true \
-p:IncludeNativeLibrariesForSelfExtract=true \
-p:PublishTrimmed=false \
-p:DebugType=embedded \
-p:ContinuousIntegrationBuild=true \
-o "$RUNNER_TEMP/publish"

- name: Smoke-test executable
env:
RELEASE_VERSION: ${{ needs.validate.outputs.version }}
run: |
set -euo pipefail
EXECUTABLE="$RUNNER_TEMP/publish/bitfinance-cli"
test -x "$EXECUTABLE"
"$EXECUTABLE" --help > /dev/null
ACTUAL_VERSION="$($EXECUTABLE --version)"
test "$ACTUAL_VERSION" = "$RELEASE_VERSION"

- name: Package executable
env:
RELEASE_VERSION: ${{ needs.validate.outputs.version }}
RID: ${{ matrix.rid }}
run: |
set -euo pipefail
ARCHIVE="bitfinance-cli-$RELEASE_VERSION-$RID.tar.gz"
tar -czf "$RUNNER_TEMP/$ARCHIVE" -C "$RUNNER_TEMP/publish" bitfinance-cli

- name: Upload packaged executable
uses: actions/upload-artifact@v7
with:
name: bitfinance-cli-${{ matrix.rid }}
path: ${{ runner.temp }}/bitfinance-cli-${{ needs.validate.outputs.version }}-${{ matrix.rid }}.tar.gz
if-no-files-found: error
retention-days: 1

release:
runs-on: ubuntu-latest
needs:
- validate
- build
permissions:
contents: write

steps:
- name: Download packaged executables
uses: actions/download-artifact@v7
with:
path: ${{ runner.temp }}/release
pattern: bitfinance-cli-*
merge-multiple: true

- name: Generate checksums
working-directory: ${{ runner.temp }}/release
run: sha256sum bitfinance-cli-*.tar.gz > checksums.txt

- name: Create GitHub Release
working-directory: ${{ runner.temp }}/release
env:
GH_TOKEN: ${{ github.token }}
RELEASE_VERSION: ${{ needs.validate.outputs.version }}
run: |
set -euo pipefail
EXTRA_ARGS=()
if [[ "$RELEASE_VERSION" == *-* ]]; then
EXTRA_ARGS+=(--prerelease)
fi

gh release create "$GITHUB_REF_NAME" \
bitfinance-cli-*.tar.gz \
checksums.txt \
--verify-tag \
--generate-notes \
--title "BitFinance CLI v$RELEASE_VERSION" \
"${EXTRA_ARGS[@]}"
32 changes: 32 additions & 0 deletions .github/workflows/main-validation.yml
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ jobs:
frontend: ${{ steps.filter.outputs.frontend }}
backend: ${{ steps.filter.outputs.backend }}
mcp: ${{ steps.filter.outputs.mcp }}
cli: ${{ steps.filter.outputs.cli }}
steps:
- name: Checkout repository
uses: actions/checkout@v6
Expand All @@ -40,6 +41,10 @@ jobs:
- 'apps/mcp-server/**'
- '.github/workflows/mcp-docker-publish.yml'
- '.github/workflows/main-validation.yml'
cli:
- 'apps/cli/**'
- '.github/workflows/cli-release.yml'
- '.github/workflows/main-validation.yml'

frontend:
runs-on: ubuntu-latest
Expand Down Expand Up @@ -129,3 +134,30 @@ jobs:

- name: Test MCP server
run: dotnet test apps/mcp-server/tests/BitFinance.MCP.UnitTests/BitFinance.MCP.UnitTests.csproj --disable-build-servers -v:minimal

cli:
runs-on: ubuntu-latest
needs: changes
if: needs.changes.outputs.cli == 'true'
steps:
- name: Checkout repository
uses: actions/checkout@v6

- name: Set up .NET
uses: actions/setup-dotnet@v5
with:
dotnet-version: "10.0.x"

- name: Cache NuGet packages
uses: actions/cache@v5
with:
path: ~/.nuget/packages
key: ${{ runner.os }}-nuget-cli-${{ hashFiles('apps/cli/**/*.csproj') }}
restore-keys: |
${{ runner.os }}-nuget-cli-

- name: Build CLI
run: dotnet build apps/cli/src/BitFinance.Cli.csproj --disable-build-servers -v:minimal

- name: Test CLI
run: dotnet test apps/cli/tests/BitFinance.Cli.UnitTests/BitFinance.Cli.UnitTests.csproj --disable-build-servers -v:minimal
11 changes: 11 additions & 0 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,15 @@ MCP server:
dotnet build apps/mcp-server/src/BitFinance.MCP.csproj
```

CLI:

```bash
dotnet build apps/cli/src/BitFinance.Cli.csproj
dotnet test apps/cli/tests/BitFinance.Cli.UnitTests/BitFinance.Cli.UnitTests.csproj
dotnet format apps/cli/src/BitFinance.Cli.csproj --verify-no-changes
dotnet format apps/cli/tests/BitFinance.Cli.UnitTests/BitFinance.Cli.UnitTests.csproj --verify-no-changes
```

## Commit Format

This repository follows Conventional Commits. Include the affected project or area as the scope.
Expand All @@ -49,6 +58,7 @@ Examples:
feat(frontend): add bill status filter
fix(backend): correct filtered bill count
feat(mcp-server): expose bill description search
feat(cli): add bill creation command
docs(readme): clarify local setup
ci(frontend): update deploy workflow paths
```
Expand All @@ -68,6 +78,7 @@ Preferred scopes:
- `frontend`
- `backend`
- `mcp-server`
- `cli`
- `docs`
- `ci`
- `monorepo`
Expand Down
12 changes: 11 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
# BitFinance

BitFinance is a finance platform for tracking bills, expenses, organizations, and financial activity across a web app, backend API, and MCP server integration.
BitFinance is a finance platform for tracking bills, expenses, organizations, and financial activity across a web app, backend API, MCP server integration, and agent-oriented CLI.

## Components

- **Frontend**: React 19, TypeScript, Vite, Tailwind CSS, TanStack Query, Zustand, and installable PWA support.
- **Backend**: .NET API with PostgreSQL persistence, Redis caching support, object storage integration, authentication, and organization-based finance workflows.
- **MCP server**: .NET Streamable HTTP MCP server that exposes BitFinance API capabilities to MCP-compatible agents and clients.
- **CLI**: Self-contained .NET command-line client with stable JSON output for agents and automation.

## Local Development

Expand Down Expand Up @@ -41,6 +42,15 @@ Run the MCP server directly after setting the required environment variables:
dotnet run --project apps/mcp-server/src/BitFinance.MCP.csproj
```

Run the CLI after configuring an API URL and access token:

```bash
export BITFINANCE_API_BASE_URL="https://<bitfinance-api-host>"
export BITFINANCE_ACCESS_TOKEN="<access-token>"

dotnet run --project apps/cli/src/BitFinance.Cli.csproj -- organizations list
```

## Documentation

Each component keeps its own README with setup, configuration, and deployment details.
Loading
Loading