Fix black lint, fix /processing-runs 404s, add semantic release and GitOps deploy

Agent-Logs-Url: https://github.com/christianlouis/InboxConverge/sessions/3fdf6219-3e1f-4867-b74d-efb6e4fe7e72

Co-authored-by: christianlouis <361235+christianlouis@users.noreply.github.com>
This commit is contained in:
copilot-swe-agent[bot]
2026-03-26 19:17:11 +00:00
parent 69716517aa
commit 896329ccb7
7 changed files with 220 additions and 3 deletions
+56
View File
@@ -224,3 +224,59 @@ jobs:
cache-from: type=gha
cache-to: type=gha,mode=max
platforms: linux/amd64,linux/arm64
# ── Phase 5: GitOps update preprod k8s manifest ─────────────────────────
update-k8s-manifest:
name: Update Preprod K8s Manifest
runs-on: ubuntu-latest
needs: [build]
if: github.ref == 'refs/heads/main' && github.event_name == 'push'
permissions:
contents: read
steps:
- name: Compute image tags
id: tag
run: |
SHORT_SHA=$(echo "${{ github.sha }}" | cut -c1-7)
echo "backend_image=ghcr.io/${{ github.repository_owner }}/inboxconverge/backend:main-${SHORT_SHA}" >> "$GITHUB_OUTPUT"
echo "frontend_image=ghcr.io/${{ github.repository_owner }}/inboxconverge/frontend:main-${SHORT_SHA}" >> "$GITHUB_OUTPUT"
echo "short_sha=${SHORT_SHA}" >> "$GITHUB_OUTPUT"
- name: Checkout k8s-cluster-state
uses: actions/checkout@v4
with:
repository: christianlouis/k8s-cluster-state
token: ${{ secrets.GH_PAT }}
path: k8s-cluster-state
- name: Update backend image tag in preprod manifest
uses: mikefarah/yq@v4.44.6
env:
IMAGE: ${{ steps.tag.outputs.backend_image }}
with:
cmd: |
yq -i '(.. | select(tag == "!!str") | select(test("^ghcr\\.io/christianlouis/inboxconverge/backend:"))) = strenv(IMAGE)' \
k8s-cluster-state/apps/gmail-puller/preprod/gmail-puller-stack.yaml
- name: Update frontend image tag in preprod manifest
uses: mikefarah/yq@v4.44.6
env:
IMAGE: ${{ steps.tag.outputs.frontend_image }}
with:
cmd: |
yq -i '(.. | select(tag == "!!str") | select(test("^ghcr\\.io/christianlouis/inboxconverge/frontend:"))) = strenv(IMAGE)' \
k8s-cluster-state/apps/gmail-puller/preprod/gmail-puller-stack.yaml
- name: Commit and push manifest update
run: |
cd k8s-cluster-state
git config user.name "github-actions[bot]"
git config user.email "github-actions[bot]@users.noreply.github.com"
git add apps/gmail-puller/preprod/gmail-puller-stack.yaml
if git diff --staged --quiet; then
echo "No changes to commit"
else
git commit -m "chore(preprod): update inboxconverge images to ${{ steps.tag.outputs.short_sha }}"
git push
fi
+68
View File
@@ -0,0 +1,68 @@
name: Semantic Release
on:
push:
branches:
- main
workflow_dispatch:
permissions:
contents: write
issues: write
pull-requests: write
packages: write
env:
FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: true
jobs:
release:
name: Semantic Release
runs-on: ubuntu-latest
if: github.repository == 'christianlouis/InboxConverge'
steps:
- name: Checkout Code
uses: actions/checkout@v4
with:
fetch-depth: 0
token: ${{ secrets.GITHUB_TOKEN }}
- name: Set up Python
uses: actions/setup-python@v6
with:
python-version: '3.12'
cache: 'pip'
- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install python-semantic-release
- name: Configure Git
run: |
git config --global user.name "github-actions[bot]"
git config --global user.email "github-actions[bot]@users.noreply.github.com"
- name: Run Semantic Release
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
semantic-release version --print
semantic-release version
semantic-release publish
- name: Update changelog if no new version was released
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
if git diff --name-only HEAD~1 2>/dev/null | grep -q CHANGELOG.md; then
echo "CHANGELOG.md was already updated by semantic-release version"
else
semantic-release changelog
if ! git diff --quiet CHANGELOG.md; then
git add CHANGELOG.md
git commit -m "docs(changelog): update changelog [skip ci]"
git push
fi
fi
+12
View File
@@ -7,6 +7,18 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
## [Unreleased]
### Fixed
- **Black formatting**: `backend/app/api/v1/endpoints/admin.py` was not formatted correctly; reformatted to pass `black --check`.
- **`/processing-runs` endpoint 404s**: Routes in `logs.py` had a redundant `/processing-runs` path segment (the router was already mounted at `/processing-runs` in `api.py`). All three user-facing log endpoints now return correct results:
- `GET /processing-runs` (was: `GET /processing-runs/processing-runs`)
- `GET /processing-runs/{id}` (was: `GET /processing-runs/processing-runs/{id}`)
- `GET /processing-runs/{id}/logs` (was: `GET /processing-runs/processing-runs/{id}/logs`)
### Added
- **Semantic Release** (`release.yml`): Automated versioning and GitHub Release creation on every push to `main` using `python-semantic-release`. Reads conventional-commit prefixes (`feat:`, `fix:`, etc.) to determine the next version and updates `CHANGELOG.md`.
- **`pyproject.toml`**: Project metadata and `[tool.semantic_release]` configuration for `python-semantic-release`.
- **GitOps auto-deployment** (step in `ci.yml`): After a successful Docker build on `main`, a new `update-k8s-manifest` job checks out `christianlouis/k8s-cluster-state` (using the `GH_PAT` secret) and updates the backend and frontend image tags in `apps/gmail-puller/preprod/gmail-puller-stack.yaml` to the new `main-<sha>` image, then commits and pushes.
### Changed
- **Project renamed to InboxConverge**: All user-visible strings, Docker container names, database defaults, Docker image paths, monitoring job names, Grafana dashboard titles, and documentation updated from the legacy names (`POP3 to Gmail Forwarder`, `InboxRescue`, `gmail-puller`, `pop3_forwarder`, etc.) to **InboxConverge** / `inboxconverge`.
- **Domain updated to `inboxconverge.com`**: All contact and administrative email addresses now default to `@inboxconverge.com` (e.g. `christian@inboxconverge.com`).
+2
View File
@@ -407,6 +407,8 @@ async def test_admin_notification_config(
"""Test an admin notification channel by sending a test message (admin only)"""
success, message = await test_notification(request.apprise_url)
return NotificationTestResponse(success=success, message=message)
# ── Admin Logs ─────────────────────────────────────────────────────────────────
+3 -3
View File
@@ -48,7 +48,7 @@ def _paginate(total: int, page: int, page_size: int) -> dict:
@router.get(
"/processing-runs",
"",
response_model=PaginatedProcessingRunsResponse,
summary="List processing runs for the current user",
)
@@ -117,7 +117,7 @@ async def list_processing_runs(
@router.get(
"/processing-runs/{run_id}",
"/{run_id}",
response_model=ProcessingRunDetailResponse,
summary="Get a single processing run",
)
@@ -160,7 +160,7 @@ async def get_processing_run(
@router.get(
"/processing-runs/{run_id}/logs",
"/{run_id}/logs",
response_model=PaginatedProcessingLogsResponse,
summary="Get per-email logs for a processing run",
)
+5
View File
@@ -7,6 +7,11 @@ Comprehensive task breakdown for repository improvements and production readines
- [x] Rename entire project to **InboxConverge**: all user-visible strings, Docker container/image names, DB defaults, monitoring, and docs updated.
- [x] Domain updated to `inboxconverge.com`; contact email defaults to `christian@inboxconverge.com`.
- [x] New configurable env vars: `CONTACT_EMAIL`, `APP_URL`, `NEXT_PUBLIC_APP_NAME`.
- [x] Fixed Black formatting failure in CI (`admin.py` reformatted).
- [x] Fixed `/processing-runs` endpoint 404s caused by duplicate path prefix in `logs.py`.
- [x] Added Semantic Release workflow (`release.yml`) for automatic versioning and GitHub Releases.
- [x] Added `pyproject.toml` with `[tool.semantic_release]` configuration.
- [x] Added GitOps auto-deployment step in `ci.yml` to update preprod k8s manifest in `k8s-cluster-state` repo.
## 🔴 Critical - Security (In Progress)
+74
View File
@@ -0,0 +1,74 @@
[build-system]
requires = ["setuptools>=45", "wheel"]
build-backend = "setuptools.build_meta"
[project]
name = "inboxconverge"
dynamic = ["version"]
description = "Multi-account email forwarding and processing service"
readme = "README.md"
requires-python = ">=3.12"
license = {text = "MIT"}
authors = [
{name = "Christian Louis", email = "christianlouis@users.noreply.github.com"}
]
[project.urls]
Homepage = "https://github.com/christianlouis/InboxConverge"
Repository = "https://github.com/christianlouis/InboxConverge"
Issues = "https://github.com/christianlouis/InboxConverge/issues"
Changelog = "https://github.com/christianlouis/InboxConverge/blob/main/CHANGELOG.md"
[tool.semantic_release]
version_source = "tag"
commit_version_number = true
tag_format = "v{version}"
major_on_zero = false
allow_zero_version = true
[tool.semantic_release.branches.main]
match = "main"
prerelease = false
[tool.semantic_release.changelog]
mode = "update"
exclude_commit_patterns = [
"^chore\\(release\\):",
"^Merge",
"^Bump version",
]
[tool.semantic_release.changelog.default_templates]
changelog_file = "CHANGELOG.md"
output_format = "md"
[tool.semantic_release.commit_parser_options]
allowed_tags = [
"feat",
"fix",
"docs",
"style",
"refactor",
"perf",
"test",
"build",
"ci",
"chore",
]
minor_tags = ["feat"]
patch_tags = ["fix", "perf"]
default_bump_level = 0
[tool.semantic_release.remote]
name = "origin"
type = "github"
ignore_token_for_push = false
[tool.semantic_release.remote.token]
env = "GH_TOKEN"
[tool.semantic_release.publish]
dist_glob_patterns = []
upload_to_vcs_release = true
upload_to_pypi = false
upload_to_repository = false