feat(extension): add VS Code extension with kanban board interface
- Complete VS Code extension with React-based kanban board UI - MCP integration for real-time Task Master synchronization - Professional CI/CD workflows for marketplace publishing - Comprehensive configuration system with user preferences - ShadCN UI components with VS Code theme integration - Drag-and-drop task management with status transitions - AI-powered task features via MCP protocol - Robust error handling and connection management - Multi-registry publishing (VS Code Marketplace + Open VSX) - Security audit completed with hardcoded paths removed BREAKING CHANGE: Extension requires publisher setup and marketplace keys Publisher and extension naming decisions required: - Update publisher field from placeholder 'DavidMaliglowka' - Choose unique extension name (currently 'taskr-kanban') - Select appropriate extension icon - Configure CI secrets (VSCE_PAT, OVSX_PAT) for publishing See apps/extension/docs/ for detailed setup instructions
This commit is contained in:
203
.github/workflows/extension-ci.yml
vendored
Normal file
203
.github/workflows/extension-ci.yml
vendored
Normal file
@@ -0,0 +1,203 @@
|
||||
name: Extension CI
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
- next
|
||||
paths:
|
||||
- 'apps/extension/**'
|
||||
- '.github/workflows/extension-ci.yml'
|
||||
pull_request:
|
||||
branches:
|
||||
- main
|
||||
- next
|
||||
paths:
|
||||
- 'apps/extension/**'
|
||||
- '.github/workflows/extension-ci.yml'
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
setup:
|
||||
runs-on: ubuntu-latest
|
||||
outputs:
|
||||
cache-key: ${{ steps.cache-key.outputs.key }}
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: 20
|
||||
|
||||
- uses: pnpm/action-setup@v4
|
||||
with:
|
||||
version: latest
|
||||
|
||||
- name: Generate cache key
|
||||
id: cache-key
|
||||
run: echo "key=${{ runner.os }}-extension-pnpm-${{ hashFiles('apps/extension/pnpm-lock.yaml') }}" >> $GITHUB_OUTPUT
|
||||
|
||||
- name: Cache pnpm dependencies
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: |
|
||||
~/.pnpm-store
|
||||
apps/extension/node_modules
|
||||
key: ${{ steps.cache-key.outputs.key }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-extension-pnpm-
|
||||
|
||||
- name: Install Extension Dependencies
|
||||
working-directory: apps/extension
|
||||
run: pnpm install --frozen-lockfile
|
||||
timeout-minutes: 5
|
||||
|
||||
lint-and-typecheck:
|
||||
needs: setup
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: 20
|
||||
|
||||
- uses: pnpm/action-setup@v4
|
||||
with:
|
||||
version: latest
|
||||
|
||||
- name: Restore pnpm dependencies
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: |
|
||||
~/.pnpm-store
|
||||
apps/extension/node_modules
|
||||
key: ${{ needs.setup.outputs.cache-key }}
|
||||
|
||||
- name: Install if cache miss
|
||||
working-directory: apps/extension
|
||||
run: pnpm install --frozen-lockfile --prefer-offline
|
||||
timeout-minutes: 3
|
||||
|
||||
- name: Lint Extension
|
||||
working-directory: apps/extension
|
||||
run: pnpm run lint
|
||||
env:
|
||||
FORCE_COLOR: 1
|
||||
|
||||
- name: Type Check Extension
|
||||
working-directory: apps/extension
|
||||
run: pnpm run check-types
|
||||
env:
|
||||
FORCE_COLOR: 1
|
||||
|
||||
build:
|
||||
needs: setup
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: 20
|
||||
|
||||
- uses: pnpm/action-setup@v4
|
||||
with:
|
||||
version: latest
|
||||
|
||||
- name: Restore pnpm dependencies
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: |
|
||||
~/.pnpm-store
|
||||
apps/extension/node_modules
|
||||
key: ${{ needs.setup.outputs.cache-key }}
|
||||
|
||||
- name: Install if cache miss
|
||||
working-directory: apps/extension
|
||||
run: pnpm install --frozen-lockfile --prefer-offline
|
||||
timeout-minutes: 3
|
||||
|
||||
- name: Build Extension
|
||||
working-directory: apps/extension
|
||||
run: pnpm run build
|
||||
env:
|
||||
FORCE_COLOR: 1
|
||||
|
||||
- name: Package Extension
|
||||
working-directory: apps/extension
|
||||
run: pnpm run package
|
||||
env:
|
||||
FORCE_COLOR: 1
|
||||
|
||||
- name: Verify Package Contents
|
||||
working-directory: apps/extension
|
||||
run: |
|
||||
echo "Checking vsix-build contents..."
|
||||
ls -la vsix-build/
|
||||
echo "Checking dist contents..."
|
||||
ls -la vsix-build/dist/
|
||||
echo "Checking package.json exists..."
|
||||
test -f vsix-build/package.json
|
||||
|
||||
- name: Create VSIX Package (Test)
|
||||
working-directory: apps/extension/vsix-build
|
||||
run: pnpm exec vsce package --no-dependencies
|
||||
env:
|
||||
FORCE_COLOR: 1
|
||||
|
||||
- name: Upload Extension Artifact
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: extension-package
|
||||
path: |
|
||||
apps/extension/vsix-build/*.vsix
|
||||
apps/extension/dist/
|
||||
retention-days: 30
|
||||
|
||||
test:
|
||||
needs: setup
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: 20
|
||||
|
||||
- uses: pnpm/action-setup@v4
|
||||
with:
|
||||
version: latest
|
||||
|
||||
- name: Restore pnpm dependencies
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: |
|
||||
~/.pnpm-store
|
||||
apps/extension/node_modules
|
||||
key: ${{ needs.setup.outputs.cache-key }}
|
||||
|
||||
- name: Install if cache miss
|
||||
working-directory: apps/extension
|
||||
run: pnpm install --frozen-lockfile --prefer-offline
|
||||
timeout-minutes: 3
|
||||
|
||||
- name: Run Extension Tests
|
||||
working-directory: apps/extension
|
||||
run: xvfb-run -a pnpm run test
|
||||
env:
|
||||
CI: true
|
||||
FORCE_COLOR: 1
|
||||
timeout-minutes: 10
|
||||
|
||||
- name: Upload Test Results
|
||||
if: always()
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: extension-test-results
|
||||
path: apps/extension/test-results
|
||||
retention-days: 30
|
||||
240
.github/workflows/extension-release.yml
vendored
Normal file
240
.github/workflows/extension-release.yml
vendored
Normal file
@@ -0,0 +1,240 @@
|
||||
name: Extension Release
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
paths:
|
||||
- 'apps/extension/**'
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
force_publish:
|
||||
description: 'Force publish even without version changes'
|
||||
required: false
|
||||
default: false
|
||||
type: boolean
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
concurrency: extension-release-${{ github.ref }}
|
||||
|
||||
jobs:
|
||||
check-version:
|
||||
runs-on: ubuntu-latest
|
||||
outputs:
|
||||
should-publish: ${{ steps.version-check.outputs.should-publish }}
|
||||
current-version: ${{ steps.version-check.outputs.current-version }}
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Check version changes
|
||||
id: version-check
|
||||
run: |
|
||||
# Get current version from package.json
|
||||
CURRENT_VERSION=$(jq -r '.version' apps/extension/package.json)
|
||||
echo "current-version=$CURRENT_VERSION" >> $GITHUB_OUTPUT
|
||||
|
||||
# Check if this is a force publish
|
||||
if [ "${{ github.event.inputs.force_publish }}" = "true" ]; then
|
||||
echo "should-publish=true" >> $GITHUB_OUTPUT
|
||||
echo "Force publish requested"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# Check if version changed in the last commit
|
||||
if git diff HEAD~1 HEAD --name-only | grep -q "apps/extension/package.json\|apps/extension/package.publish.json"; then
|
||||
# Check if version field actually changed
|
||||
PREV_VERSION=$(git show HEAD~1:apps/extension/package.json | jq -r '.version')
|
||||
if [ "$CURRENT_VERSION" != "$PREV_VERSION" ]; then
|
||||
echo "should-publish=true" >> $GITHUB_OUTPUT
|
||||
echo "Version changed from $PREV_VERSION to $CURRENT_VERSION"
|
||||
else
|
||||
echo "should-publish=false" >> $GITHUB_OUTPUT
|
||||
echo "No version change detected"
|
||||
fi
|
||||
else
|
||||
echo "should-publish=false" >> $GITHUB_OUTPUT
|
||||
echo "No package.json changes detected"
|
||||
fi
|
||||
|
||||
build-and-publish:
|
||||
needs: check-version
|
||||
if: needs.check-version.outputs.should-publish == 'true'
|
||||
runs-on: ubuntu-latest
|
||||
environment: extension-release
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: 20
|
||||
|
||||
- uses: pnpm/action-setup@v4
|
||||
with:
|
||||
version: latest
|
||||
|
||||
- name: Cache pnpm dependencies
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: |
|
||||
~/.pnpm-store
|
||||
apps/extension/node_modules
|
||||
key: ${{ runner.os }}-extension-pnpm-${{ hashFiles('apps/extension/pnpm-lock.yaml') }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-extension-pnpm-
|
||||
|
||||
- name: Install Extension Dependencies
|
||||
working-directory: apps/extension
|
||||
run: pnpm install --frozen-lockfile
|
||||
timeout-minutes: 5
|
||||
|
||||
- name: Run Tests
|
||||
working-directory: apps/extension
|
||||
run: xvfb-run -a pnpm run test
|
||||
env:
|
||||
CI: true
|
||||
FORCE_COLOR: 1
|
||||
timeout-minutes: 10
|
||||
|
||||
- name: Lint Extension
|
||||
working-directory: apps/extension
|
||||
run: pnpm run lint
|
||||
env:
|
||||
FORCE_COLOR: 1
|
||||
|
||||
- name: Type Check Extension
|
||||
working-directory: apps/extension
|
||||
run: pnpm run check-types
|
||||
env:
|
||||
FORCE_COLOR: 1
|
||||
|
||||
- name: Build Extension
|
||||
working-directory: apps/extension
|
||||
run: pnpm run build
|
||||
env:
|
||||
FORCE_COLOR: 1
|
||||
|
||||
- name: Package Extension
|
||||
working-directory: apps/extension
|
||||
run: pnpm run package
|
||||
env:
|
||||
FORCE_COLOR: 1
|
||||
|
||||
- name: Verify Package Structure
|
||||
working-directory: apps/extension
|
||||
run: |
|
||||
echo "=== Checking vsix-build structure ==="
|
||||
ls -la vsix-build/
|
||||
echo "=== Checking dist contents ==="
|
||||
ls -la vsix-build/dist/
|
||||
echo "=== Verifying required files ==="
|
||||
test -f vsix-build/package.json || (echo "Missing package.json" && exit 1)
|
||||
test -f vsix-build/dist/extension.js || (echo "Missing extension.js" && exit 1)
|
||||
echo "=== Checking package.json content ==="
|
||||
cat vsix-build/package.json | jq '.name, .version, .publisher'
|
||||
|
||||
- name: Create VSIX Package
|
||||
working-directory: apps/extension/vsix-build
|
||||
run: pnpm exec vsce package --no-dependencies
|
||||
env:
|
||||
FORCE_COLOR: 1
|
||||
|
||||
- name: Get VSIX filename
|
||||
id: vsix-info
|
||||
working-directory: apps/extension/vsix-build
|
||||
run: |
|
||||
VSIX_FILE=$(ls *.vsix)
|
||||
echo "vsix-filename=$VSIX_FILE" >> $GITHUB_OUTPUT
|
||||
echo "Found VSIX: $VSIX_FILE"
|
||||
|
||||
- name: Validate VSIX Package
|
||||
working-directory: apps/extension/vsix-build
|
||||
run: |
|
||||
echo "=== VSIX Package Contents ==="
|
||||
unzip -l "${{ steps.vsix-info.outputs.vsix-filename }}"
|
||||
|
||||
- name: Publish to VS Code Marketplace
|
||||
working-directory: apps/extension/vsix-build
|
||||
run: pnpm exec vsce publish --packagePath "${{ steps.vsix-info.outputs.vsix-filename }}"
|
||||
env:
|
||||
VSCE_PAT: ${{ secrets.VSCE_PAT }}
|
||||
FORCE_COLOR: 1
|
||||
|
||||
- name: Install Open VSX CLI
|
||||
run: npm install -g ovsx
|
||||
|
||||
- name: Publish to Open VSX Registry
|
||||
working-directory: apps/extension/vsix-build
|
||||
run: ovsx publish "${{ steps.vsix-info.outputs.vsix-filename }}"
|
||||
env:
|
||||
OVSX_PAT: ${{ secrets.OVSX_PAT }}
|
||||
FORCE_COLOR: 1
|
||||
|
||||
- name: Create GitHub Release
|
||||
uses: actions/create-release@v1
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
with:
|
||||
tag_name: extension-v${{ needs.check-version.outputs.current-version }}
|
||||
release_name: Extension v${{ needs.check-version.outputs.current-version }}
|
||||
body: |
|
||||
VS Code Extension Release v${{ needs.check-version.outputs.current-version }}
|
||||
|
||||
**Changes in this release:**
|
||||
- Published to VS Code Marketplace
|
||||
- Published to Open VSX Registry
|
||||
- Extension package: `${{ steps.vsix-info.outputs.vsix-filename }}`
|
||||
|
||||
**Installation:**
|
||||
- Install from VS Code Marketplace: [Task Master Kanban](https://marketplace.visualstudio.com/items?itemName=[TBD])
|
||||
- Install from Open VSX Registry: [Task Master Kanban](https://open-vsx.org/extension/[TBD])
|
||||
- Or download the VSIX file below and install manually
|
||||
draft: false
|
||||
prerelease: false
|
||||
|
||||
- name: Upload VSIX to Release
|
||||
uses: actions/upload-release-asset@v1
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
with:
|
||||
upload_url: ${{ steps.create_release.outputs.upload_url }}
|
||||
asset_path: apps/extension/vsix-build/${{ steps.vsix-info.outputs.vsix-filename }}
|
||||
asset_name: ${{ steps.vsix-info.outputs.vsix-filename }}
|
||||
asset_content_type: application/zip
|
||||
|
||||
- name: Upload Build Artifacts
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: extension-release-v${{ needs.check-version.outputs.current-version }}
|
||||
path: |
|
||||
apps/extension/vsix-build/*.vsix
|
||||
apps/extension/dist/
|
||||
retention-days: 90
|
||||
|
||||
notify-success:
|
||||
needs: [check-version, build-and-publish]
|
||||
if: success() && needs.check-version.outputs.should-publish == 'true'
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Success Notification
|
||||
run: |
|
||||
echo "🎉 Extension v${{ needs.check-version.outputs.current-version }} successfully published!"
|
||||
echo "📦 Available on VS Code Marketplace"
|
||||
echo "🌍 Available on Open VSX Registry"
|
||||
echo "🏷️ GitHub release created: extension-v${{ needs.check-version.outputs.current-version }}"
|
||||
|
||||
notify-skipped:
|
||||
needs: check-version
|
||||
if: needs.check-version.outputs.should-publish == 'false'
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Skip Notification
|
||||
run: |
|
||||
echo "ℹ️ Extension publish skipped - no version changes detected"
|
||||
echo "Current version: ${{ needs.check-version.outputs.current-version }}"
|
||||
echo "To force publish, use workflow_dispatch with force_publish=true"
|
||||
Reference in New Issue
Block a user