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
1 change: 1 addition & 0 deletions .claude/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
settings.local.json
43 changes: 43 additions & 0 deletions .claude/commands/commit.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
---
description: Commit recent changes using a conventional commit message, after syncing with the remote.
allowed-tools: Bash(git status:*), Bash(git pull:*), Bash(git diff:*), Bash(git add:*), Bash(git commit:*), Bash(git push:*), AskUserQuestion, Edit, Write
context: fork
---
Commit recent changes using a conventional commit message, after syncing with the remote.

## Steps

1. **Check git status** — run `git status` to see staged, unstaged, and untracked files. If there is nothing staged, stage recent changes. If there are unstaged or changed files from previous sessions group them (if possible) and use `AskUserQuestion` to ask the user if these changes shall be commited as well.

2. **Sync** — run `git pull --rebase` to incorporate upstream changes before committing. If it fails (e.g. conflicts), stop and report the error; do not proceed.

3. **Analyze the diff** — run `git diff --cached` to understand what is staged.

4. **Draft a conventional commit message** following this format:
```
<type>(<optional scope>): <short description>

<optional body — explain WHY, not WHAT>
```
- **type**: `feat` | `fix` | `docs` | `style` | `refactor` | `test` | `chore` | `perf` | `ci` | `build` | `revert`
- **scope**: affected module/component (omit if unclear or cross-cutting)
- **short description**: imperative mood, lowercase, no trailing period, ≤ 72 chars
- **body**: wrap at 72 chars; omit if the subject line is self-explanatory
- Add `BREAKING CHANGE: <description>` in the footer if applicable

5. **Update CHANGELOG.md** — prepend an entry for this commit under the `[Unreleased]` section (create the file and section if absent). Format:
```
## [Unreleased]

### <Category>
- <human-readable summary of the change>
```
Categories: `Added` | `Changed` | `Fixed` | `Removed` | `Security` | `Performance`. Use one category block per entry; add multiple bullets if needed. Stage `CHANGELOG.md` with `git add CHANGELOG.md` before committing.

6. **Confirm** — use `AskUserQuestion` with two questions in a single call:
1. Show the drafted commit message and CHANGELOG entry; ask the user to approve or request changes.
2. Ask whether to push after committing.

7. **Commit** — once confirmed, run `git commit -m "<message>"`.

8. **Push** — if the user chose to push, run `git push`.
81 changes: 81 additions & 0 deletions .claude/commands/release.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
---
description: Bump the app version (major/minor/patch or explicit semver), update CHANGELOG.md, and commit the release.
allowed-tools: Bash(git status:*), Bash(git pull:*), Bash(git diff:*), Bash(git add:*), Bash(git commit:*), Bash(git push:*), Read, Edit, Bash, AskUserQuestion, TodoWrite, TodoRead
context: fork
---

You are preparing a new release for the AutoSugar Android app. Your job is to determine the new version number, update `app/build.gradle.kts`, restructure `CHANGELOG.md`, and commit the result.

## Input

The user may have provided an argument: `$ARGUMENTS`

Interpret `$ARGUMENTS` as follows:
- `major`, `minor`, or `patch` (case-insensitive) → bump that semver component
- A full semver string like `1.0.4` or `2.0.0` → use it exactly
- Empty / blank → analyse the changelog and suggest a bump type (see below)
- Anything else → it is unusual; flag it and ask for confirmation or correction

## Step 1 — Read current version

Read `app/build.gradle.kts` and extract:
- `versionName` (e.g. `"0.1.0"`)
- `versionCode` (integer)

## Step 2 — Determine target version

**If argument is `major` / `minor` / `patch`:**
Compute the new semver by incrementing the appropriate component (reset lower components to 0).

