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
48 changes: 48 additions & 0 deletions .github/ISSUE_TEMPLATE/bug_report.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
name: Bug report
description: Report reproducible behavior that is incorrect
title: "[Bug]: "
labels:
- bug
body:
- type: markdown
attributes:
value: |
Thanks for helping improve Bill. Do not include tokens, private keys,
real private server details, or other secrets.
- type: textarea
id: problem
attributes:
label: Problem
description: What happened, and who or what was affected?
validations:
required: true
- type: textarea
id: reproduce
attributes:
label: Steps to reproduce
description: Provide the smallest safe sequence that demonstrates the problem.
placeholder: |
1. Configure ...
2. Run ...
3. Observe ...
validations:
required: true
- type: textarea
id: expected
attributes:
label: Expected behavior
description: What should have happened instead?
validations:
required: true
- type: textarea
id: acceptance
attributes:
label: Acceptance criteria
description: What observable outcomes would confirm the bug is fixed?
validations:
required: true
- type: textarea
id: context
attributes:
label: Additional safe context
description: Add sanitized logs or screenshots if useful. Remove secrets and private IDs.
1 change: 1 addition & 0 deletions .github/ISSUE_TEMPLATE/config.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
blank_issues_enabled: true
42 changes: 42 additions & 0 deletions .github/ISSUE_TEMPLATE/feature_request.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
name: Feature request
description: Propose an outcome or improvement for Bill
title: "[Feature]: "
labels:
- enhancement
body:
- type: markdown
attributes:
value: |
Start with the problem rather than only a preferred implementation.
Do not include secrets or private server information.
- type: textarea
id: problem
attributes:
label: Problem or opportunity
description: Who needs this, and what are they unable to do today?
validations:
required: true
- type: textarea
id: outcome
attributes:
label: Desired outcome
description: Describe the user-visible result.
validations:
required: true
- type: textarea
id: acceptance
attributes:
label: Acceptance criteria
description: List concrete conditions that would make this request complete.
validations:
required: true
- type: textarea
id: alternatives
attributes:
label: Alternatives considered
description: Note workarounds or simpler approaches that were considered.
- type: textarea
id: context
attributes:
label: Additional context
description: Add safe examples, sketches, or related Issue links.
18 changes: 18 additions & 0 deletions .github/pull_request_template.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
## Summary

<!-- What changed, and why is this the smallest coherent change? -->

## Related work

<!-- Use "Closes #123" only when merging this PR should close the Issue. -->

## Checks

- [ ] Python compile, Ruff, and pytest pass
- [ ] Worker typecheck and Vitest pass
- [ ] No secrets, private IDs, or local environment files are included
- [ ] Documentation and manual steps are updated when needed

## Risk and rollout

<!-- Note behavior changes, limitations, rollout/rollback needs, or write "None". -->
14 changes: 14 additions & 0 deletions .github/release.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
changelog:
exclude:
labels:
- skip-changelog
categories:
- title: Features
labels:
- enhancement
- title: Fixes
labels:
- bug
- title: Other changes
labels:
- "*"
111 changes: 111 additions & 0 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
name: Release

on:
push:
tags:
- "v*"

# Validation needs only repository reads. The publishing job receives its own
# narrowly scoped write permission after every check succeeds.
permissions:
contents: read

jobs:
validate:
name: Validate tag and code
runs-on: ubuntu-latest
outputs:
tag_object: ${{ steps.release_metadata.outputs.tag_object }}
steps:
- name: Check out the tagged revision with release history
uses: actions/checkout@v4
with:
fetch-depth: 0

- name: Fetch current main ref
run: git fetch --no-tags origin main:refs/remotes/origin/main

- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: "3.12"
cache: pip

- name: Set up Node.js
uses: actions/setup-node@v4
with:
node-version: "22"
cache: npm
cache-dependency-path: worker/package-lock.json

