Skip to content
Open
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
28 changes: 28 additions & 0 deletions .github/SETUP.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
# GitHub Actions Setup

## Required Secrets

Add these in **Settings → Secrets and variables → Actions**:

| Secret | Description | Where to get it |
|--------|-------------|-----------------|
| `AZURE_DEVOPS_PAT` | Personal Access Token | [marketplace.visualstudio.com/manage](https://marketplace.visualstudio.com/manage) → Create token with **Marketplace (Manage)** scope |
| `AZURE_DEVOPS_SHARE_WITH` | Orgs to share dev/hotfix builds | Comma-separated org names, e.g., `org1,org2` (optional) |

Extension metadata (publisher, ID, name) is read from `vss-extension.json`.

## Workflow Triggers

- **`feature/*` branches** → Build + Publish to Development (e.g., `feature/1.0.0`)
- **`hotfix/*` branches** → Build + Publish to Hotfix (e.g., `hotfix/1.0.1`)
- **Tags** → Build + Publish to Release + Create GitHub Release (e.g., `1.0.0`)
- **Pull requests** → Build + Test only

**Note:** Branch and tag names must contain a semver version number (e.g., `1.0.0`).

## Optional: Environment Protection

Add approval gates in **Settings → Environments**:
- Development
- Hotfix
- Release (recommended)
200 changes: 200 additions & 0 deletions .github/workflows/build-and-publish.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,200 @@
name: Build and Publish Extension

on:
push:
branches:
- 'feature/**'
- 'hotfix/**'
tags:
- '*'
pull_request:
branches:
- main

env:
NODE_VERSION: '20.x'

jobs:
determine-environment:
runs-on: ubuntu-latest
outputs:
environment: ${{ steps.set-env.outputs.environment }}
should-publish: ${{ steps.set-env.outputs.should-publish }}
steps:
- name: Determine environment
id: set-env
run: |
if [[ "${{ github.ref }}" == refs/tags/* ]]; then
echo "environment=Release" >> $GITHUB_OUTPUT
echo "should-publish=true" >> $GITHUB_OUTPUT
elif [[ "${{ github.ref }}" == refs/heads/feature/* ]]; then
echo "environment=Development" >> $GITHUB_OUTPUT
echo "should-publish=true" >> $GITHUB_OUTPUT
elif [[ "${{ github.ref }}" == refs/heads/hotfix/* ]]; then
echo "environment=Hotfix" >> $GITHUB_OUTPUT
echo "should-publish=true" >> $GITHUB_OUTPUT
else
echo "environment=Development" >> $GITHUB_OUTPUT
echo "should-publish=false" >> $GITHUB_OUTPUT
fi

build:
runs-on: ubuntu-latest
needs: determine-environment
steps:
- name: Checkout repository
uses: actions/checkout@v4
with:
fetch-depth: 0
fetch-tags: true

- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: ${{ env.NODE_VERSION }}
cache: 'npm'

- name: Install dependencies and build
run: |
npm run initdev
npm run build

- name: Get version from tag or branch
id: version
run: |
COMMIT_COUNT=$(git rev-list --count HEAD)

# For pull requests, use a test version
if [[ "${{ github.ref }}" == refs/pull/* ]]; then
VERSION="1.0.0-pr${{ github.event.pull_request.number }}"
echo "version=$VERSION" >> $GITHUB_OUTPUT
echo "Building PR version: $VERSION"
exit 0
fi

BRANCH_NAME="${GITHUB_REF#refs/heads/}"
BRANCH_NAME="${BRANCH_NAME#refs/tags/}"

# Extract version number (e.g., from "feature/1.0.0" or "1.0.0")
if [[ "$BRANCH_NAME" =~ ([0-9]+\.[0-9]+\.[0-9]+) ]]; then
VERSION_BASE="${BASH_REMATCH[1]}"
else
echo "Error: Branch/tag name must contain a semver version (e.g., feature/1.0.0)"
exit 1
fi

if [[ "${{ github.ref }}" == refs/tags/* ]]; then
VERSION="${VERSION_BASE}.${COMMIT_COUNT}"
elif [[ "${{ github.ref }}" == refs/heads/feature/* ]]; then
VERSION="${VERSION_BASE}.${COMMIT_COUNT}-feature"
elif [[ "${{ github.ref }}" == refs/heads/hotfix/* ]]; then
VERSION="${VERSION_BASE}.${COMMIT_COUNT}-hotfix"
else
VERSION="${VERSION_BASE}.${COMMIT_COUNT}"
fi

echo "version=$VERSION" >> $GITHUB_OUTPUT
echo "Building version: $VERSION"

- name: Package extension
run: |
npm run package:tasks -- --outputPath "${{ github.workspace }}/dist" --extensionVersion "${{ steps.version.outputs.version }}"

- name: Upload artifact
uses: actions/upload-artifact@v4
with:
name: vsix
path: dist/*.vsix
retention-days: 30

publish:
runs-on: ubuntu-latest
needs: [determine-environment, build]
if: needs.determine-environment.outputs.should-publish == 'true'
environment: ${{ needs.determine-environment.outputs.environment }}
steps:
- name: Checkout repository
uses: actions/checkout@v4
with:
fetch-depth: 0
fetch-tags: true

- name: Download artifact
uses: actions/download-artifact@v4
with:
name: vsix
path: dist

- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: ${{ env.NODE_VERSION }}

- name: Install tfx-cli
run: npm install -g tfx-cli

- name: Read extension metadata
id: metadata
run: |
PUBLISHER=$(jq -r '.publisher' vss-extension.json)
EXTENSION_ID=$(jq -r '.id' vss-extension.json)
echo "publisher=$PUBLISHER" >> $GITHUB_OUTPUT
echo "extension-id=$EXTENSION_ID" >> $GITHUB_OUTPUT

- name: Set publish variables
id: publish-vars
env:
ENVIRONMENT: ${{ needs.determine-environment.outputs.environment }}
run: |
if [ "$ENVIRONMENT" = "Release" ]; then
echo "extension-tag=" >> $GITHUB_OUTPUT
echo "visibility=public" >> $GITHUB_OUTPUT
echo "share-with=" >> $GITHUB_OUTPUT
else
echo "extension-tag=-$ENVIRONMENT" >> $GITHUB_OUTPUT
echo "visibility=private" >> $GITHUB_OUTPUT
echo "share-with=${{ secrets.AZURE_DEVOPS_SHARE_WITH }}" >> $GITHUB_OUTPUT
fi

- name: Unpublish old non-release extension
if: needs.determine-environment.outputs.environment != 'Release'
continue-on-error: true
env:
AZURE_DEVOPS_PAT: ${{ secrets.AZURE_DEVOPS_PAT }}
run: |
tfx extension unpublish \
--token "$AZURE_DEVOPS_PAT" \
--publisher "${{ steps.metadata.outputs.publisher }}" \
--extension-id "${{ steps.metadata.outputs.extension-id }}${{ steps.publish-vars.outputs.extension-tag }}" \
--no-prompt

- name: Publish to Azure DevOps Marketplace
env:
AZURE_DEVOPS_PAT: ${{ secrets.AZURE_DEVOPS_PAT }}
run: |
SHARE_WITH="${{ steps.publish-vars.outputs.share-with }}"
VSIX_FILE=$(ls dist/*.vsix)

if [ -n "$SHARE_WITH" ]; then
tfx extension publish \
--token "$AZURE_DEVOPS_PAT" \
--vsix "$VSIX_FILE" \
--share-with $SHARE_WITH \
--no-prompt
else
tfx extension publish \
--token "$AZURE_DEVOPS_PAT" \
--vsix "$VSIX_FILE" \
--no-prompt
fi

- name: Create GitHub Release
if: needs.determine-environment.outputs.environment == 'Release'
uses: softprops/action-gh-release@v1
with:
files: dist/*.vsix
tag_name: ${{ github.ref_name }}
draft: false
prerelease: false
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
44 changes: 0 additions & 44 deletions azure-pipelines.yml

This file was deleted.

23 changes: 0 additions & 23 deletions build/pipeline/README.md

This file was deleted.

37 changes: 0 additions & 37 deletions build/pipeline/build_job.yml

This file was deleted.

Loading