**If argument is a valid semver (`X.Y.Z` with all three numeric parts):**
Use it as-is. Warn (but don't block) if the new version is less than or equal to the current one.

**If argument is empty:**
Read the `## [Unreleased]` section of `CHANGELOG.md`. Based on the entries:
- Any `### Added` → at minimum a `minor` bump
- Only `### Fixed` or `### Changed` (no new features) → `patch`
- Breaking change indicated (rare) → `major`

Formulate a suggestion with a one-sentence rationale.

**If argument is unusual** (e.g. only two parts like `1.2`, has leading zeros, non-numeric, etc.):
Do not proceed. Ask the user to confirm or correct.

## Step 3 — Confirm with user

Before making any changes, use **AskUserQuestion** to confirm. Show:
- Current version
- Proposed new version
- New versionCode (current + 1)

Single question, two options: "Proceed" and "Cancel / change". If the user cancels or provides a correction, re-evaluate from Step 2 with their input, then confirm again.

## Step 4 — Apply changes

**4a. Update `app/build.gradle.kts`**

Replace the `versionCode` and `versionName` lines with the new values. Use Edit — do not rewrite the whole file.

**4b. Update `CHANGELOG.md`**

Get today's date via: `date +%Y-%m-%d`

Replace the line `## [Unreleased]` (at the top of the Unreleased section) with:

```
## [Unreleased]

## [X.Y.Z] - YYYY-MM-DD
```

This preserves an empty Unreleased section for future work and stamps the release with today's date.

## Step 5 — Commit

Run:
```
git add app/build.gradle.kts CHANGELOG.md
git commit -m "chore(release): bump version to X.Y.Z"
```

Do **not** push. Tell the user the commit is ready and they can push / open a PR when ready.
70 changes: 70 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
name: CI

on:
push:
branches: [main, develop]
pull_request:
branches: [main, develop]

jobs:
build:
name: Build
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4

- uses: actions/setup-java@v4
with:
distribution: temurin
java-version: 17

- uses: gradle/actions/setup-gradle@v3

- name: Assemble debug APK
run: ./gradlew assembleDebug

test:
name: Unit Tests
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4

- uses: actions/setup-java@v4
with:
distribution: temurin
java-version: 17

- uses: gradle/actions/setup-gradle@v3

- name: Run unit tests
run: ./gradlew test

- name: Upload test results
if: always()
uses: actions/upload-artifact@v4
with:
name: test-results
path: app/build/reports/tests/

lint:
name: Lint
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4

- uses: actions/setup-java@v4
with:
distribution: temurin
java-version: 17

- uses: gradle/actions/setup-gradle@v3

- name: Run lint
run: ./gradlew lint

- name: Upload lint report
if: always()
uses: actions/upload-artifact@v4
with:
name: lint-report
path: app/build/reports/lint-results-debug.html
114 changes: 114 additions & 0 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
name: Release

on:
push:
branches: [main]
workflow_dispatch:
inputs:
track:
description: Google Play track to upload to
required: false
default: beta
type: choice
options:
- internal
- alpha
- beta
- production

jobs:
release:
name: Tag, publish & deploy
runs-on: ubuntu-latest
permissions:
contents: write

steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0

- name: Read version
id: version
run: |
VERSION=$(grep 'versionName' app/build.gradle.kts | sed 's/.*"\(.*\)".*/\1/')
echo "name=$VERSION" >> "$GITHUB_OUTPUT"
echo "tag=v$VERSION" >> "$GITHUB_OUTPUT"

- name: Check if tag already exists
id: tag_check
run: |
if git rev-parse "${{ steps.version.outputs.tag }}" >/dev/null 2>&1; then
echo "exists=true" >> "$GITHUB_OUTPUT"
else
echo "exists=false" >> "$GITHUB_OUTPUT"
fi

- name: Extract release notes from CHANGELOG.md
if: steps.tag_check.outputs.exists == 'false'
id: notes
run: |
VERSION="${{ steps.version.outputs.name }}"
NOTES=$(awk "/^## \[$VERSION\]/{found=1; next} found && /^## \[/{exit} found{print}" CHANGELOG.md \
| sed '/^[[:space:]]*$/d' | awk 'NR==1{p=1} p')
# Preserve multiline output
{
echo "body<<RELEASE_NOTES_EOF"
echo "$NOTES"
echo "RELEASE_NOTES_EOF"
} >> "$GITHUB_OUTPUT"

- name: Create and push tag
if: steps.tag_check.outputs.exists == 'false'
run: |
git config user.name "github-actions[bot]"
git config user.email "github-actions[bot]@users.noreply.github.com"
git tag "${{ steps.version.outputs.tag }}"
git push origin "${{ steps.version.outputs.tag }}"

- name: Create GitHub Release
if: steps.tag_check.outputs.exists == 'false'
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
gh release create "${{ steps.version.outputs.tag }}" \
--title "${{ steps.version.outputs.tag }}" \
--notes "${{ steps.notes.outputs.body }}"

- uses: actions/setup-java@v4
if: steps.tag_check.outputs.exists == 'false'
with:
distribution: temurin
java-version: 17

- uses: gradle/actions/setup-gradle@v3
if: steps.tag_check.outputs.exists == 'false'

- name: Decode keystore
if: steps.tag_check.outputs.exists == 'false'
run: echo "${{ secrets.KEYSTORE_BASE64 }}" | base64 -d > keystore.jks

- name: Build signed AAB
if: steps.tag_check.outputs.exists == 'false'
env:
KEYSTORE_PATH: keystore.jks
KEYSTORE_PASSWORD: ${{ secrets.KEYSTORE_PASSWORD }}
KEY_ALIAS: ${{ secrets.KEY_ALIAS }}
KEY_PASSWORD: ${{ secrets.KEY_PASSWORD }}
run: ./gradlew bundleRelease

- name: Prepare what's new for Google Play
if: steps.tag_check.outputs.exists == 'false'
run: |
mkdir -p whatsnew
echo "${{ steps.notes.outputs.body }}" > whatsnew/whatsnew-en-US

- name: Upload to Google Play
if: steps.tag_check.outputs.exists == 'false'
uses: r0adkll/upload-google-play@v1
with:
serviceAccountJsonPlainText: ${{ secrets.SERVICE_ACCOUNT_JSON }}
packageName: de.autosugar
releaseFiles: app/build/outputs/bundle/release/*.aab
track: ${{ inputs.track || 'beta' }}
whatsNewDirectory: whatsnew/
6 changes: 6 additions & 0 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,12 @@

This document defines specific roles for AI agents or developers to ensure a modular and scalable implementation of AutoSugar.

## Branch Strategy

* **`main`** is protected. Never commit or push directly to `main`.
* All work happens on **`develop`** (or feature branches off `develop`).
* Merges into `main` are done via pull request only.

## Agent 1: Android Auto UX/UI Specialist
* **Focus:** Implementing the `CarAppService` and `Screen` hierarchy.
* **Tasks:** * Design a dynamic `PaneTemplate` that updates based on the selected source.
Expand Down
39 changes: 39 additions & 0 deletions AutoSugar.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Loading