- name: Validate release tag and synchronized versions
id: release_metadata
run: |
python scripts/validate_release.py "$GITHUB_REF_NAME"
tag_object="$(git rev-parse "refs/tags/${GITHUB_REF_NAME}")"
echo "tag_object=${tag_object}" >> "$GITHUB_OUTPUT"

- name: Install Python dependencies
run: python -m pip install -e '.[dev]'

- name: Compile Python
run: python -m compileall -q bill

- name: Lint Python
run: ruff check bill tests

- name: Test Python
run: pytest -q

- name: Install Worker dependencies
working-directory: worker
run: npm ci

- name: Type-check and test Worker
working-directory: worker
run: npm run check

publish:
name: Publish GitHub Release
needs: validate
runs-on: ubuntu-latest
permissions:
contents: write
steps:
- name: Create release once
env:
GH_TOKEN: ${{ github.token }}
EXPECTED_TAG_OBJECT: ${{ needs.validate.outputs.tag_object }}
TAG: ${{ github.ref_name }}
shell: bash
run: |
set -euo pipefail

# Bind publishing to the exact annotated tag object that passed validation.
live_tag_object="$(gh api \
"repos/${GITHUB_REPOSITORY}/git/ref/tags/${TAG}" \
--jq '.object.sha')"
if [[ "${live_tag_object}" != "${EXPECTED_TAG_OBJECT}" ]]; then
echo "Tag changed after validation; refusing to publish." >&2
exit 1
fi

# A rerun must preserve any release text that a maintainer may have edited.
error_file="$(mktemp)"
trap 'rm -f "${error_file}"' EXIT
if release_url="$(gh api "repos/${GITHUB_REPOSITORY}/releases/tags/${TAG}" \
--jq '.html_url' 2>"${error_file}")"; then
echo "Release already exists: ${release_url}"
exit 0
fi

if ! grep -q 'HTTP 404' "${error_file}"; then
cat "${error_file}" >&2
exit 1
fi

gh release create "${TAG}" \
--repo "${GITHUB_REPOSITORY}" \
--verify-tag \
--generate-notes \
--title "Bill ${TAG}"
25 changes: 25 additions & 0 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
# Contributing to Bill

Bill uses small reviewed changes rather than direct pushes to `main`.

1. Open or choose a clear Issue when the work needs tracking or agreement.
2. Start one focused branch or coding session from current `main`.
3. Make the smallest coherent change; never include secrets or production IDs.
4. Inspect and commit the intended patch, then push the feature branch.
5. Open a focused PR into `main`, link its Issue, and describe what changed and
how it was checked. Use a draft while work is incomplete.
6. Run and fix the Python and Worker checks documented in the
[README](README.md).
7. Address review conversations in the same branch and resolve threads only
after replying.
8. Merge with an enabled repository strategy after checks and review pass.
Delete the branch only when its work is safely merged and no stack depends
on it.

Use stacked PRs only for genuinely dependent, separately reviewable layers.
Coordinate before rebasing or force-updating any shared or session-owned branch.

Read [version control](docs/version-control.md), [GitHub collaboration](docs/github-collaboration.md),
and [releases](docs/releases.md) before changing shared history or publishing a
version. Creating a GitHub Release never deploys Bill; production rollout
remains a separate manual process.
11 changes: 9 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,15 @@ npm ci
npm run check
```

See [deployment](docs/deployment.md), [architecture](docs/architecture.md), and
[send tracking](docs/send-tracking.md) for the runnable setup and behavior.
## Guides

- [Version control with Git and GitHub](docs/version-control.md)
- [Collaborating with Issues, PRs, reviews, and stacks](docs/github-collaboration.md)
- [Releasing Bill](docs/releases.md)
- [Contributing](CONTRIBUTING.md)
- [Deployment](docs/deployment.md)
- [Architecture](docs/architecture.md)
- [Send tracking](docs/send-tracking.md)

## Current scope

Expand Down
Loading
Loading