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
83 changes: 83 additions & 0 deletions .github/workflows/pr-checks.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
# Runs automated quality checks on pull requests before merging.
# Validates code quality by running linting, compilation, tests, and agent file checks.
# Serves as a quality gate to prevent broken code or oversized agent files from being merged.
#
# Path filtering ensures workflow only runs when relevant files change.
# Uses xvfb for headless VS Code extension testing.
name: PR Checks

on:
pull_request:
branches:
- main
paths:
- 'src/**'
- 'agents/**'
- 'skills/**'
- 'cli/**'
- 'scripts/**'
- '.github/workflows/pr-checks.yml'

jobs:
test:
runs-on: ubuntu-latest

steps:
- name: Checkout code
uses: actions/checkout@v4

- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '20'
cache: 'npm'
cache-dependency-path: package-lock.json

- name: Install dependencies
run: npm ci

- name: Lint code
run: npm run lint

- name: Compile extension
run: npm run compile

- name: Run extension unit tests
run: |
# Install xvfb for headless VS Code testing
# xvfb provides a virtual display server, required for VS Code's Electron environment
sudo apt-get update
sudo apt-get install -y xvfb

# Run tests with virtual display
# xvfb-run -a automatically finds an available display number
xvfb-run -a npm test
env:
# Prevent VS Code from showing UI during tests
DISPLAY: ':99.0'

- name: Install CLI dependencies
run: cd cli && npm ci

