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
908 changes: 908 additions & 0 deletions AGENTS.md

Large diffs are not rendered by default.

150 changes: 150 additions & 0 deletions docs/diagrams/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,150 @@
# Release Scripts Diagrams

This directory contains Mermaid diagram files (`.mmd`) that visualize the architecture and workflows of the @ucdjs/release-scripts project.

## Recommended Viewing Order

For the best understanding of the system, view the diagrams in this order:

### 1. Architecture Overview
Start with the overall architecture to understand how services interact:

**[service-dependency-graph.mmd](./service-dependency-graph.mmd)**
- Shows all 7 services and their dependencies
- Illustrates how configuration flows into services
- Displays which services are used by each workflow (verify, prepare, publish)
- Color-coded by service type

### 2. Supporting Algorithms
Before diving into workflows, understand the key algorithms:

**[version-bump-calculation.mmd](./version-bump-calculation.mmd)**
- How version bumps are calculated from conventional commits
- Shows the priority: breaking changes → major, features → minor, fixes → patch
- Includes version override handling

**[commit-attribution-flow.mmd](./commit-attribution-flow.mmd)**
- Sophisticated global commit attribution algorithm
- Three modes: none, all, dependencies
- Timestamp-based filtering to prevent double-counting
- Critical for understanding how commits are attributed in monorepos

### 3. Main Workflows
Now examine the three main workflows in order of complexity:

**[verify-workflow.mmd](./verify-workflow.mmd)** (Implemented)
- Verifies that release branch matches expected state
- Loads overrides, discovers packages, calculates expected versions
- Compares expected vs actual versions/dependencies
- Sets GitHub commit status (success/failure)
- **Use case**: CI/CD validation of release PRs

**[prepare-workflow.mmd](./prepare-workflow.mmd)** (Implemented)
- Prepares releases by calculating and applying version updates
- Updates package.json files in topological order
- Supports dry-run mode
- Shows future enhancements (PR creation, changelog generation)
- **Use case**: Local release preparation before creating/updating PR

**[publish-workflow.mmd](./publish-workflow.mmd)** (Planned)
- Publishing packages to NPM in topological order
- Parallel publishing within dependency levels
- NPM version existence checking
- Git tag creation after successful publish
- **Use case**: Automated NPM publishing from CI/CD

## Diagram Files

| File | Type | Purpose | Status |
|------|------|---------|--------|
| `service-dependency-graph.mmd` | Architecture | Service dependencies and workflow usage | Current |
| `version-bump-calculation.mmd` | Algorithm | Version bump logic from commits | Current |
| `commit-attribution-flow.mmd` | Algorithm | Global commit attribution | Current |
| `verify-workflow.mmd` | Workflow | Release branch verification | Implemented |
| `prepare-workflow.mmd` | Workflow | Release preparation | Implemented |
| `publish-workflow.mmd` | Workflow | NPM publishing | Planned |

## Viewing the Diagrams

### Online (GitHub)
GitHub automatically renders `.mmd` files when you view them in the web interface. Simply click on any diagram file above.

