From 274890d71c56deb2b608528acd7b006d58e14410 Mon Sep 17 00:00:00 2001 From: Devraj Mehta Date: Fri, 3 Apr 2026 19:59:19 -0400 Subject: [PATCH 1/2] Add npm publish workflow with OIDC trusted publishing Adds a workflow_dispatch workflow (.github/workflows/publish.yml) that: - Accepts version_type input (major/minor/patch, default patch) - Determines next version from the latest npm-published version - Publishes to npm using OIDC trusted publishing (no tokens needed) - Creates a GitHub release with auto-generated notes and npm tarball - Pipes command output to GITHUB_STEP_SUMMARY for visibility - Hardens against script injection using environment variables Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- .github/workflows/publish.yml | 123 ++++++++++++++++++++++++++++++++++ 1 file changed, 123 insertions(+) create mode 100644 .github/workflows/publish.yml diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml new file mode 100644 index 0000000..a928c39 --- /dev/null +++ b/.github/workflows/publish.yml @@ -0,0 +1,123 @@ +name: Publish to npm + +on: + workflow_dispatch: + inputs: + version_type: + description: "Version increment type" + required: true + type: choice + options: + - patch + - minor + - major + default: patch + +permissions: + contents: write + id-token: write + +jobs: + publish: + runs-on: ubuntu-latest + environment: npm-publish + steps: + - name: Checkout repository + uses: actions/checkout@v4 + with: + fetch-depth: 0 + + - name: Setup Node.js + uses: actions/setup-node@v4 + with: + node-version: 22 + registry-url: "https://registry.npmjs.org" + + - name: Get current npm version + id: current_version + run: | + CURRENT_VERSION=$(npm view @github/copilot-engine-sdk version 2>/dev/null || echo "0.0.0") + echo "version=$CURRENT_VERSION" >> "$GITHUB_OUTPUT" + echo "Current published version: $CURRENT_VERSION" + echo "- Current published version: \`$CURRENT_VERSION\`" >> "$GITHUB_STEP_SUMMARY" + + - name: Calculate next version + id: next_version + env: + CURRENT: ${{ steps.current_version.outputs.version }} + VERSION_TYPE: ${{ inputs.version_type }} + run: | + IFS='.' read -r MAJOR MINOR PATCH <<< "$CURRENT" + + case "$VERSION_TYPE" in + major) + MAJOR=$((MAJOR + 1)) + MINOR=0 + PATCH=0 + ;; + minor) + MINOR=$((MINOR + 1)) + PATCH=0 + ;; + patch) + PATCH=$((PATCH + 1)) + ;; + esac + + NEXT_VERSION="${MAJOR}.${MINOR}.${PATCH}" + echo "version=$NEXT_VERSION" >> "$GITHUB_OUTPUT" + echo "Next version: $NEXT_VERSION (incremented $VERSION_TYPE from $CURRENT)" + echo "- Next version: \`$NEXT_VERSION\` (incremented $VERSION_TYPE from \`$CURRENT\`)" >> "$GITHUB_STEP_SUMMARY" + + - name: Set package version + env: + VERSION: ${{ steps.next_version.outputs.version }} + run: npm version "$VERSION" --no-git-tag-version + + - name: Install dependencies + run: npm ci + + - name: Build + run: npm run build + + - name: Create npm tarball + run: npm pack + + - name: Publish to npm + run: npm publish --access public 2>&1 | tee -a "$GITHUB_STEP_SUMMARY" + + - name: Determine previous release tag + id: previous_tag + run: | + PREVIOUS_TAG=$(gh release list --limit 1 --json tagName --jq '.[0].tagName // empty' 2>/dev/null || echo "") + echo "tag=$PREVIOUS_TAG" >> "$GITHUB_OUTPUT" + if [ -n "$PREVIOUS_TAG" ]; then + echo "Previous release tag: $PREVIOUS_TAG" + echo "- Previous release tag: \`$PREVIOUS_TAG\`" >> "$GITHUB_STEP_SUMMARY" + else + echo "No previous release found" + echo "- No previous release found" >> "$GITHUB_STEP_SUMMARY" + fi + env: + GH_TOKEN: ${{ github.token }} + + - name: Create GitHub release + env: + VERSION: ${{ steps.next_version.outputs.version }} + PREVIOUS_TAG: ${{ steps.previous_tag.outputs.tag }} + GH_TOKEN: ${{ github.token }} + run: | + TAG="v${VERSION}" + + RELEASE_ARGS=( + "$TAG" + --title "$TAG" + --generate-notes + ./*.tgz + ) + + if [ -n "$PREVIOUS_TAG" ]; then + RELEASE_ARGS+=(--notes-start-tag "$PREVIOUS_TAG") + fi + + gh release create "${RELEASE_ARGS[@]}" 2>&1 | tee -a "$GITHUB_STEP_SUMMARY" From b22e5fbaa899a08ec5cba2f88cc04f9356c6bb42 Mon Sep 17 00:00:00 2001 From: Devraj Mehta Date: Fri, 3 Apr 2026 21:40:18 -0400 Subject: [PATCH 2/2] Address PR review feedback - Use semver package for robust version incrementing - Filter out drafts and pre-releases when finding previous tag - Add concurrency guard to prevent publish races - Enable npm caching in setup-node Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- .github/workflows/publish.yml | 35 +++++++++++++---------------------- 1 file changed, 13 insertions(+), 22 deletions(-) diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index a928c39..d1f5436 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -21,6 +21,9 @@ jobs: publish: runs-on: ubuntu-latest environment: npm-publish + concurrency: + group: publish-npm + cancel-in-progress: false steps: - name: Checkout repository uses: actions/checkout@v4 @@ -32,6 +35,7 @@ jobs: with: node-version: 22 registry-url: "https://registry.npmjs.org" + cache: npm - name: Get current npm version id: current_version @@ -43,31 +47,18 @@ jobs: - name: Calculate next version id: next_version - env: - CURRENT: ${{ steps.current_version.outputs.version }} - VERSION_TYPE: ${{ inputs.version_type }} run: | - IFS='.' read -r MAJOR MINOR PATCH <<< "$CURRENT" - - case "$VERSION_TYPE" in - major) - MAJOR=$((MAJOR + 1)) - MINOR=0 - PATCH=0 - ;; - minor) - MINOR=$((MINOR + 1)) - PATCH=0 - ;; - patch) - PATCH=$((PATCH + 1)) - ;; - esac - - NEXT_VERSION="${MAJOR}.${MINOR}.${PATCH}" + CURRENT="${{ steps.current_version.outputs.version }}" + NEXT_VERSION=$(npx --yes semver "$CURRENT" -i "$VERSION_TYPE") + if [ -z "$NEXT_VERSION" ]; then + echo "Failed to calculate next version from $CURRENT using increment $VERSION_TYPE" >&2 + exit 1 + fi echo "version=$NEXT_VERSION" >> "$GITHUB_OUTPUT" echo "Next version: $NEXT_VERSION (incremented $VERSION_TYPE from $CURRENT)" echo "- Next version: \`$NEXT_VERSION\` (incremented $VERSION_TYPE from \`$CURRENT\`)" >> "$GITHUB_STEP_SUMMARY" + env: + VERSION_TYPE: ${{ inputs.version_type }} - name: Set package version env: @@ -89,7 +80,7 @@ jobs: - name: Determine previous release tag id: previous_tag run: | - PREVIOUS_TAG=$(gh release list --limit 1 --json tagName --jq '.[0].tagName // empty' 2>/dev/null || echo "") + PREVIOUS_TAG=$(gh release list --limit 1 --exclude-drafts --exclude-pre-releases --json tagName --jq '.[0].tagName // empty' 2>/dev/null || echo "") echo "tag=$PREVIOUS_TAG" >> "$GITHUB_OUTPUT" if [ -n "$PREVIOUS_TAG" ]; then echo "Previous release tag: $PREVIOUS_TAG"