- name: Run CLI tests
run: |
cd cli
# Check if test files exist before running
if ls lib/*.test.js 1> /dev/null 2>&1; then
npm test
else
echo "No CLI test files found (lib/*.test.js) - skipping"
fi

- name: Lint agent files
run: npm run lint:agent:all

- name: PR checks summary
if: success()
run: |
echo "✅ All PR checks passed!"
echo "- Code linting: PASSED"
echo "- Compilation: PASSED"
echo "- Extension tests: PASSED"
echo "- CLI tests: PASSED"
echo "- Agent linting: PASSED"
129 changes: 129 additions & 0 deletions .github/workflows/publish-cli.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,129 @@
# Publishes the CLI package to npm when CLI version tags are pushed.
# Triggers on tags matching cli-v* pattern (e.g., cli-v1.0.0, cli-v0.2.0-beta).
# Builds, tests, publishes to npm with provenance, and creates GitHub Release.
#
# Pre-release convention: versions with -alpha, -beta, or -rc suffix are pre-releases
# and are published to npm with the 'beta' tag instead of 'latest'.
#
# AUTHENTICATION:
# This workflow uses NPM_TOKEN secret for npm authentication.
# To set up:
# 1. Generate an npm access token at https://www.npmjs.com/settings/tokens
# 2. Add as repository secret: Settings → Secrets → Actions → NPM_TOKEN
#
# For enhanced security with provenance, you can also configure npm OIDC:
# 1. In cli/package.json, add: "publishConfig": { "provenance": true }
# 2. On npmjs.com, link the package to the GitHub repository
# 3. The id-token permission below enables OIDC attestation
#
# PREREQUISITES (first-time setup):
# 1. Create NPM_TOKEN secret in repository settings
# 2. First publish may need to be manual: cd cli && npm publish --access public
name: Publish CLI

on:
push:
tags:
- 'cli-v*'

permissions:
id-token: write # Required for OIDC trusted publishing to npm
contents: write # Required to create GitHub releases

jobs:
publish:
runs-on: ubuntu-latest
defaults:
run:
working-directory: cli

steps:
- uses: actions/checkout@v4

- name: Setup Node.js
uses: actions/setup-node@v4
with:
# Using Node 20 for consistency with extension workflow
# PAW uses Node 24, but 20 is sufficient and more stable
node-version: '20'
registry-url: 'https://registry.npmjs.org'

- name: Extract version from tag
id: version
run: |
TAG_NAME="${{ github.ref_name }}"
VERSION="${TAG_NAME#cli-v}" # Remove 'cli-v' prefix
echo "version=${VERSION}" >> $GITHUB_OUTPUT
echo "Extracted version: ${VERSION}"

- name: Determine pre-release status
id: prerelease
run: |
VERSION="${{ steps.version.outputs.version }}"
# Check for pre-release suffixes: -alpha, -beta, -rc
# Examples: 1.0.0-beta, 0.2.0-alpha.1, 1.0.0-rc.1
if [[ "$VERSION" =~ -(alpha|beta|rc) ]]; then
echo "is_prerelease=true" >> $GITHUB_OUTPUT
echo "npm_tag=beta" >> $GITHUB_OUTPUT
echo "This is a pre-release version"
else
echo "is_prerelease=false" >> $GITHUB_OUTPUT
echo "npm_tag=latest" >> $GITHUB_OUTPUT
echo "This is a stable release version"
fi

- name: Set version from tag
run: npm version ${{ steps.version.outputs.version }} --no-git-tag-version

- name: Install dependencies
run: npm ci

- name: Build distribution
run: npm run build

- name: Run tests
run: npm test

- name: Publish to npm
run: npm publish --access public --tag ${{ steps.prerelease.outputs.npm_tag }}
env:
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}

- name: Check if release exists
id: check_release
working-directory: ${{ github.workspace }}
run: |
RELEASE_EXISTS=$(gh release view "${{ github.ref_name }}" --json id 2>/dev/null || echo "")
if [ -n "$RELEASE_EXISTS" ]; then
echo "exists=true" >> $GITHUB_OUTPUT
else
echo "exists=false" >> $GITHUB_OUTPUT
fi
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

- name: Create GitHub Release
if: steps.check_release.outputs.exists == 'false'
uses: softprops/action-gh-release@v1
with:
name: CLI ${{ steps.version.outputs.version }}
tag_name: ${{ github.ref_name }}
body: |
Published to npm: `@erdem-tuna/markdown-commenter@${{ steps.version.outputs.version }}`

## Installation

```bash
npx @erdem-tuna/markdown-commenter install copilot
```

Or install globally:
```bash
npm install -g @erdem-tuna/markdown-commenter
markdown-commenter install copilot
```

Release notes will be added by the release preparation process.
prerelease: ${{ steps.prerelease.outputs.is_prerelease }}
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
156 changes: 156 additions & 0 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,156 @@
# Automatically builds and releases the VS Code extension when version tags are pushed.
# Triggers on tags matching v* pattern (e.g., v0.2.0, v1.0.0).
# Builds extension, packages VSIX, creates GitHub Release, and publishes to VS Code Marketplace.
#
# Pre-release convention: odd minor versions (0.1.x, 0.3.x) are pre-releases,
# even minor versions (0.2.x, 0.4.x) are stable releases.
#
# SECRETS REQUIRED:
# - VSCE_PAT: Personal Access Token for VS Code Marketplace publishing
# To create: https://code.visualstudio.com/api/working-with-extensions/publishing-extension#get-a-personal-access-token
# Required scopes: Marketplace (Manage)
# Add to repository: Settings → Secrets and variables → Actions → New repository secret
#
# The workflow will create a GitHub Release even if Marketplace upload fails,
# ensuring users can always download the VSIX manually.
name: Release VSIX

on:
push:
tags:
- 'v*'

jobs:
release:
runs-on: ubuntu-latest

permissions:
contents: write # Required to create releases and upload assets

steps:
- name: Checkout code
uses: actions/checkout@v4

- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '20'
cache: 'npm'
cache-dependency-path: 'package-lock.json'

- name: Install dependencies
run: npm ci

- name: Compile extension
run: npm run compile

- name: Extract version from tag
id: version
run: |
# Extract semantic version from tag (e.g., v0.2.0 -> 0.2.0)
# This version becomes the source of truth for the release
TAG_NAME="${{ github.ref_name }}"
VERSION="${TAG_NAME#v}" # Remove 'v' prefix using bash parameter expansion
echo "version=${VERSION}" >> $GITHUB_OUTPUT
echo "Extracted version: ${VERSION}"

- name: Update package.json version to match tag
run: |
# Set package.json version to match the git tag
# This eliminates the need for manual version updates before tagging
# Local development stays on "0.0.1-dev" so every activation reinstalls agents
# The release workflow overwrites that dev suffix with the semver tag
TAG_VERSION="${{ steps.version.outputs.version }}"
npm version ${TAG_VERSION} --no-git-tag-version --allow-same-version
echo "Updated package.json to version: ${TAG_VERSION}"

- name: Determine pre-release status
id: prerelease
run: |
# VS Code extension convention: odd minor versions (0.1.x, 0.3.x) are pre-releases,
# even minor versions (0.2.x, 0.4.x) are stable releases
# This follows the VS Code pre-release extension best practices
VERSION="${{ steps.version.outputs.version }}"
# Extract minor version (second number in semver, e.g., 0.2.0 -> 2)
MINOR=$(echo $VERSION | cut -d. -f2)
# Check if minor version is odd (pre-release) or even (stable)
if [ $((MINOR % 2)) -eq 1 ]; then
echo "is_prerelease=true" >> $GITHUB_OUTPUT
echo "This is a pre-release version (minor=$MINOR is odd)"
else
echo "is_prerelease=false" >> $GITHUB_OUTPUT
echo "This is a stable release version (minor=$MINOR is even)"
fi

- name: Package VSIX
run: npm run package

- name: Verify VSIX created
id: vsix
run: |
# Verify the VSIX file was created with the expected filename format
# The package name comes from package.json: markdown-commenter-<version>.vsix
VSIX_FILE="markdown-commenter-${{ steps.version.outputs.version }}.vsix"
if [ ! -f "$VSIX_FILE" ]; then
echo "Error: Expected VSIX file not found: $VSIX_FILE"
exit 1
fi
# Export both the full path (for release upload) and filename (for display)
echo "vsix_path=${VSIX_FILE}" >> $GITHUB_OUTPUT
echo "vsix_name=${VSIX_FILE}" >> $GITHUB_OUTPUT
echo "VSIX created successfully: $VSIX_FILE"

- name: Check if release exists
id: check_release
run: |
RELEASE_EXISTS=$(gh release view "${{ github.ref_name }}" --json id 2>/dev/null || echo "")
if [ -n "$RELEASE_EXISTS" ]; then
echo "exists=true" >> $GITHUB_OUTPUT
else
echo "exists=false" >> $GITHUB_OUTPUT
fi
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

- name: Create GitHub Release
if: steps.check_release.outputs.exists == 'false'
uses: softprops/action-gh-release@v1
with:
name: ${{ github.ref_name }}
tag_name: ${{ github.ref_name }}
body: |
Release notes will be added by the release preparation process.

## Installation

Download the `.vsix` file and install via:
```bash
code --install-extension ${{ steps.vsix.outputs.vsix_name }}
```

Or install from VS Code Marketplace (if published successfully).
files: ${{ steps.vsix.outputs.vsix_path }}
prerelease: ${{ steps.prerelease.outputs.is_prerelease }}
fail_on_unmatched_files: true
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

- name: Publish to VS Code Marketplace
id: marketplace
# continue-on-error ensures GitHub Release is created even if Marketplace fails
# This provides resilience: users can always download VSIX from GitHub
continue-on-error: true
run: |
echo "Publishing to VS Code Marketplace..."
npx vsce publish --pat ${{ secrets.VSCE_PAT }}
env:
VSCE_PAT: ${{ secrets.VSCE_PAT }}

- name: Marketplace publish status
if: always()
run: |
if [ "${{ steps.marketplace.outcome }}" == "failure" ]; then
echo "⚠️ VS Code Marketplace publish failed"
echo "GitHub Release was still created with VSIX attached"
echo "You can manually publish later with: npx vsce publish"
fi
Loading