### Locally with VS Code
Install the [Markdown Preview Mermaid Support](https://marketplace.visualstudio.com/items?itemName=bierner.markdown-mermaid) extension to view diagrams in markdown preview.

### Generate PNG/SVG Images
Use the [Mermaid CLI](https://github.com/mermaid-js/mermaid-cli) to generate images:

```bash
# Install mermaid-cli
npm install -g @mermaid-js/mermaid-cli

# Generate PNG
mmdc -i verify-workflow.mmd -o verify-workflow.png

# Generate SVG
mmdc -i verify-workflow.mmd -o verify-workflow.svg

# Generate all diagrams
for file in *.mmd; do mmdc -i "$file" -o "${file%.mmd}.png"; done
```

### Online Editor
Copy and paste diagram content into the [Mermaid Live Editor](https://mermaid.live/) for interactive viewing and editing.

## Color Coding

The diagrams use consistent color coding:

### Workflow Diagrams
- **Green** (`#e1f5e1`): Start/Success states
- **Red** (`#ffe1e1`, `#ffcccc`): Error states and exit failures
- **Yellow** (`#fff4e1`): Decision points and important checks
- **Blue dashed** (`#e1f0ff` with dashed border): Planned/future features
- **Light green** (`#d4edda`): Successful operations
- **Light red** (`#f8d7da`): Failed operations
- **Gray** (`#f0f0f0`): Skip/neutral operations

### Service Dependency Graph
- **Light blue** (`#e1f0ff`): Configuration
- **Light red** (`#ffe1e1`): External services (Git, GitHub, NPM)
- **Light green** (`#e1ffe1`): Core workspace service
- **Yellow** (`#fff4e1`): Calculation services
- **Purple** (`#f0e1ff`): Update services
- **Gray** (`#f0f0f0`): Helper utilities
- **Green** (`#d4edda`): Implemented workflows
- **Blue dashed**: Planned workflows

### Version Bump Calculation
- **Red** (`#ffcccc`): Major bump
- **Yellow** (`#fff4cc`): Minor bump
- **Green** (`#ccffcc`): Patch bump
- **Gray** (`#f0f0f0`): No bump
- **Blue** (`#e1f0ff`): Override

## Integration

These diagrams are referenced in the main project documentation:
- **[AGENTS.md](../../AGENTS.md)**: Complete architecture guide with inline diagram previews
- Each workflow section in AGENTS.md links to the corresponding diagram file

## Updating Diagrams

When updating diagrams:

1. Edit the `.mmd` file directly
2. Test the diagram syntax at [Mermaid Live Editor](https://mermaid.live/)
3. Ensure color coding follows the conventions above
4. Update both the `.mmd` file and the corresponding inline diagram in AGENTS.md
5. Consider regenerating PNG/SVG images if they're used elsewhere

## Contributing

When adding new diagrams:

1. Follow the naming convention: `kebab-case.mmd`
2. Add the diagram to this README with description and purpose
3. Reference it from AGENTS.md if applicable
4. Use consistent color coding (see above)
5. Include clear labels and decision points
6. Test rendering on GitHub before committing
65 changes: 65 additions & 0 deletions docs/diagrams/commit-attribution-flow.mmd
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
sequenceDiagram
participant API as Main Workflow
participant Helpers as Helper Utils
participant Git as GitService
participant Packages as Package List

Note over API,Packages: Input: Packages with package-specific commits already merged

API->>Helpers: mergeCommitsAffectingGloballyIntoPackage(packages, mode)

alt mode = "none"
Helpers-->>API: Return packages unchanged
Note over API: No global commits added
else mode = "all" or "dependencies"
Note over Helpers,Git: 1. Get all commits from main branch
Helpers->>Packages: findCommitRange(packages)
Packages-->>Helpers: {oldest, newest} commit timestamps

Helpers->>Git: getCommitsSince(oldestTag)
Git-->>Helpers: allCommits[]

Note over Helpers: 2. Filter for global commits
loop For each commit
Helpers->>Helpers: isGlobalCommit(commit, packages)
alt Commit affects files outside package dirs
Helpers->>Helpers: Mark as global commit
alt mode = "dependencies"
Helpers->>Helpers: isDependencyFile(commit.files)
opt Is dependency file
Helpers->>Helpers: Keep commit
end
else mode = "all"
Helpers->>Helpers: Keep commit
end
end
end

Note over Helpers: 3. Attribute commits to packages
loop For each package
Helpers->>Git: getMostRecentPackageTag(package)
Git-->>Helpers: lastReleaseTag

Helpers->>Git: getCommitsSince(lastReleaseTag)
Git-->>Helpers: lastReleaseCommits[]

Helpers->>Helpers: Find newest commit timestamp
Note over Helpers: lastReleaseTime = newest commit time

Note over Helpers: 4. Filter global commits by timestamp
loop For each global commit
alt commit.time > lastReleaseTime
Helpers->>Helpers: Attribute to package
Note over Helpers: This prevents double-counting:<br/>commit happened AFTER this<br/>package was last released
else commit.time <= lastReleaseTime
Helpers->>Helpers: Skip (already counted in previous release)
end
end

Helpers->>Packages: Merge attributed commits into package
end

Helpers-->>API: packages with global commits added
end

Note over API: Result: Packages with both package-specific<br/>and attributed global commits
80 changes: 80 additions & 0 deletions docs/diagrams/package-lifecycle.mmd
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
stateDiagram-v2
[*] --> Discovered: Package found in workspace

Discovered --> Analyzing: Has commits since last tag
Discovered --> NoChanges: No commits since last tag

NoChanges --> [*]: Skip release

Analyzing --> ParsingCommits: Load commits
ParsingCommits --> GlobalCommitAttribution: Package commits parsed

GlobalCommitAttribution --> CalculatingBump: Global commits attributed

CalculatingBump --> CheckOverride: Analyze conventional commits
CheckOverride --> OverrideApplied: Override exists
CheckOverride --> BumpCalculated: No override

OverrideApplied --> PendingRelease: Version set from override
BumpCalculated --> NoBump: No significant changes
BumpCalculated --> PendingRelease: Bump type determined

NoBump --> [*]: Skip release

PendingRelease --> InDependencyGraph: Add to graph
InDependencyGraph --> CircularCheck: Analyze dependencies

CircularCheck --> Error: Circular dependency detected
CircularCheck --> TopoSorted: No cycles found

Error --> [*]: Release fails

TopoSorted --> WaitingForDeps: Assigned level in graph
WaitingForDeps --> ReadyToUpdate: Dependencies updated

note right of ReadyToUpdate
Packages at Level 0 skip this wait.
Others wait for lower levels.
end note

ReadyToUpdate --> UpdatingVersion: Turn in topological order
UpdatingVersion --> UpdatingDependencies: Version bumped in package.json
UpdatingDependencies --> ValidatingRanges: Workspace deps updated

ValidatingRanges --> RangeError: Invalid semver range
ValidatingRanges --> DryRunCheck: Ranges valid

RangeError --> [*]: Release fails

DryRunCheck --> LoggedUpdate: Dry-run mode
DryRunCheck --> WrittenToDisk: Normal mode

LoggedUpdate --> Updated: Simulated update
WrittenToDisk --> Updated: package.json written

Updated --> Verifying: verify() called

Verifying --> DriftDetected: Expected ≠ Actual
Verifying --> Verified: Expected = Actual

DriftDetected --> [*]: Verification fails

Verified --> AwaitingPublish: Ready for NPM
AwaitingPublish --> CheckingNPM: publish() called

CheckingNPM --> AlreadyPublished: Version exists on NPM
CheckingNPM --> Building: Version not on NPM

AlreadyPublished --> [*]: Skip publish

Building --> Publishing: Build successful
Publishing --> CreatingTag: Published to NPM
CreatingTag --> PushingTag: Git tag created
PushingTag --> Published: Tag pushed to remote

Published --> [*]: Release complete

note left of Published
Package is now available on NPM
with a corresponding git tag
end note
Loading
Loading