mirror of
https://github.com/stan-smith/FossFLOW.git
synced 2025-12-25 23:49:10 -05:00
feat(ci): implemented automatic versioning plus releases
This commit is contained in:
10
.github/workflows/docker.yml
vendored
10
.github/workflows/docker.yml
vendored
@@ -6,12 +6,15 @@ on:
|
||||
types:
|
||||
- completed
|
||||
branches: ["main", "master"]
|
||||
push:
|
||||
tags:
|
||||
- 'v*.*.*'
|
||||
|
||||
jobs:
|
||||
build-and-push:
|
||||
runs-on: ubuntu-latest
|
||||
if: ${{ github.event.workflow_run.conclusion == 'success' }}
|
||||
|
||||
if: ${{ github.event.workflow_run.conclusion == 'success' || github.event_name == 'push' }}
|
||||
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v4
|
||||
@@ -34,6 +37,9 @@ jobs:
|
||||
type=ref,event=branch
|
||||
type=ref,event=pr
|
||||
type=sha,prefix={{branch}}-
|
||||
type=semver,pattern={{version}}
|
||||
type=semver,pattern={{major}}.{{minor}}
|
||||
type=semver,pattern={{major}}
|
||||
type=raw,value=latest,enable={{is_default_branch}}
|
||||
|
||||
- name: Build and push Docker image
|
||||
|
||||
44
.github/workflows/release.yml
vendored
Normal file
44
.github/workflows/release.yml
vendored
Normal file
@@ -0,0 +1,44 @@
|
||||
name: Release
|
||||
|
||||
on:
|
||||
workflow_run:
|
||||
workflows: ["Run Tests"]
|
||||
types:
|
||||
- completed
|
||||
branches: ["main", "master"]
|
||||
|
||||
permissions:
|
||||
contents: write
|
||||
issues: write
|
||||
pull-requests: write
|
||||
|
||||
jobs:
|
||||
release:
|
||||
name: Semantic Release
|
||||
runs-on: ubuntu-latest
|
||||
if: ${{ github.event.workflow_run.conclusion == 'success' }}
|
||||
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
persist-credentials: false
|
||||
|
||||
- name: Setup Node.js
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: '20'
|
||||
cache: 'npm'
|
||||
|
||||
- name: Install dependencies
|
||||
run: npm ci
|
||||
|
||||
- name: Verify build
|
||||
run: npm run build
|
||||
|
||||
- name: Run semantic-release
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
|
||||
run: npx semantic-release
|
||||
73
.releaserc.json
Normal file
73
.releaserc.json
Normal file
@@ -0,0 +1,73 @@
|
||||
{
|
||||
"branches": ["master", "main"],
|
||||
"repositoryUrl": "https://github.com/stan-smith/FossFLOW.git",
|
||||
"plugins": [
|
||||
[
|
||||
"@semantic-release/commit-analyzer",
|
||||
{
|
||||
"preset": "conventionalcommits",
|
||||
"releaseRules": [
|
||||
{ "type": "feat", "release": "minor" },
|
||||
{ "type": "fix", "release": "patch" },
|
||||
{ "type": "perf", "release": "patch" },
|
||||
{ "type": "revert", "release": "patch" },
|
||||
{ "type": "docs", "release": false },
|
||||
{ "type": "style", "release": false },
|
||||
{ "type": "chore", "release": false },
|
||||
{ "type": "refactor", "release": "patch" },
|
||||
{ "type": "test", "release": false },
|
||||
{ "type": "build", "release": false },
|
||||
{ "type": "ci", "release": false },
|
||||
{ "breaking": true, "release": "major" }
|
||||
]
|
||||
}
|
||||
],
|
||||
[
|
||||
"@semantic-release/release-notes-generator",
|
||||
{
|
||||
"preset": "conventionalcommits",
|
||||
"presetConfig": {
|
||||
"types": [
|
||||
{ "type": "feat", "section": "Features" },
|
||||
{ "type": "fix", "section": "Bug Fixes" },
|
||||
{ "type": "perf", "section": "Performance" },
|
||||
{ "type": "revert", "section": "Reverts" },
|
||||
{ "type": "docs", "section": "Documentation", "hidden": false },
|
||||
{ "type": "style", "section": "Styles", "hidden": true },
|
||||
{ "type": "chore", "section": "Chores", "hidden": true },
|
||||
{ "type": "refactor", "section": "Code Refactoring" },
|
||||
{ "type": "test", "section": "Tests", "hidden": true },
|
||||
{ "type": "build", "section": "Build System", "hidden": true },
|
||||
{ "type": "ci", "section": "CI/CD", "hidden": true }
|
||||
]
|
||||
}
|
||||
}
|
||||
],
|
||||
[
|
||||
"@semantic-release/changelog",
|
||||
{
|
||||
"changelogFile": "CHANGELOG.md",
|
||||
"changelogTitle": "# Changelog\n\nAll notable changes to FossFLOW will be documented in this file.\n\nThe format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),\nand this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html)."
|
||||
}
|
||||
],
|
||||
[
|
||||
"@semantic-release/exec",
|
||||
{
|
||||
"prepareCmd": "npm run update-version ${nextRelease.version}"
|
||||
}
|
||||
],
|
||||
"@semantic-release/github",
|
||||
[
|
||||
"@semantic-release/git",
|
||||
{
|
||||
"assets": [
|
||||
"CHANGELOG.md",
|
||||
"package.json",
|
||||
"package-lock.json",
|
||||
"packages/*/package.json"
|
||||
],
|
||||
"message": "chore(release): ${nextRelease.version} [skip ci]\n\n${nextRelease.notes}"
|
||||
}
|
||||
]
|
||||
]
|
||||
}
|
||||
@@ -217,22 +217,76 @@ npm run dev
|
||||
|
||||
### 4. Commit Your Changes
|
||||
|
||||
We follow conventional commits:
|
||||
**IMPORTANT**: We use [Conventional Commits](https://www.conventionalcommits.org/) with automated semantic versioning. Your commit messages directly control version bumps and changelog generation.
|
||||
|
||||
#### Commit Format
|
||||
|
||||
```
|
||||
<type>(<scope>): <subject>
|
||||
|
||||
[optional body]
|
||||
|
||||
[optional footer]
|
||||
```
|
||||
|
||||
#### Examples
|
||||
|
||||
```bash
|
||||
git commit -m "feat: add undo/redo functionality"
|
||||
git commit -m "fix: prevent menu from opening during drag"
|
||||
git commit -m "docs: update installation instructions"
|
||||
git commit -m "feat(connector)!: change default connector mode to click"
|
||||
```
|
||||
|
||||
Commit types:
|
||||
- `feat`: New feature
|
||||
- `fix`: Bug fix
|
||||
- `docs`: Documentation changes
|
||||
- `style`: Code style changes (formatting, etc.)
|
||||
- `refactor`: Code changes that neither fix bugs nor add features
|
||||
- `test`: Adding or updating tests
|
||||
- `chore`: Maintenance tasks
|
||||
#### Commit Types
|
||||
|
||||
**Version-bumping commits:**
|
||||
- `feat`: New feature (triggers MINOR version bump, e.g., 1.0.0 → 1.1.0)
|
||||
- `fix`: Bug fix (triggers PATCH version bump, e.g., 1.0.0 → 1.0.1)
|
||||
- `perf`: Performance improvement (triggers PATCH version bump)
|
||||
- `refactor`: Code refactoring (triggers PATCH version bump)
|
||||
|
||||
**Non-version-bumping commits:**
|
||||
- `docs`: Documentation only changes (no version bump)
|
||||
- `style`: Code style changes - formatting, whitespace (no version bump)
|
||||
- `test`: Adding or updating tests (no version bump)
|
||||
- `chore`: Maintenance tasks, dependency updates (no version bump)
|
||||
- `build`: Build system changes (no version bump)
|
||||
- `ci`: CI/CD configuration changes (no version bump)
|
||||
|
||||
**Breaking changes:**
|
||||
- Add `!` after type/scope OR add `BREAKING CHANGE:` in footer
|
||||
- Triggers MAJOR version bump (e.g., 1.0.0 → 2.0.0)
|
||||
- Example: `feat!: redesign node selection API`
|
||||
|
||||
#### Scopes (optional but recommended)
|
||||
|
||||
Common scopes in FossFLOW:
|
||||
- `connector`: Connector-related changes
|
||||
- `ui`: UI components and interactions
|
||||
- `storage`: Storage and persistence
|
||||
- `export`: Export/import functionality
|
||||
- `docker`: Docker and deployment
|
||||
- `i18n`: Internationalization
|
||||
|
||||
#### Breaking Change Examples
|
||||
|
||||
```bash
|
||||
# Option 1: Using ! in type
|
||||
git commit -m "feat(api)!: remove deprecated exportImage function"
|
||||
|
||||
# Option 2: Using footer
|
||||
git commit -m "feat: update node API
|
||||
|
||||
BREAKING CHANGE: Node.position is now an object with x,y properties instead of array"
|
||||
```
|
||||
|
||||
#### Release Notes
|
||||
|
||||
Your commits will automatically generate:
|
||||
- Version number based on commit types
|
||||
- Changelog with categorized changes
|
||||
- GitHub release notes
|
||||
|
||||
## Coding Standards
|
||||
|
||||
|
||||
194
docs/SEMANTIC_RELEASE.md
Normal file
194
docs/SEMANTIC_RELEASE.md
Normal file
@@ -0,0 +1,194 @@
|
||||
# Semantic Release Setup
|
||||
|
||||
This document explains how FossFLOW uses automated semantic versioning and releases.
|
||||
|
||||
## Overview
|
||||
|
||||
FossFLOW uses [semantic-release](https://github.com/semantic-release/semantic-release) to automate:
|
||||
- Version number calculation based on commit messages
|
||||
- CHANGELOG.md generation
|
||||
- GitHub release creation
|
||||
- Git tag creation
|
||||
- Docker image tagging with version numbers
|
||||
|
||||
## How It Works
|
||||
|
||||
### 1. Commit Messages Drive Versioning
|
||||
|
||||
When you commit code using conventional commits, the commit type determines the version bump:
|
||||
|
||||
| Commit Type | Version Bump | Example |
|
||||
|-------------|--------------|---------|
|
||||
| `feat:` | Minor (1.0.0 → 1.1.0) | New features |
|
||||
| `fix:` | Patch (1.0.0 → 1.0.1) | Bug fixes |
|
||||
| `perf:` | Patch (1.0.0 → 1.0.1) | Performance improvements |
|
||||
| `refactor:` | Patch (1.0.0 → 1.0.1) | Code refactoring |
|
||||
| `feat!:` or `BREAKING CHANGE:` | Major (1.0.0 → 2.0.0) | Breaking changes |
|
||||
| `docs:`, `style:`, `test:`, `chore:` | No bump | Non-code changes |
|
||||
|
||||
### 2. Automated Workflow
|
||||
|
||||
When you push to `master` branch:
|
||||
|
||||
1. **Tests run** (via `.github/workflows/test.yml`)
|
||||
2. **If tests pass**, semantic-release workflow triggers (`.github/workflows/release.yml`)
|
||||
3. **Semantic-release analyzes** commits since last release
|
||||
4. **If version bump needed**:
|
||||
- Calculates new version number
|
||||
- Updates `package.json` files in all workspace packages
|
||||
- Generates CHANGELOG.md
|
||||
- Creates git tag (e.g., `v1.2.0`)
|
||||
- Commits changes with `[skip ci]`
|
||||
- Pushes tag to GitHub
|
||||
- Creates GitHub release with notes
|
||||
5. **Docker workflow triggers** on new tag (`.github/workflows/docker.yml`)
|
||||
6. **Docker images are tagged** with:
|
||||
- `latest`
|
||||
- `1.2.0` (full version)
|
||||
- `1.2` (major.minor)
|
||||
- `1` (major only)
|
||||
|
||||
### 3. Multiple Package Versioning
|
||||
|
||||
FossFLOW is a monorepo with multiple packages. All packages are versioned together:
|
||||
- Root `package.json`
|
||||
- `packages/fossflow-lib/package.json`
|
||||
- `packages/fossflow-app/package.json`
|
||||
- `packages/fossflow-backend/package.json`
|
||||
|
||||
The `scripts/update-version.js` script syncs version numbers across all packages.
|
||||
|
||||
## Configuration Files
|
||||
|
||||
### `.releaserc.json`
|
||||
|
||||
Main semantic-release configuration:
|
||||
- Defines which branches trigger releases (`master`, `main`)
|
||||
- Configures commit analysis rules
|
||||
- Sets up changelog generation
|
||||
- Defines which files to commit
|
||||
|
||||
### `.github/workflows/release.yml`
|
||||
|
||||
GitHub Actions workflow that:
|
||||
- Runs after tests pass
|
||||
- Executes semantic-release
|
||||
- Uses `GITHUB_TOKEN` for GitHub API access
|
||||
- Uses `NPM_TOKEN` for npm publishing (optional)
|
||||
|
||||
### `scripts/update-version.js`
|
||||
|
||||
Node.js script that updates version numbers in all package.json files simultaneously.
|
||||
|
||||
## Example Release Flow
|
||||
|
||||
### Scenario: Adding a New Feature
|
||||
|
||||
```bash
|
||||
# Make your changes
|
||||
git add .
|
||||
git commit -m "feat(connector): add multi-point connector routing"
|
||||
git push origin master
|
||||
```
|
||||
|
||||
**Result:**
|
||||
- Tests run and pass
|
||||
- Semantic-release detects `feat:` commit
|
||||
- Version bumps from 1.0.5 → 1.1.0
|
||||
- CHANGELOG.md updated with new entry
|
||||
- Git tag `v1.1.0` created
|
||||
- GitHub release created
|
||||
- Docker images tagged: `1.1.0`, `1.1`, `1`, `latest`
|
||||
|
||||
### Scenario: Fixing a Bug
|
||||
|
||||
```bash
|
||||
git commit -m "fix(export): resolve image export quality issue"
|
||||
git push origin master
|
||||
```
|
||||
|
||||
**Result:**
|
||||
- Version bumps from 1.1.0 → 1.1.1
|
||||
- Patch release created
|
||||
|
||||
### Scenario: Breaking Change
|
||||
|
||||
```bash
|
||||
git commit -m "feat(api)!: redesign node creation API
|
||||
|
||||
BREAKING CHANGE: createNode() now requires nodeType parameter"
|
||||
git push origin master
|
||||
```
|
||||
|
||||
**Result:**
|
||||
- Version bumps from 1.1.1 → 2.0.0
|
||||
- Major release created with breaking change highlighted
|
||||
|
||||
### Scenario: Documentation Update
|
||||
|
||||
```bash
|
||||
git commit -m "docs: update installation instructions"
|
||||
git push origin master
|
||||
```
|
||||
|
||||
**Result:**
|
||||
- No version bump
|
||||
- No release created
|
||||
- Changes still merged to master
|
||||
|
||||
## Manual Testing Locally
|
||||
|
||||
You can test semantic-release locally without publishing:
|
||||
|
||||
```bash
|
||||
# Dry run (no changes made)
|
||||
npx semantic-release --dry-run
|
||||
|
||||
# See what version would be released
|
||||
npx semantic-release --dry-run --no-ci
|
||||
```
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### No Release Created
|
||||
|
||||
Check if:
|
||||
- Commits follow conventional commit format
|
||||
- Commits include version-bumping types (`feat`, `fix`, etc.)
|
||||
- Tests passed successfully
|
||||
- You're on the `master` or `main` branch
|
||||
|
||||
### Version Not Updated
|
||||
|
||||
Ensure:
|
||||
- `scripts/update-version.js` has execute permissions
|
||||
- Script is referenced in `.releaserc.json` under `@semantic-release/exec`
|
||||
|
||||
### Docker Not Tagged
|
||||
|
||||
Verify:
|
||||
- Git tag was created successfully
|
||||
- Docker workflow has permission to run
|
||||
|
||||
## Additional Resources
|
||||
|
||||
- [Conventional Commits](https://www.conventionalcommits.org/)
|
||||
- [Semantic Versioning](https://semver.org/)
|
||||
- [Semantic Release Documentation](https://semantic-release.gitbook.io/semantic-release/)
|
||||
- [Keep a Changelog](https://keepachangelog.com/)
|
||||
|
||||
## Maintaining This System
|
||||
|
||||
### Updating Semantic Release
|
||||
|
||||
```bash
|
||||
npm update semantic-release @semantic-release/changelog @semantic-release/git @semantic-release/exec
|
||||
```
|
||||
|
||||
### Adding New Commit Types
|
||||
|
||||
Edit `.releaserc.json` under `releaseRules` to add custom commit type behaviors.
|
||||
|
||||
### Changing Release Branch
|
||||
|
||||
Edit `.releaserc.json` and `.github/workflows/release.yml` to target different branches.
|
||||
6021
package-lock.json
generated
6021
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
11
package.json
11
package.json
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "fossflow-monorepo",
|
||||
"version": "1.0.0",
|
||||
"version": "1.0.5",
|
||||
"private": true,
|
||||
"description": "Monorepo for FossFLOW diagram editor and library",
|
||||
"workspaces": [
|
||||
@@ -19,13 +19,20 @@
|
||||
"clean": "npm run clean --workspaces --if-present && rm -rf node_modules",
|
||||
"publish:lib": "npm run build:lib && npm publish --workspace=packages/fossflow-lib",
|
||||
"docker:build": "docker build -t fossflow:local .",
|
||||
"docker:run": "docker compose -f compose.dev.yml up"
|
||||
"docker:run": "docker compose -f compose.dev.yml up",
|
||||
"update-version": "node scripts/update-version.js",
|
||||
"semantic-release": "semantic-release"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@semantic-release/changelog": "^6.0.3",
|
||||
"@semantic-release/exec": "^7.1.0",
|
||||
"@semantic-release/git": "^10.0.1",
|
||||
"@types/node": "^18.19.0",
|
||||
"@types/react": "^18.3.1",
|
||||
"@types/react-dom": "^18.3.0",
|
||||
"conventional-changelog-conventionalcommits": "^9.1.0",
|
||||
"cross-env": "^10.0.0",
|
||||
"semantic-release": "^24.2.9",
|
||||
"typescript": "^5.3.3"
|
||||
},
|
||||
"engines": {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "fossflow-app",
|
||||
"version": "1.0.0",
|
||||
"version": "1.0.5",
|
||||
"private": true,
|
||||
"description": "Progressive Web App for creating isometric diagrams",
|
||||
"dependencies": {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "fossflow-backend",
|
||||
"version": "1.0.0",
|
||||
"version": "1.0.5",
|
||||
"description": "Optional backend server for FossFLOW persistent storage",
|
||||
"main": "server.js",
|
||||
"type": "module",
|
||||
@@ -17,4 +17,4 @@
|
||||
"devDependencies": {
|
||||
"nodemon": "^3.0.1"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
47
scripts/update-version.js
Executable file
47
scripts/update-version.js
Executable file
@@ -0,0 +1,47 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
/**
|
||||
* Updates version numbers across all packages in the monorepo
|
||||
* Used by semantic-release to sync versions
|
||||
*/
|
||||
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
|
||||
const version = process.argv[2];
|
||||
|
||||
if (!version) {
|
||||
console.error('Error: Version number required');
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
console.log(`Updating all packages to version ${version}...`);
|
||||
|
||||
// List of package.json files to update
|
||||
const packageFiles = [
|
||||
'package.json',
|
||||
'packages/fossflow-lib/package.json',
|
||||
'packages/fossflow-app/package.json',
|
||||
'packages/fossflow-backend/package.json'
|
||||
];
|
||||
|
||||
packageFiles.forEach(file => {
|
||||
const filePath = path.join(process.cwd(), file);
|
||||
|
||||
if (!fs.existsSync(filePath)) {
|
||||
console.warn(`Warning: ${file} not found, skipping...`);
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
const packageJson = JSON.parse(fs.readFileSync(filePath, 'utf8'));
|
||||
packageJson.version = version;
|
||||
fs.writeFileSync(filePath, JSON.stringify(packageJson, null, 2) + '\n');
|
||||
console.log(`Updated ${file} to ${version}`);
|
||||
} catch (error) {
|
||||
console.error(`Error updating ${file}:`, error.message);
|
||||
process.exit(1);
|
||||
}
|
||||
});
|
||||
|
||||
console.log('Version update complete!');
|
||||
Reference in New Issue
Block a user