Skip to content

Commit 0df3eb6

Browse files
authored
CI for building / releasing backend + frontend (#9)
* CI for building Go binaries / release * Build VSCE extensions and publish on release * Handle pre-release builds * Generate release notes on tag push * Rename workflows * Fix test * Fix some CI * Clean up some vsce package related stuff * Build Go with LFS
1 parent 7058e1e commit 0df3eb6

File tree

12 files changed

+550
-29
lines changed

12 files changed

+550
-29
lines changed
Lines changed: 209 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,209 @@
1+
# VSCode Marketplace Publishing Setup
2+
3+
This document explains how to set up automated publishing to the Visual Studio Code Marketplace via GitHub Actions.
4+
5+
## Prerequisites
6+
7+
You need a Personal Access Token (PAT) from the Visual Studio Marketplace with publishing permissions.
8+
9+
## Creating a Visual Studio Marketplace PAT
10+
11+
1. Go to https://dev.azure.com/ and sign in with the account that has access to the `jet-propulsion-laboratory` publisher
12+
2. Click on your profile icon in the top right → **Personal access tokens**
13+
3. Click **+ New Token**
14+
4. Configure the token:
15+
- **Name**: `GitHub Actions - Hermes Extensions`
16+
- **Organization**: Select your organization (or "All accessible organizations")
17+
- **Expiration**: Set an appropriate expiration date (recommended: 1 year, then rotate)
18+
- **Scopes**: Select **Marketplace****Manage** (this grants publish/unpublish permissions)
19+
5. Click **Create**
20+
6. **IMPORTANT**: Copy the token immediately - you won't be able to see it again!
21+
22+
## Adding the Token to GitHub Secrets
23+
24+
1. Go to your GitHub repository: https://github.com/nasa/hermes
25+
2. Navigate to **Settings****Secrets and variables****Actions**
26+
3. Click **New repository secret**
27+
4. Add the following secret:
28+
- **Name**: `VSCE_PAT`
29+
- **Secret**: Paste the Personal Access Token you created above
30+
5. Click **Add secret**
31+
32+
## How the Workflow Works
33+
34+
The workflow (`.github/workflows/build-vscode-extensions.yml`) has two jobs:
35+
36+
### Build Job (always runs)
37+
- Triggers on:
38+
- Git tags starting with `v*` (e.g., `v4.0.0`)
39+
- Manual workflow dispatch
40+
- Pull requests that modify TypeScript/extension code
41+
- Builds both `hermes` (core) and `hermes-fprime` extensions
42+
- Packages them as `.vsix` files
43+
- Uploads artifacts to GitHub Actions
44+
- **On tag pushes**: Uploads `.vsix` files to GitHub Release
45+
46+
### Publish Job (only on tags)
47+
- Triggers only when a Git tag is pushed
48+
- Depends on successful build job
49+
- Publishes both extensions to the VS Code Marketplace using the `VSCE_PAT` secret
50+
51+
## Publishing a New Release
52+
53+
The workflow automatically sets the extension version from the Git tag. You don't need to manually update `package.json` files.
54+
55+
### Publishing a Stable Release
56+
57+
1. Create and push a Git tag with the desired version:
58+
```bash
59+
git tag v4.1.0
60+
git push origin v4.1.0
61+
```
62+
63+
2. The workflow will automatically:
64+
- Extract the version from the tag (e.g., `v4.1.0``4.1.0`)
65+
- Update all `package.json` files with the new version
66+
- Build both extensions with the correct version
67+
- Create a GitHub Release with auto-generated changelog notes
68+
- Upload all assets (4 Go binaries + 2 VSCode extensions) to the release
69+
- Publish both extensions to the VS Code Marketplace with version `4.1.0`
70+
71+
### Publishing a Pre-Release
72+
73+
Pre-release versions are detected automatically based on semantic versioning (versions containing a hyphen).
74+
75+
1. Create a pre-release tag:
76+
```bash
77+
# Beta release
78+
git tag v4.1.0-beta.1
79+
git push origin v4.1.0-beta.1
80+
81+
# Release candidate
82+
git tag v4.1.0-rc.1
83+
git push origin v4.1.0-rc.1
84+
85+
# Alpha release
86+
git tag v4.1.0-alpha.1
87+
git push origin v4.1.0-alpha.1
88+
```
89+
90+
2. The workflow will automatically:
91+
- Detect the hyphen in the version and mark it as a pre-release
92+
- Create a **Pre-release** on GitHub (marked with the "Pre-release" badge)
93+
- Publish to the VS Code Marketplace with the `--pre-release` flag
94+
- Users can opt-in to pre-release versions in VS Code via "Switch to Pre-Release Version"
95+
96+
**Pre-release Benefits:**
97+
- Test new features with early adopters before stable release
98+
- Pre-release extensions show up in VS Code's pre-release channel
99+
- GitHub releases are clearly marked as pre-release
100+
- Can iterate quickly (`v4.1.0-beta.1`, `v4.1.0-beta.2`, etc.)
101+
102+
**Note**: The version in your local `package.json` files doesn't matter for releases - the Git tag is the source of truth. However, you may want to keep them in sync manually for consistency:
103+
104+
```bash
105+
# Optional: Update package.json files to match
106+
vim package.json # Change "version": "4.1.0"
107+
vim src/extensions/core/package.json
108+
vim src/extensions/fprime/package.json
109+
git add package.json src/extensions/*/package.json
110+
git commit -m "Bump version to v4.1.0"
111+
git tag v4.1.0
112+
git push origin main v4.1.0
113+
```
114+
115+
## Auto-Generated Release Notes
116+
117+
Both workflows automatically generate release notes using GitHub's built-in changelog generator. When you push a tag, the GitHub release will include:
118+
119+
- **What's Changed**: List of merged pull requests since the last release
120+
- **New Contributors**: First-time contributors in this release
121+
- **Full Changelog**: Link to compare view showing all changes
122+
123+
The changelog is generated from:
124+
- PR titles merged between the previous tag and the current tag
125+
- Commit messages (if no PRs are associated)
126+
- Contributor information
127+
128+
**Customizing Release Notes:**
129+
130+
You can customize the format and grouping by creating a `.github/release.yml` file:
131+
132+
```yaml
133+
changelog:
134+
exclude:
135+
labels:
136+
- ignore-for-release
137+
categories:
138+
- title: Breaking Changes 🛠
139+
labels:
140+
- breaking-change
141+
- title: New Features 🎉
142+
labels:
143+
- enhancement
144+
- title: Bug Fixes 🐛
145+
labels:
146+
- bug
147+
- title: Other Changes
148+
labels:
149+
- "*"
150+
```
151+
152+
See [GitHub's documentation](https://docs.github.com/en/repositories/releasing-projects-on-github/automatically-generated-release-notes) for more options.
153+
154+
## Testing Without Publishing
155+
156+
To test the workflow without publishing:
157+
158+
1. Push changes to a PR branch that modifies extension code
159+
2. The workflow will build and package extensions
160+
3. Check the Actions tab for build artifacts
161+
4. Download and test the `.vsix` files locally
162+
163+
Or manually trigger the workflow:
164+
165+
1. Go to **Actions** → **Build VSCode Extensions**
166+
2. Click **Run workflow**
167+
3. Select a branch and click **Run workflow**
168+
169+
## Troubleshooting
170+
171+
### "Failed to publish: The Personal Access Token verification has failed"
172+
- The `VSCE_PAT` secret is missing, expired, or invalid
173+
- Create a new PAT following the steps above
174+
- Update the GitHub secret with the new token
175+
176+
### "Failed to publish: Extension publisher 'jet-propulsion-laboratory' does not exist"
177+
- The publisher name in `package.json` doesn't match your Marketplace publisher
178+
- Verify the publisher at https://marketplace.visualstudio.com/manage/publishers/jet-propulsion-laboratory
179+
180+
### "Failed to package: Missing required field 'repository'"
181+
- Ensure both extension `package.json` files have the `repository` field
182+
- This is already configured in the current setup
183+
184+
## Manual Publishing
185+
186+
If you need to publish manually (bypassing GitHub Actions):
187+
188+
```bash
189+
# Install vsce
190+
yarn global add @vscode/vsce
191+
192+
# Build extensions
193+
yarn build
194+
195+
# Publish core extension
196+
cd src/extensions/core
197+
vsce publish --yarn -p YOUR_PAT_HERE
198+
199+
# Publish fprime extension
200+
cd ../fprime
201+
vsce publish -p YOUR_PAT_HERE
202+
```
203+
204+
## Security Notes
205+
206+
- **Never commit PATs to the repository**
207+
- Rotate the PAT annually or if compromised
208+
- The PAT has full Marketplace management permissions - keep it secure
209+
- Only repository administrators should have access to GitHub secrets

.github/workflows/nightly-fprime-build.yml renamed to .github/workflows/build-fprime-nightly.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ on:
88

99
jobs:
1010
build-fprime-cache:
11-
uses: ./.github/workflows/fprime-build-template.yml
11+
uses: ./.github/workflows/template-build-fprime.yml
1212
with:
1313
tag: nightly
1414
fprime-branch: devel
Lines changed: 119 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,119 @@
1+
name: Build Go Binaries
2+
3+
on:
4+
push:
5+
tags:
6+
- 'v*'
7+
workflow_dispatch:
8+
pull_request:
9+
paths:
10+
- 'cmd/**'
11+
- 'pkg/**'
12+
- 'go.mod'
13+
- 'go.sum'
14+
- '.github/workflows/build-go-binaries.yml'
15+
16+
jobs:
17+
test:
18+
name: Run Go Tests
19+
runs-on: ubuntu-latest
20+
steps:
21+
- name: Checkout code
22+
uses: actions/checkout@v4
23+
with:
24+
lfs: true
25+
26+
- name: Set up Go
27+
uses: actions/setup-go@v5
28+
with:
29+
go-version-file: 'go.mod'
30+
cache: true
31+
32+
- name: Run tests
33+
run: go test ./pkg/...
34+
35+
build:
36+
name: Build ${{ matrix.goos }}-${{ matrix.goarch }}
37+
runs-on: ubuntu-latest
38+
needs: test
39+
strategy:
40+
matrix:
41+
include:
42+
- goos: linux
43+
goarch: amd64
44+
- goos: linux
45+
goarch: arm64
46+
- goos: darwin
47+
goarch: amd64
48+
- goos: darwin
49+
goarch: arm64
50+
51+
steps:
52+
- name: Checkout code
53+
uses: actions/checkout@v4
54+
55+
- name: Set up Go
56+
uses: actions/setup-go@v5
57+
with:
58+
go-version-file: 'go.mod'
59+
cache: true
60+
61+
- name: Get version
62+
id: version
63+
run: |
64+
if [[ "${{ github.ref }}" == refs/tags/* ]]; then
65+
VERSION="${GITHUB_REF#refs/tags/}"
66+
# Remove 'v' prefix for pre-release detection
67+
SEMVER="${VERSION#v}"
68+
else
69+
VERSION="dev-$(git rev-parse --short HEAD)"
70+
SEMVER="0.0.0-dev.$(git rev-parse --short HEAD)"
71+
fi
72+
73+
# Detect pre-release versions (contain hyphen: -alpha, -beta, -rc, etc.)
74+
if [[ "$SEMVER" == *-* ]]; then
75+
IS_PRERELEASE="true"
76+
echo "Detected pre-release version"
77+
else
78+
IS_PRERELEASE="false"
79+
fi
80+
81+
echo "version=$VERSION" >> $GITHUB_OUTPUT
82+
echo "is_prerelease=$IS_PRERELEASE" >> $GITHUB_OUTPUT
83+
echo "Building version: $VERSION (pre-release: $IS_PRERELEASE)"
84+
85+
- name: Build binaries
86+
env:
87+
GOOS: ${{ matrix.goos }}
88+
GOARCH: ${{ matrix.goarch }}
89+
CGO_ENABLED: 0
90+
GO_FLAGS: -trimpath -ldflags="-s -w"
91+
run: |
92+
echo "Building for $GOOS/$GOARCH..."
93+
make go
94+
echo "Build complete"
95+
ls -lh out/
96+
97+
- name: Create archive
98+
run: |
99+
ARCHIVE_NAME="hermes-${{ steps.version.outputs.version }}-${{ matrix.goos }}-${{ matrix.goarch }}.tar.gz"
100+
tar -czf "$ARCHIVE_NAME" -C out backend uplink sqlrecord protocolc
101+
echo "Created archive: $ARCHIVE_NAME"
102+
ls -lh "$ARCHIVE_NAME"
103+
104+
- name: Upload artifact
105+
uses: actions/upload-artifact@v4
106+
with:
107+
name: hermes-${{ steps.version.outputs.version }}-${{ matrix.goos }}-${{ matrix.goarch }}
108+
path: hermes-${{ steps.version.outputs.version }}-${{ matrix.goos }}-${{ matrix.goarch }}.tar.gz
109+
retention-days: 30
110+
111+
- name: Upload to release
112+
if: startsWith(github.ref, 'refs/tags/')
113+
uses: softprops/action-gh-release@v1
114+
with:
115+
files: hermes-${{ steps.version.outputs.version }}-${{ matrix.goos }}-${{ matrix.goarch }}.tar.gz
116+
prerelease: ${{ steps.version.outputs.is_prerelease }}
117+
generate_release_notes: true
118+
env:
119+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

0 commit comments

Comments
 (0)