diff options
| author | 2026-01-16 12:59:29 +0800 | |
|---|---|---|
| committer | 2026-01-16 12:59:29 +0800 | |
| commit | 5c875de340009692ef47f1f6886f721adf8e4637 (patch) | |
| tree | 879b1c49a04a463e2887386c399a5f9f80ac7fb1 | |
| parent | d02dd4df19e763a4dc94950e3a929ea454dfa500 (diff) | |
| parent | 77031c3f21bd100acbac838d0b02f5f04bf66188 (diff) | |
| download | DropOut-5c875de340009692ef47f1f6886f721adf8e4637.tar.gz DropOut-5c875de340009692ef47f1f6886f721adf8e4637.zip | |
Merge pull request #50 from BegoniaHe/docs/copilot-instructions
| -rw-r--r-- | .github/agents/commit.agent.md | 260 | ||||
| -rw-r--r-- | .github/copilot-instructions.md | 252 | ||||
| -rw-r--r-- | .github/instructions/commit.instructions.md | 38 | ||||
| -rw-r--r-- | .github/references/git/conventional-commit.md | 153 |
4 files changed, 703 insertions, 0 deletions
diff --git a/.github/agents/commit.agent.md b/.github/agents/commit.agent.md new file mode 100644 index 0000000..13372e5 --- /dev/null +++ b/.github/agents/commit.agent.md @@ -0,0 +1,260 @@ +# Commit Helper Agent + +You are a Git commit message assistant following the Conventional Commits specification. + +## Task + +Generate well-structured commit messages based on staged changes or user descriptions. + +## Commit Format + +``` +<type>[optional scope]: <description> + +[optional body] + +[optional footer(s)] +``` + +## Workflow Rules + +### Language Policy + +1. **Commit message language**: ALWAYS write in **English** unless user explicitly requests another language +2. **Explanation language**: Use the **same language as user's request** +3. **Translation rule**: If commit language ≠ user's language → provide explanation + - User speaks Chinese + English commit → Explain in Chinese + - User speaks English + Chinese commit → Explain in English + - User speaks English + English commit → No extra explanation needed + - User speaks Chinese + Chinese commit → No extra explanation needed + +### Confirmation Policy + +**ALWAYS ask for confirmation before committing** unless user explicitly says: +- "commit directly" +- "commit immediately" +- "just commit it" + +**Standard flow**: +1. Generate commit message +2. Explain what it means (in user's language if different from English) +3. Show the command: `git commit -m "..."` +4. Ask: "Proceed with this commit?" (in user's language) +5. Only execute if user confirms + +### Step 0: Check Current Branch (REQUIRED) + +**Before doing anything**, check the current branch and validate: + +1. Run `git branch --show-current` to get current branch name +2. Run `git status` to see if there are any changes +3. **Validate branch naming**: + - Feature work → Should be on `feat/*` or `feature/*` branch + - Bug fixes → Should be on `fix/*` or `bugfix/*` branch + - Documentation → Should be on `docs/*` branch + - Refactoring → Should be on `refactor/*` branch + - Hotfix → Should be on `hotfix/*` branch + +4. **Branch validation rules**: + - If on `main` or `master` → WARN: "You're on the main branch. Consider creating a feature branch first." + - If branch name doesn't match change type → WARN: "Current branch is `X`, but changes look like `Y` type. Continue or switch branch?" + - If branch name matches change type → Proceed silently + +**Example warnings**: +``` +On main + adding feature: + "You're on main branch. Consider: git checkout -b feat/your-feature-name" + +On feat/ui-update + fixing bug: + "Current branch is feat/ui-update but changes look like a bug fix. + Consider: git checkout -b fix/bug-name or continue on current branch?" + +On docs/readme + adding code: + "Current branch is docs/readme but changes include code modifications. + Consider switching to feat/* or fix/* branch?" +``` + +If user chooses to continue, proceed to generate commit message as normal. + +### Step 1: Analyze Changes + +When user asks for a commit message: + +1. **If changes are staged**: Run `git diff --cached --stat` to see what files changed +2. **If specific files mentioned**: Run `git diff <file>` to understand the changes +3. **If user describes changes**: Use their description directly + +### Step 2: Determine Type + +| Type | When to Use | +|------|-------------| +| `feat` | New feature for the user | +| `fix` | Bug fix | +| `docs` | Documentation only changes | +| `style` | Formatting, missing semicolons, etc. (no code change) | +| `refactor` | Code change that neither fixes a bug nor adds a feature | +| `perf` | Performance improvement | +| `test` | Adding or updating tests | +| `build` | Changes to build system or dependencies | +| `ci` | CI configuration changes | +| `chore` | Other changes that don't modify src or test files | +| `revert` | Reverts a previous commit | + +**Quick Decision Tree**: +``` +Changes involve... +├─ New user-facing feature? → feat +├─ Fix user-reported bug? → fix +├─ Only docs/comments? → docs +├─ Internal refactor? → refactor +├─ Performance improvement? → perf +└─ Breaking API change? → Add ! + BREAKING CHANGE footer +``` + +### Step 3: Determine Scope (Optional) + +Scope should be a noun describing the section of codebase: +- `feat(gui)`: GUI-related feature +- `fix(memory)`: Memory-related fix +- `docs(api)`: API documentation +- `refactor(core)`: Core module refactoring + +### Step 4: Write Description + +- Use imperative mood: "add" not "added" or "adds" +- Don't capitalize first letter +- No period at the end +- Keep under 50 characters + +**Common mistakes**: +- ❌ `Added new feature` → ✅ `add new feature` +- ❌ `Fix bug.` → ✅ `fix authentication issue` +- ❌ Multiple concerns → Split into separate commits + +### Step 5: Add Body (If Needed) + +- Explain WHAT and WHY, not HOW +- Wrap at 72 characters +- Separate from description with blank line + +### Step 6: Add Footer (If Needed) + +**Breaking Changes**: +``` +BREAKING CHANGE: <description> +``` + +**AI-Generated Commits** (REQUIRED for AI assistance): +``` +Reviewed-by: [MODEL_NAME] +``` + +**Issue References**: +``` +Refs #123 +Closes #456 +``` + +## Examples + +### Simple Feature +``` +feat(gui): add transparent window support +``` + +### Bug Fix with Body +``` +fix(memory): resolve index memory leak + +The index was not being properly released when switching +between different memory contexts, causing gradual memory +growth over extended sessions. + +Reviewed-by: [MODEL_NAME] +``` + +### Breaking Change +``` +refactor(core)!: restructure plugin system + +Plugin API now requires explicit registration instead of +auto-discovery. This improves startup time but requires +migration of existing plugins. + +BREAKING CHANGE: Plugin API signature changed from +`register()` to `register(manifest: PluginManifest)` + +Reviewed-by: [MODEL_NAME] +``` + +### Documentation Update +``` +docs: update PRD with new interaction flow + +Reviewed-by: [MODEL_NAME] +``` + +### Multiple Changes (use most significant type) +``` +feat(state): add mood decay system with persistence + +- Implement time-based mood decay algorithm +- Add SQLite persistence for mood state +- Create mood recovery mechanics + +Reviewed-by: [MODEL_NAME] +Refs #42 +``` + +## Commands + +When user says "create commit" or "commit message": + +1. **[REQUIRED]** Check current branch and validate (Step 0) +2. Ask what changes to commit (or analyze staged changes) +3. Generate commit message in **English** (following Conventional Commits format) +4. **If commit language is not user's language**: Explain the commit in user's language +5. **Always ask for confirmation** before executing (unless user said "commit directly" or similar) +6. If confirmed, run: `git commit -m "<message>"` + +**Example 1 (Chinese user, English commit)**: +``` +User: "帮我提交这个功能" +AI: "建议的提交信息: + feat(gui): add transparent window support + + 这个提交添加了透明窗口功能。是否执行此提交?" +User: "是" or "直接提交" or "y" +AI: [executes git commit] +``` + +**Example 2 (English user, Chinese commit)**: +``` +User: "write a Chinese commit for this feature" +AI: "Suggested commit: + feat(gui): 添加透明窗口支持 + + This commit adds transparent window support. Proceed?" +User: "yes" or "commit directly" or "y" +AI: [executes git commit] +``` + +**Example 3 (English user, English commit - no explanation)**: +``` +User: "commit this feature" +AI: "Suggested commit: + feat(gui): add transparent window support + + Proceed with this commit?" +User: "yes" or "commit directly" or "y" +AI: [executes git commit] +``` + +When user says "amend commit": +```bash +git commit --amend -m "<new message>" +``` + +## References + +- Commit spec: <a>.github/references/git/conventional-commit.md</a>
\ No newline at end of file diff --git a/.github/copilot-instructions.md b/.github/copilot-instructions.md new file mode 100644 index 0000000..15acef6 --- /dev/null +++ b/.github/copilot-instructions.md @@ -0,0 +1,252 @@ +# DropOut Minecraft Launcher - AI Development Guide + +## Architecture Overview + +**DropOut** is a Tauri v2 desktop application combining: +- **Backend (Rust)**: Game launching, asset management, authentication, mod loader installation +- **Frontend (Svelte 5)**: Reactive UI with Tailwind CSS 4 and particle effects +- **Communication**: Tauri commands (invoke) and events (emit/listen) + +**Key Data Flow**: Frontend invokes Rust commands → Rust processes/downloads → Rust emits progress events → Frontend updates UI via listeners + +## Project Structure + +``` +src-tauri/ # Rust backend + src/ + main.rs # Tauri commands, game launch logic, event emissions + core/ # Core modules (auth, downloader, fabric, forge, java, etc.) + mod.rs # Module declarations + auth.rs # Microsoft OAuth + offline auth via Device Code Flow + downloader.rs # Concurrent downloads with progress tracking, resumable downloads + fabric.rs # Fabric loader installation and version management + forge.rs # Forge installer execution and profile generation + java.rs # Java detection, Adoptium download/install, catalog management + config.rs # LauncherConfig (memory, java path, download threads) + game_version.rs # Minecraft version JSON parsing + manifest.rs # Mojang version manifest fetching + maven.rs # Maven artifact URL resolution for mod loaders + rules.rs # OS/feature rule evaluation for libraries + version_merge.rs # Parent version inheritance merging + utils/ + zip.rs # Native library extraction +ui/ # Svelte 5 frontend + src/ + App.svelte # Main app component, enforces dark mode + stores/ # Svelte 5 runes state management ($state, $effect) + auth.svelte.ts # Authentication state with device code polling + game.svelte.ts # Game state (running, logs) + settings.svelte.ts # Settings + Java detection + ui.svelte.ts # UI state (toasts, modals, active view) + components/ # UI components (HomeView, VersionsView, SettingsView, etc.) + lib/ # Reusable components (DownloadMonitor, GameConsole) +``` + +## Critical Development Workflows + +### Development Mode +```bash +cargo tauri dev # Starts frontend dev server (Vite on :5173) + Tauri window +``` +- Frontend uses Vite with hot reload +- Backend recompiles on Rust file changes +- Console shows both Rust stdout and frontend Vite logs + +### Building +```bash +cd ui && pnpm install # Install frontend dependencies +cargo tauri build # Produces platform bundles in src-tauri/target/release/bundle/ +``` + +### Pre-commit Checks +- Uses `pre-commit` with Python (configured in `pyproject.toml`) +- Hooks: JSON/TOML/YAML validation, Ruff for Python files +- Run manually: `pre-commit run --all-files` + +### Testing +- CI workflow: [`.github/workflows/test.yml`](.github/workflows/test.yml) tests on Ubuntu, Arch (Wayland), Windows, macOS +- Local: `cargo test` (no comprehensive test suite exists yet) + +## Project-Specific Patterns & Conventions + +### Tauri Command Pattern +Commands in [`main.rs`](../src-tauri/src/main.rs) follow this structure: +```rust +#[tauri::command] +async fn command_name( + window: Window, + state: State<'_, SomeState>, + param: Type, +) -> Result<ReturnType, String> { + emit_log!(window, "Status message"); // Emits "launcher-log" event + // ... async logic + Ok(result) +} +``` +**Register in `main()`:** +```rust +tauri::Builder::default() + .invoke_handler(tauri::generate_handler![command_name, ...]) +``` + +### Event Communication +**Rust → Frontend (Progress/Logs):** +```rust +// In Rust +window.emit("launcher-log", "Downloading assets...")?; +window.emit("download-progress", progress_struct)?; +``` +```typescript +// In Frontend (Svelte) +import { listen } from "@tauri-apps/api/event"; +const unlisten = await listen("launcher-log", (event) => { + console.log(event.payload); +}); +``` + +**Frontend → Rust (Commands):** +```typescript +import { invoke } from "@tauri-apps/api/core"; +const result = await invoke("start_game", { versionId: "1.20.4" }); +``` + +### State Management (Rust) +Global state via Tauri's managed state: +```rust +pub struct ConfigState { + pub config: Mutex<LauncherConfig>, + pub file_path: PathBuf, +} +// In main: +.manage(ConfigState::new(&app_handle)) +// In commands: +config_state: State<'_, ConfigState> +``` + +### State Management (Svelte 5) +Uses **Svelte 5 runes** (not stores): +```typescript +// stores/auth.svelte.ts +export class AuthState { + currentAccount = $state<Account | null>(null); // Reactive state + isLoginModalOpen = $state(false); + + $effect(() => { // Side effects + // Runs when dependencies change + }); +} +// Export singleton +export const authState = new AuthState(); +``` + +### Version Inheritance System +Modded versions (Fabric/Forge) use `inheritsFrom` field: +- [`version_merge.rs`](../src-tauri/src/core/version_merge.rs): Merges parent vanilla JSON with mod loader JSON +- [`manifest.rs`](../src-tauri/src/core/manifest.rs): `load_version()` recursively resolves inheritance +- Libraries, assets, arguments are merged from parent + modded version + +### Microsoft Authentication Flow +Uses **Device Code Flow** (no redirect needed): +1. Frontend calls `start_microsoft_login()` → gets device code + URL +2. User visits URL in browser, enters code +3. Frontend polls `complete_microsoft_login()` with device code +4. Rust exchanges code → MS token → Xbox Live → XSTS → Minecraft token +5. Stores MS refresh token for auto-refresh (see [`auth.rs`](../src-tauri/src/core/auth.rs)) + +**Client ID**: Uses ATLauncher's public client ID (`c36a9fb6-4f2a-41ff-90bd-ae7cc92031eb`) + +### Download System +[`downloader.rs`](../src-tauri/src/core/downloader.rs) features: +- **Concurrent downloads** with semaphore (configurable threads) +- **Resumable downloads**: `.part` + `.part.meta` files track progress +- **Multi-segment downloads**: Large files split into segments downloaded in parallel +- **Checksum verification**: SHA1/SHA256 validation +- **Progress events**: Emits `download-progress` with file name, bytes, ETA +- **Queue persistence**: Java downloads saved to `download_queue.json` for resumption + +### Java Management +[`java.rs`](../src-tauri/src/core/java.rs): +- **Auto-detection**: Scans `/usr/lib/jvm`, `/Library/Java`, `JAVA_HOME`, `PATH` +- **Adoptium API**: Fetches available JDK/JRE versions for current OS/arch +- **Catalog caching**: `java_catalog.json` cached for 24 hours +- **Installation**: Downloads, extracts to `app_data_dir/java/<version>` +- **Cancellation**: Global `AtomicBool` flag for download cancellation + +### Error Handling +- Commands return `Result<T, String>` (String for JS-friendly errors) +- Use `.map_err(|e| e.to_string())` to convert errors +- Emit detailed error logs: `emit_log!(window, format!("Error: {}", e))` + +### File Paths +- **Game directory**: `app_handle.path().app_data_dir()` (~/.local/share/com.dropout.launcher on Linux) +- **Versions**: `game_dir/versions/<version_id>/<version_id>.json` +- **Libraries**: `game_dir/libraries/<maven-path>` +- **Assets**: `game_dir/assets/objects/<hash[0..2]>/<hash>` +- **Config**: `game_dir/config.json` +- **Accounts**: `game_dir/accounts.json` + +## Integration Points + +### External APIs +- **Mojang**: `https://piston-meta.mojang.com/mc/game/version_manifest_v2.json` +- **Fabric Meta**: `https://meta.fabricmc.net/v2/` +- **Forge Maven**: `https://maven.minecraftforge.net/` +- **Adoptium**: `https://api.adoptium.net/v3/` +- **GitHub Releases**: `https://api.github.com/repos/HsiangNianian/DropOut/releases` + +### Native Dependencies +- **Linux**: `libwebkit2gtk-4.1-dev`, `libgtk-3-dev` (see [test.yml](../.github/workflows/test.yml)) +- **macOS**: System WebKit via Tauri +- **Windows**: WebView2 runtime (bundled) + +## Common Tasks + +### Adding a New Tauri Command +1. Define function in [`main.rs`](../src-tauri/src/main.rs) with `#[tauri::command]` +2. Add to `.invoke_handler(tauri::generate_handler![..., new_command])` +3. Call from frontend: `invoke("new_command", { args })` + +### Adding a New UI View +1. Create component in `ui/src/components/NewView.svelte` +2. Import in [`App.svelte`](../ui/src/App.svelte) +3. Add navigation in [`Sidebar.svelte`](../ui/src/components/Sidebar.svelte) +4. Update `uiState.activeView` in [`ui.svelte.ts`](../ui/src/stores/ui.svelte.ts) + +### Emitting Progress Events +Use `emit_log!` macro for launcher logs: +```rust +emit_log!(window, format!("Downloading {}", filename)); +``` +For custom events: +```rust +window.emit("custom-event", payload)?; +``` + +### Handling Placeholders in Arguments +Game arguments may contain `${variable}` placeholders. Use the `has_unresolved_placeholder()` helper to skip malformed arguments (see [`main.rs:57-67`](../src-tauri/src/main.rs#L57-L67)). + +## Important Notes + +- **Dark mode enforced**: [`App.svelte`](../ui/src/App.svelte) force-adds `dark` class regardless of system preference +- **Svelte 5 syntax**: Use `$state`, `$derived`, `$effect` (not `writable` stores) +- **No CREATE_NO_WINDOW on non-Windows**: Use `#[cfg(target_os = "windows")]` for Windows-specific code +- **Version IDs**: Fabric uses `fabric-loader-<loader>-<game>`, Forge uses `<game>-forge-<loader>` +- **Mod loader libraries**: Don't have `downloads.artifact`, use Maven resolution via [`maven.rs`](../src-tauri/src/core/maven.rs) +- **Native extraction**: Extract to `versions/<version>/natives/`, exclude META-INF +- **Classpath order**: Libraries → Client JAR (see [`main.rs:437-453`](../src-tauri/src/main.rs#L437-L453)) + +## Debugging Tips + +- **Rust logs**: Check terminal running `cargo tauri dev` +- **Frontend logs**: Browser devtools (Ctrl+Shift+I in Tauri window) +- **Game logs**: Listen to `game-stdout`/`game-stderr` events +- **Download issues**: Check `download-progress` events, validate SHA1 hashes +- **Auth issues**: MS WAF blocks requests without User-Agent (see [`auth.rs:6-12`](../src-tauri/src/core/auth.rs#L6-L12)) + +## Version Compatibility + +- **Rust**: Edition 2021, requires Tauri v2 dependencies +- **Node.js**: pnpm for frontend (uses Rolldown-based Vite fork) +- **Tauri**: v2.9+ +- **Svelte**: v5.46+ (runes mode) +- **Java**: Supports detection of Java 8-23+, recommends Java 17+ for modern Minecraft diff --git a/.github/instructions/commit.instructions.md b/.github/instructions/commit.instructions.md new file mode 100644 index 0000000..cc29e9c --- /dev/null +++ b/.github/instructions/commit.instructions.md @@ -0,0 +1,38 @@ +--- +applyTo: "**" +--- + +# Commit Helper Instructions + +When user requests commit help → Follow <a>.github/agents/commit.agent.md</a> + +## Critical Rules + +1. **Language**: Commit message ALWAYS in **English** (unless user specifies otherwise) +2. **Explanation**: Use **user's request language** ONLY when commit language differs + - Chinese user + English commit → Explain in Chinese + - English user + Chinese commit → Explain in English + - Same language → No extra explanation needed +3. **Confirmation**: ALWAYS ask before committing (unless "commit directly" requested) + +## Quick Reference + +**Format**: `<type>[scope]: <description>` + +**Common types**: `feat` `fix` `docs` `refactor` `perf` `test` `chore` + +**AI commits MUST include**: `Reviewed-by: [MODEL_NAME]` + +**Spec**: <a>.github/references/git/conventional-commit.md</a> + +## Common Mistakes + +| Wrong | Right | +|-------|-------| +| `feat: Added feature` | `feat: add feature` (imperative) | +| `Fix bug.` | `fix: resolve auth issue` (lowercase, no period) | +| `feat: add A, refactor B, update C` | Split into 3 commits | + +## User Triggers + +"create commit", "commit message", "conventional commit"
\ No newline at end of file diff --git a/.github/references/git/conventional-commit.md b/.github/references/git/conventional-commit.md new file mode 100644 index 0000000..a9e27bc --- /dev/null +++ b/.github/references/git/conventional-commit.md @@ -0,0 +1,153 @@ +# What is Conventional Commits? + +> A standard for writing commit messages. + +## Table of Contents + +- [What is Conventional Commits?](#what-is-conventional-commits) +- [Examples](#examples) +- [Rules](#rules) +- [Why Should We Use It?](#why-should-we-use-it) +- [Changelog Generation](#changelog-generation) +- [Bump the Version Precisely](#bump-the-version-precisely) +- [How About Squash Merges?](#how-about-squash-merges) + +The Conventional Commits specification is a lightweight convention on top of commit messages. It provides an easy set of rules for creating an explicit commit history; which makes it easier to write automated tools on top of. This convention dovetails with [SemVer](https://semver.org/), by describing the features, fixes, and breaking changes made in commit messages. + +```text +<type>[optional scope]: <description> + +[optional body] + +[optional footer(s)] +``` + +## Examples + +> Commit message with scope + +```text +feat(SHOPPER-000): introduce OrderMonitor v2 +``` + +> Commit message with breaking change + +```text +refactor!: drop support for Node 6 +``` + +> Commit message with footer and breaking change + +```text +feat: enhance error handling + +BREAKING CHANGE: Modified every error message and added the error key +``` + +> Commit message with multi-paragraph body and multiple footers + +```text +fix(SHOPPER-000): correct minor typos in code + +see the issue for details + +on typos fixed. + +Reviewed-by: Z +Refs #133 +``` + +> Here reviewer should be replaced with the actual name of the reviewer or the **model name card** like "GPT-4o mini" by default. + +## Rules + +The key words **“MUST”, “MUST NOT”, “REQUIRED”, “SHALL”, “SHALL NOT”, “SHOULD”, “SHOULD NOT”, “RECOMMENDED”, “MAY”, and “OPTIONAL”** in this document are to be interpreted as described in [RFC 2119](https://www.ietf.org/rfc/rfc2119.txt). + +- Commits MUST be prefixed with a type, which consists of a noun, feat, fix, etc., followed by the OPTIONAL scope, OPTIONAL !, and REQUIRED terminal colon and space. +- The type feat MUST be used when a commit adds a new feature to your application or library. +- The type fix MUST be used when a commit represents a bug fix for your application. +- A scope MAY be provided after a type. A scope MUST consist of a noun describing a section of the codebase surrounded by parenthesis, e.g., fix(parser): +- A description MUST immediately follow the colon and space after the type/scope prefix. The description is a short summary of the code changes, e.g., fix: array parsing issue when multiple spaces were contained in string. +- A longer commit body MAY be provided after the short description, providing additional contextual information about the code changes. The body MUST begin one blank line after the description. +- A commit body is free-form and MAY consist of any number of newline separated paragraphs. +- One or more footers MAY be provided one blank line after the body. Each footer MUST consist of a word token, followed by either a :<space> or <space># separator, followed by a string value (this is inspired by the git trailer convention). +- A footer’s token MUST use - in place of whitespace characters, e.g., Acked-by (this helps differentiate the footer section from a multi-paragraph body). An exception is made for BREAKING CHANGE, which MAY also be used as a token. +- A footer’s value MAY contain spaces and newlines, and parsing MUST terminate when the next valid footer token/separator pair is observed. +- Breaking changes MUST be indicated in the type/scope prefix of a commit, or as an entry in the footer. +- If included as a footer, a breaking change MUST consist of the uppercase text BREAKING CHANGE, followed by a colon, space, and description, e.g., BREAKING CHANGE: environment variables now take precedence over config files. +If included in the type/scope prefix, breaking changes MUST be indicated by a ! immediately before the :. If ! is used, BREAKING CHANGE: MAY be omitted from the footer section, and the commit description SHALL be used to describe the breaking change. +- Types other than feat and fix MAY be used in your commit messages, e.g., docs: updated ref docs. +- The units of information that make up Conventional Commits MUST NOT be treated as case sensitive by implementors, with the exception of BREAKING CHANGE which MUST be uppercase. +- BREAKING-CHANGE MUST be synonymous with BREAKING CHANGE, when used as a token in a footer. + +## Why Should We Use It? + +- Automatic changelog generation +- The context information that refers to business initiative when it's needed +- Noticeable breaking changes +- Forces us to write better commit messages (no more vague 'fix', 'refactor' commits) +- Bumping version precisely +- Making it easier to contribute to the projects by allowing contributors to explore a more structured commit history + +## Changelog Generation + +### Why Changelog? + +A changelog is a file that contains a curated, chronologically ordered list of notable changes for each version of a project to make it easier for users and contributors. + +For more information, see the [Keep a Changelog](https://keepachangelog.com/) standard. + +### Why Generate Changelogs via Conventional Commits? + +It's hard to maintain changelogs by hand and most of the time it fails. Manual changelog updates lead to: + +- Discrepancy between docs and actual versions +- Missing breaking changes +- Outdated changelogs + +You can automate the process of generating changelogs via GitHub Actions or locally via git hooks, which speeds up the process significantly. + +## Bump the Version Precisely + +### Benefits of Bumping Version Through Conventional Commits + +- We shouldn't depend on one owner who knows every change between releases +- Every contributor should decide the impact of their changes during the development process +- You can auto-bump the version once it's merged to a specific branch (no more forgotten version updates) +- See [Conventional Commits Version Bump](https://github.com/marketplace/actions/conventional-commits-version-bump) GitHub Action +- Speeds up the process +- Prevents human mistakes + +**Major Version Bump** + +```text +refactor!: drop support for Node 6 +``` + +**Minor Version Bump** + +```text +feat(SHOPPER-000): introduce OrderMonitor v2 +``` + +**Patch Version Bump** + +```text +fix(SHOPPER-000): correct minor typos in code +``` + +## How About Squash Merges? + +Why do we need squash merges if we have good commit messages? + +### Pros + +- Every squash commit linked to PR +- Cleaner git history +- Easy roll-back + +### Cons + +- It changes commit history, which can cause conflicts +- It's hard to understand what actually changed +- Sometimes what you commit is not related to the purpose of the PR |