Skip to content

Commit 891c044

Browse files
committed
Merge origin/main into issue-688-relink
2 parents d5184c3 + f3ce361 commit 891c044

23 files changed

Lines changed: 2208 additions & 15 deletions

.github/actions/prepare/action.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,8 @@ inputs:
55
sdk-version:
66
description: "Dart SDK version"
77
required: false
8-
# 3.6.0 Version required for pubspec_parse ^1.5.0 compatibility
9-
default: "3.6.0"
8+
# 3.10.0 required for latest win32/archive/file compatibility
9+
default: "3.10.0"
1010

1111
runs:
1212
using: "composite"

.github/workflows/README.md

Lines changed: 47 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,31 @@
3131
6. Push tag: `git push origin v4.0.0-beta.3`
3232
7. Everything deploys automatically!
3333

34+
### `release-fvm-mcp.yml`
35+
**Trigger**: Git tag push with `fvm-mcp-v*` pattern + manual dispatch
36+
**Purpose**: Build and publish `fvm_mcp` standalone binaries to GitHub Releases
37+
**Process**:
38+
1. **Validate** - Enforce release tag format and version consistency:
39+
- Tag must match `fvm-mcp-v<semver>`
40+
- Tag version must match `fvm_mcp/pubspec.yaml`
41+
- Tag version must match `fvm_mcp/lib/src/server.dart` default server version
42+
2. **Build** - Compile binaries on all supported runners:
43+
- 🐧 Linux (`tar.gz`)
44+
- 🍎 macOS (`tar.gz`)
45+
- 🪟 Windows (`zip`)
46+
3. **Publish** - Create/update GitHub release and upload:
47+
- Platform archives
48+
- `SHA256SUMS` integrity file
49+
50+
**Usage**:
51+
1. Update `fvm_mcp/pubspec.yaml` version
52+
2. Update `fvm_mcp/lib/src/server.dart` `FVM_MCP_VERSION` default
53+
3. Add/update `fvm_mcp/CHANGELOG.md` entry for that exact version
54+
4. Commit changes
55+
5. Tag with MCP prefix: `git tag fvm-mcp-v0.0.1-alpha.1`
56+
6. Push tag: `git push origin fvm-mcp-v0.0.1-alpha.1`
57+
7. `release-fvm-mcp.yml` publishes release assets automatically
58+
3459
### `test.yml`
3560
**Trigger**: Push, PR, workflow_call
3661
**Purpose**: Run all tests and quality checks
@@ -72,6 +97,23 @@ artifacts for inspection.
7297
- Monitor progress in [Actions](https://github.com/leoafarias/fvm/actions)
7398
- All platforms deployed simultaneously
7499

100+
### 🧩 FVM MCP Release (Standalone)
101+
102+
1. **Prepare MCP version**
103+
- Update `fvm_mcp/pubspec.yaml` version (for example `0.0.1-alpha.1`)
104+
- Update `fvm_mcp/lib/src/server.dart` default `FVM_MCP_VERSION`
105+
- Add a matching section in `fvm_mcp/CHANGELOG.md`
106+
- Commit changes
107+
108+
2. **Create and Push MCP Tag**
109+
- Create tag: `git tag fvm-mcp-vX.Y.Z` or `git tag fvm-mcp-vX.Y.Z-alpha.N`
110+
- Push tag: `git push origin fvm-mcp-vX.Y.Z`
111+
112+
3. **Automatic MCP Deployment**
113+
- `release-fvm-mcp.yml` validates version alignment
114+
- Builds Linux/macOS/Windows standalone binaries
115+
- Publishes assets and checksums to the tagged GitHub release
116+
75117
### ⚡ Emergency Release (Alternative)
76118

77119
For hotfixes or platform-specific urgent updates, use individual platform workflows:
@@ -83,15 +125,18 @@ For hotfixes or platform-specific urgent updates, use individual platform workfl
83125
## Version Management
84126

85127
- **Version Source**: `pubspec.yaml` (manually updated before tagging)
86-
- **Tag Format**: Must follow semver with 'v' prefix: `v4.0.0-beta.2`
128+
- **Tag Format (FVM CLI)**: Must follow semver with `v` prefix: `v4.0.0-beta.2`
129+
- **Tag Format (FVM MCP)**: Must follow semver with `fvm-mcp-v` prefix: `fvm-mcp-v0.0.1-alpha.1`
87130
- **CHANGELOG**: cli_pkg reads CHANGELOG.md to populate GitHub release notes
88131
- **Generated Files**: `lib/src/version.dart` is generated by build_runner from pubspec.yaml
89132

90133
## Troubleshooting
91134

92135
### Workflow doesn't trigger
93136
- Ensure tag is pushed to remote (not just created locally)
94-
- Check that tag follows `v*` pattern
137+
- Check that tag follows the correct pattern for the workflow:
138+
- `v*` for `release.yml`
139+
- `fvm-mcp-v*` for `release-fvm-mcp.yml`
95140
- Verify all required secrets are configured
96141

97142
### Binary upload fails
Lines changed: 223 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,223 @@
1+
name: Deploy FVM MCP
2+
3+
on:
4+
workflow_dispatch:
5+
inputs:
6+
tag:
7+
description: "Release tag in format fvm-mcp-vX.Y.Z[-pre-release]"
8+
required: true
9+
type: string
10+
push:
11+
tags:
12+
- "fvm-mcp-v*"
13+
14+
env:
15+
SDK_VERSION: "3.10.0"
16+
17+
permissions:
18+
contents: write
19+
20+
jobs:
21+
validate:
22+
name: Validate FVM MCP release
23+
runs-on: ubuntu-latest
24+
outputs:
25+
tag: ${{ steps.meta.outputs.tag }}
26+
version: ${{ steps.meta.outputs.version }}
27+
prerelease: ${{ steps.meta.outputs.prerelease }}
28+
steps:
29+
- name: Checkout
30+
uses: actions/checkout@v4
31+
with:
32+
ref: ${{ github.event_name == 'workflow_dispatch' && inputs.tag || github.ref }}
33+
34+
- name: Prepare environment
35+
uses: ./.github/actions/prepare
36+
with:
37+
sdk-version: ${{ env.SDK_VERSION }}
38+
39+
- name: fvm_mcp | Install dependencies
40+
working-directory: fvm_mcp
41+
run: dart pub get
42+
43+
- name: fvm_mcp | Format check
44+
working-directory: fvm_mcp
45+
run: dart format --output=none --set-exit-if-changed .
46+
47+
- name: fvm_mcp | Analyze
48+
working-directory: fvm_mcp
49+
run: dart analyze
50+
51+
- name: fvm_mcp | Tests
52+
working-directory: fvm_mcp
53+
run: dart test
54+
55+
- name: Resolve release metadata
56+
id: meta
57+
shell: bash
58+
run: |
59+
set -euo pipefail
60+
61+
if [[ "${GITHUB_EVENT_NAME}" == "workflow_dispatch" ]]; then
62+
TAG="${{ inputs.tag }}"
63+
else
64+
TAG="${GITHUB_REF_NAME}"
65+
fi
66+
67+
if [[ ! "$TAG" =~ ^fvm-mcp-v[0-9]+\.[0-9]+\.[0-9]+(-[0-9A-Za-z-]+(\.[0-9A-Za-z-]+)*)?(\+[0-9A-Za-z-]+(\.[0-9A-Za-z-]+)*)?$ ]]; then
68+
echo "Invalid tag format: $TAG"
69+
echo "Expected: fvm-mcp-v<semver>, for example fvm-mcp-v0.0.1-alpha.1"
70+
exit 1
71+
fi
72+
73+
VERSION="${TAG#fvm-mcp-v}"
74+
PUBSPEC_VERSION="$(awk '/^version:/ {print $2; exit}' fvm_mcp/pubspec.yaml)"
75+
SERVER_VERSION="$(sed -n "s/.*defaultValue: '\\([^']*\\)'.*/\\1/p" fvm_mcp/lib/src/server.dart | head -n1)"
76+
77+
if [[ -z "${PUBSPEC_VERSION}" ]]; then
78+
echo "Unable to read version from fvm_mcp/pubspec.yaml"
79+
exit 1
80+
fi
81+
82+
if [[ -z "${SERVER_VERSION}" ]]; then
83+
echo "Unable to read default server version from fvm_mcp/lib/src/server.dart"
84+
exit 1
85+
fi
86+
87+
if [[ "${VERSION}" != "${PUBSPEC_VERSION}" ]]; then
88+
echo "Tag version (${VERSION}) does not match pubspec version (${PUBSPEC_VERSION})"
89+
exit 1
90+
fi
91+
92+
if [[ "${VERSION}" != "${SERVER_VERSION}" ]]; then
93+
echo "Tag version (${VERSION}) does not match server default version (${SERVER_VERSION})"
94+
exit 1
95+
fi
96+
97+
PRERELEASE=false
98+
if [[ "${VERSION}" == *-* ]]; then
99+
PRERELEASE=true
100+
fi
101+
102+
echo "tag=${TAG}" >> "${GITHUB_OUTPUT}"
103+
echo "version=${VERSION}" >> "${GITHUB_OUTPUT}"
104+
echo "prerelease=${PRERELEASE}" >> "${GITHUB_OUTPUT}"
105+
106+
build:
107+
name: Build (${{ matrix.target }})
108+
runs-on: ${{ matrix.os }}
109+
needs: validate
110+
strategy:
111+
fail-fast: false
112+
matrix:
113+
include:
114+
- os: ubuntu-latest
115+
target: linux-x64
116+
binary_name: fvm_mcp
117+
archive_ext: tar.gz
118+
- os: macos-latest
119+
target: macos
120+
binary_name: fvm_mcp
121+
archive_ext: tar.gz
122+
- os: windows-latest
123+
target: windows-x64
124+
binary_name: fvm_mcp.exe
125+
archive_ext: zip
126+
127+
steps:
128+
- name: Checkout
129+
uses: actions/checkout@v4
130+
with:
131+
ref: refs/tags/${{ needs.validate.outputs.tag }}
132+
133+
- name: Prepare environment
134+
uses: ./.github/actions/prepare
135+
with:
136+
sdk-version: ${{ env.SDK_VERSION }}
137+
138+
- name: fvm_mcp | Install dependencies
139+
working-directory: fvm_mcp
140+
run: dart pub get
141+
142+
- name: fvm_mcp | Compile executable
143+
working-directory: fvm_mcp
144+
shell: bash
145+
run: |
146+
set -euo pipefail
147+
mkdir -p build/fvm_mcp
148+
dart compile exe bin/fvm_mcp.dart -o "build/fvm_mcp/${{ matrix.binary_name }}"
149+
150+
- name: Package archive (tar.gz)
151+
if: matrix.archive_ext == 'tar.gz'
152+
shell: bash
153+
run: |
154+
set -euo pipefail
155+
ARCHIVE="fvm_mcp-${{ needs.validate.outputs.version }}-${{ matrix.target }}.tar.gz"
156+
tar -C fvm_mcp/build/fvm_mcp -czf "${ARCHIVE}" "${{ matrix.binary_name }}"
157+
158+
- name: Package archive (zip)
159+
if: matrix.archive_ext == 'zip'
160+
shell: pwsh
161+
run: |
162+
$archive = "fvm_mcp-${{ needs.validate.outputs.version }}-${{ matrix.target }}.zip"
163+
Compress-Archive -Path "fvm_mcp/build/fvm_mcp/${{ matrix.binary_name }}" -DestinationPath $archive -Force
164+
165+
- name: Upload archive artifact
166+
uses: actions/upload-artifact@v4
167+
with:
168+
name: fvm_mcp-${{ matrix.target }}
169+
path: fvm_mcp-${{ needs.validate.outputs.version }}-${{ matrix.target }}.${{ matrix.archive_ext }}
170+
171+
release:
172+
name: Publish GitHub release
173+
runs-on: ubuntu-latest
174+
needs: [validate, build]
175+
steps:
176+
- name: Checkout
177+
uses: actions/checkout@v4
178+
with:
179+
ref: refs/tags/${{ needs.validate.outputs.tag }}
180+
181+
- name: Download build artifacts
182+
uses: actions/download-artifact@v4
183+
with:
184+
pattern: fvm_mcp-*
185+
merge-multiple: true
186+
path: dist
187+
188+
- name: Extract release notes from changelog
189+
shell: bash
190+
run: |
191+
set -euo pipefail
192+
VERSION="${{ needs.validate.outputs.version }}"
193+
awk -v version="${VERSION}" '
194+
BEGIN { in_section = 0 }
195+
$0 ~ "^##[[:space:]]+" version "([[:space:]]+-.*)?$" {
196+
in_section = 1
197+
next
198+
}
199+
in_section && /^##[[:space:]]+/ { exit }
200+
in_section { print }
201+
' fvm_mcp/CHANGELOG.md > RELEASE_NOTES.md
202+
203+
if [[ ! -s RELEASE_NOTES.md ]]; then
204+
echo "No changelog section found for version ${VERSION} in fvm_mcp/CHANGELOG.md"
205+
exit 1
206+
fi
207+
208+
- name: Generate checksums
209+
shell: bash
210+
run: |
211+
set -euo pipefail
212+
cd dist
213+
shasum -a 256 * > SHA256SUMS
214+
215+
- name: Create or update release
216+
uses: softprops/action-gh-release@v2
217+
with:
218+
tag_name: ${{ needs.validate.outputs.tag }}
219+
name: fvm_mcp v${{ needs.validate.outputs.version }}
220+
prerelease: ${{ needs.validate.outputs.prerelease == 'true' }}
221+
body_path: RELEASE_NOTES.md
222+
files: |
223+
dist/*

0 commit comments

Comments
 (0)