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
103 changes: 103 additions & 0 deletions .github/RELEASE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
# Release Process

This document describes the automated release workflow for Platito.

## Overview

Releases are managed through two GitHub Actions workflows that together handle the full lifecycle: branch creation, changelog update, PR to main, GitHub Release creation, and backport to develop.

```
develop ──► release/X.Y.Z ──► main ──► backport/X.Y.Z ──► develop
(PR) (Release) (PR)
```

## Prerequisites

Before running a release for the first time, enable **Allow auto-merge** in the repository:

> GitHub → Settings → General → Pull Requests → Allow auto-merge

Without this, the workflows will still create the PRs but they will need to be merged manually.

## How to trigger a release

1. Go to **Actions → Create Release → Run workflow**
2. Enter the version number following [Semantic Versioning](https://semver.org/) (e.g. `1.9.0`)
3. Click **Run workflow**

Everything else is automatic.

## What happens step by step

### Phase 1 — `release.yml` (triggered manually)

| Step | What it does |
|---|---|
| Checkout develop | Starts from the current state of `develop` |
| Create release branch | Creates `release/X.Y.Z` from `develop` |
| Bump version | Updates `package.json` and `package-lock.json` |
| Update CHANGELOG.md | Moves `[Unreleased]` content to `[X.Y.Z] - YYYY-MM-DD` and updates comparison links |
| Commit & push | Commits as `chore: release X.Y.Z` and pushes the branch |
| Create PR | Opens `release/X.Y.Z → main` with title `release: X.Y.Z` |
| Auto-merge | Enables auto-merge; the PR merges once the PR check passes |

### Phase 2 — `release-finalize.yml` (triggered automatically when the release PR merges into main)

| Step | What it does |
|---|---|
| Create GitHub Release | Tags the commit and creates a release with notes extracted from CHANGELOG.md |
| Create backport branch | Creates `backport/X.Y.Z` from `develop` and merges `release/X.Y.Z` into it |
| Create backport PR | Opens `backport/X.Y.Z → develop` |
| Auto-merge | Enables auto-merge on the backport PR |

## CHANGELOG convention

The `[Unreleased]` section at the top of `CHANGELOG.md` is where all changes are documented during development. When a release is triggered, the automation:

1. Renames `[Unreleased]` to `[X.Y.Z] - YYYY-MM-DD`
2. Adds a fresh empty `[Unreleased]` section above it
3. Updates the comparison links at the bottom of the file

During development, add entries under `[Unreleased]` using the standard categories:

```markdown
## [Unreleased]

### Added
- New feature description

### Changed
- Changed behavior description

### Fixed
- Bug fix description
```

## Conflict handling

If the backport merge has conflicts (e.g. because `develop` has new CHANGELOG entries), the workflow will:

- Skip the auto-merge
- Print a warning in the Actions log
- Leave the backport PR creation incomplete

In this case, create the backport manually:

```bash
git checkout develop
git pull origin develop
git checkout -b backport/X.Y.Z
git merge origin/release/X.Y.Z
# resolve conflicts
git push origin backport/X.Y.Z
gh pr create --base develop --head backport/X.Y.Z --title "chore: backport X.Y.Z to develop"
```

## Files involved

| File | Purpose |
|---|---|
| [workflows/release.yml](workflows/release.yml) | Manual workflow — creates release branch and PR |
| [workflows/release-finalize.yml](workflows/release-finalize.yml) | Automatic workflow — GitHub Release and backport |
| [scripts/update-changelog.js](scripts/update-changelog.js) | Updates CHANGELOG.md during release creation |
| [scripts/extract-release-notes.js](scripts/extract-release-notes.js) | Extracts version notes for the GitHub Release |
15 changes: 15 additions & 0 deletions .github/scripts/extract-release-notes.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
// Usage: node extract-release-notes.js <version>
const fs = require('fs');

const version = process.argv[2];
if (!version) {
console.error('Usage: node extract-release-notes.js <version>');
process.exit(1);
}

const content = fs.readFileSync('CHANGELOG.md', 'utf8');
const escaped = version.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
const pattern = new RegExp(`## \\[${escaped}\\][^\\n]*\\n(.*?)(?=\\n## \\[|$)`, 's');
const m = content.match(pattern);

process.stdout.write(m ? m[1].trim() : '');
41 changes: 41 additions & 0 deletions .github/scripts/update-changelog.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
// Usage: VERSION=1.9.0 node update-changelog.js
const fs = require('fs');

const version = process.env.VERSION;
const date = new Date().toISOString().split('T')[0];
const repo = 'https://github.com/tomas2305/platito';

if (!version) {
console.error('VERSION environment variable is required');
process.exit(1);
}

let content = fs.readFileSync('CHANGELOG.md', 'utf8');

// Find previous version before modifying content
const prevMatch = content.match(/^## \[(\d+\.\d+\.\d+)\]/m);
const prevVersion = prevMatch?.[1] ?? null;

// Insert new version header right after [Unreleased]
content = content.replace(
/^## \[Unreleased\]/m,
`## [Unreleased]\n\n## [${version}] - ${date}`
);

// Build the new version link
const versionLink = prevVersion
? `[${version}]: ${repo}/compare/${prevVersion}...${version}`
: `[${version}]: ${repo}/releases/tag/${version}`;

// Update [Unreleased] link and insert version link below it
if (/^\[Unreleased\]:/m.test(content)) {
content = content.replace(
/^\[Unreleased\]:.*$/m,
`[Unreleased]: ${repo}/compare/${version}...HEAD\n${versionLink}`
);
} else {
content += `\n[Unreleased]: ${repo}/compare/${version}...HEAD\n${versionLink}\n`;
}

fs.writeFileSync('CHANGELOG.md', content);
console.log(`CHANGELOG updated: ${version} (previous: ${prevVersion ?? 'none'})`);
97 changes: 97 additions & 0 deletions .github/workflows/release-finalize.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
name: Finalize Release

on:
pull_request:
types: [closed]
branches:
- main

permissions:
contents: write
pull-requests: write

jobs:
finalize:
if: github.event.pull_request.merged == true && startsWith(github.event.pull_request.head.ref, 'release/')
runs-on: ubuntu-latest

steps:
- name: Extract version
id: meta
env:
BRANCH: ${{ github.event.pull_request.head.ref }}
run: echo "version=${BRANCH#release/}" >> $GITHUB_OUTPUT

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

- uses: actions/setup-node@v4
with:
node-version: '20'

- name: Extract release notes
env:
VERSION: ${{ steps.meta.outputs.version }}
run: node .github/scripts/extract-release-notes.js "$VERSION" > /tmp/release-notes.txt

- name: Create GitHub Release
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
VERSION: ${{ steps.meta.outputs.version }}
run: |
gh release create "$VERSION" \
--title "v$VERSION" \
--notes-file /tmp/release-notes.txt

- name: Configure git
run: |
git config user.name "github-actions[bot]"
git config user.email "github-actions[bot]@users.noreply.github.com"

- name: Create backport branch and merge
id: backport
env:
VERSION: ${{ steps.meta.outputs.version }}
run: |
git fetch origin develop
git checkout -b backport/$VERSION origin/develop

if git merge --no-edit origin/release/$VERSION; then
echo "merged=true" >> $GITHUB_OUTPUT
else
echo "::warning::Merge conflict on backport/$VERSION — resolve it manually."
git merge --abort
echo "merged=false" >> $GITHUB_OUTPUT
fi

- name: Push backport branch
if: steps.backport.outputs.merged == 'true'
env:
VERSION: ${{ steps.meta.outputs.version }}
run: git push origin backport/$VERSION

- name: Create backport PR
if: steps.backport.outputs.merged == 'true'
id: backport-pr
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
VERSION: ${{ steps.meta.outputs.version }}
run: |
URL=$(gh pr create \
--base develop \
--head backport/$VERSION \
--title "chore: backport $VERSION to develop" \
--body "Automated backport of release $VERSION to develop.")
echo "url=$URL" >> $GITHUB_OUTPUT

- name: Enable auto-merge on backport
if: steps.backport.outputs.merged == 'true'
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
VERSION: ${{ steps.meta.outputs.version }}
PR_URL: ${{ steps.backport-pr.outputs.url }}
run: |
gh pr merge backport/$VERSION --auto --merge \
|| echo "::warning::Auto-merge unavailable — merge $PR_URL manually."
70 changes: 70 additions & 0 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
name: Create Release

on:
workflow_dispatch:
inputs:
version:
description: 'Version to release (e.g. 1.9.0)'
required: true
type: string

permissions:
contents: write
pull-requests: write

jobs:
create-release:
runs-on: ubuntu-latest
env:
VERSION: ${{ inputs.version }}

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

- uses: actions/setup-node@v4
with:
node-version: '20'
cache: 'npm'

- name: Configure git
run: |
git config user.name "github-actions[bot]"
git config user.email "github-actions[bot]@users.noreply.github.com"

- name: Create release branch
run: git checkout -b release/$VERSION

- name: Bump version in package.json
run: npm version $VERSION --no-git-tag-version

- name: Update CHANGELOG.md
run: node .github/scripts/update-changelog.js

- name: Commit and push
run: |
git add package.json package-lock.json CHANGELOG.md
git commit -m "chore: release $VERSION"
git push origin release/$VERSION

- name: Create PR to main
id: pr
run: |
URL=$(gh pr create \
--base main \
--head release/$VERSION \
--title "release: $VERSION" \
--body "Automated release PR for v$VERSION. See [CHANGELOG.md](CHANGELOG.md) for details.")
echo "url=$URL" >> $GITHUB_OUTPUT
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}

- name: Enable auto-merge
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
PR_URL: ${{ steps.pr.outputs.url }}
run: |
gh pr merge release/$VERSION --auto --merge \
|| echo "::warning::Auto-merge unavailable — enable it in repo Settings → Pull Requests, or merge $PR_URL manually."
9 changes: 9 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,15 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

## [Unreleased]

## [1.9.0] - 2026-05-26

### Added
- Bulk import page for loading multiple transactions and transfers at once via a structured JSON payload
- AI-assisted import prompt that embeds the user's current accounts, categories and tags so an AI agent can generate correctly referenced IDs
- Real-time JSON validation panel showing record counts, affected accounts, field errors, and duplicate warnings before committing the import
- Automated release workflow using GitHub Actions: triggers from `develop`, creates a versioned release branch, bumps `package.json`, updates `CHANGELOG.md`, opens a PR to `main`, and auto-merges when checks pass
- Automated post-merge workflow that creates a GitHub Release with notes extracted from `CHANGELOG.md` and opens a backport PR to `develop`

## [1.8.0] - 2026-05-01

### Added
Expand Down
5 changes: 1 addition & 4 deletions index.html
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,7 @@
<head>
<meta charset="UTF-8" />
<link rel="icon" type="image/svg+xml" href="/icon.svg" />
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Manrope:wght@200..800&display=swap" rel="stylesheet">
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Platito</title>
</head>
<body>
Expand Down
10 changes: 10 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
"preview": "vite preview"
},
"dependencies": {
"@fontsource-variable/manrope": "^5.2.8",
"@mantine/carousel": "^8.3.9",
"@mantine/core": "^8.3.9",
"@mantine/dates": "^8.3.9",
Expand Down
Loading
Loading