Skip to content

feat(tools): raw_api_request — прямой GET к API Яндекс.Трекера #46

feat(tools): raw_api_request — прямой GET к API Яндекс.Трекера

feat(tools): raw_api_request — прямой GET к API Яндекс.Трекера #46

Workflow file for this run

name: Release
on:
push:
branches:
- main
workflow_dispatch:
permissions:
contents: write
issues: write
pull-requests: write
packages: write
id-token: write
jobs:
# Job 1: Run semantic-release to determine version and create release
release:
name: Semantic Release
runs-on: ubuntu-latest
outputs:
new_release_published: ${{ steps.semantic.outputs.new_release_published }}
new_release_version: ${{ steps.semantic.outputs.new_release_version }}
steps:
- name: Checkout code
uses: actions/checkout@v4
with:
fetch-depth: 0
persist-credentials: false
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '22.x'
cache: 'npm'
- name: Install dependencies
run: npm ci
- name: Run full validation
run: npm run validate
env:
CI: true
- name: Run smoke tests
run: npm run test:smoke
- name: Semantic Release
id: semantic
uses: cycjimmy/semantic-release-action@v4
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
# Job 2: Publish to NPM using OIDC Trusted Publishing (no NPM_TOKEN needed!)
publish-npm:
name: Publish to NPM Registry (Trusted Publishing)
needs: release
runs-on: ubuntu-latest
if: needs.release.outputs.new_release_published == 'true'
# id-token: write MUST be declared at job level — workflow-level permissions
# are not inherited for id-token when a job uses `environment:`. Without this
# explicit block, ACTIONS_ID_TOKEN_REQUEST_URL is not set, npm can't mint an
# OIDC token, and trusted publishing silently returns HTTP 404 from registry.
permissions:
contents: read
id-token: write
# Environment must be configured in GitHub repo settings
# and match the trusted publisher config on npmjs.com
environment: npm-publish
steps:
- name: Checkout code
uses: actions/checkout@v4
with:
ref: v${{ needs.release.outputs.new_release_version }}
- name: Setup Node.js 24 with NPM registry
# Node 24 ships with npm 11.x. Node 22 ships with npm 10.x which does
# NOT support OIDC trusted publishing — it fails with ENEEDAUTH even
# when ACTIONS_ID_TOKEN_REQUEST_* env vars are set (OIDC support was
# added in npm 11.5.1). Upgrading npm inside the runner via
# `npm install -g npm@latest` hits a self-update bootstrap bug
# (MODULE_NOT_FOUND promise-retry), so the clean solution is to use
# a Node version that already ships with npm 11.x.
uses: actions/setup-node@v4
with:
node-version: '24.x'
cache: 'npm'
registry-url: 'https://registry.npmjs.org'
- name: Install dependencies
run: npm ci
- name: Verify npm version supports OIDC
run: |
NPM_VERSION=$(npm --version)
echo "npm version: $NPM_VERSION"
# OIDC trusted publishing requires npm >= 11.5.1. sort -V puts
# versions in ascending order; if the minimum of [NPM_VERSION, 11.5.1]
# is 11.5.1, then NPM_VERSION >= 11.5.1.
LOWEST=$(printf '%s\n%s\n' "$NPM_VERSION" "11.5.1" | sort -V | head -1)
if [ "$LOWEST" != "11.5.1" ]; then
echo "❌ npm $NPM_VERSION is too old for OIDC (need ≥ 11.5.1)"
exit 1
fi
echo "✅ npm $NPM_VERSION supports OIDC trusted publishing"
- name: Build all packages
run: npm run build
- name: Reset npm auth config (OIDC prerequisite)
# actions/setup-node@v4 writes a placeholder `_authToken=XXXXX-XXXXX-XXXXX-XXXXX`
# into the user .npmrc (expected to be overridden at publish time via
# NODE_AUTH_TOKEN env). npm CLI picks it up as a bearer token and never
# attempts OIDC — publishing silently 404s at /oidc/token/exchange. The
# safest fix is to wipe the user .npmrc entirely and recreate it with
# only the registry URL.
run: |
set -euo pipefail
NPMRC="${NPM_CONFIG_USERCONFIG:-$HOME/.npmrc}"
rm -f "$NPMRC" "$HOME/.npmrc"
mkdir -p "$(dirname "$NPMRC")"
printf 'registry=https://registry.npmjs.org/\n' > "$NPMRC"
# OIDC Trusted Publishing: npm CLI automatically uses id-token for auth.
# No NPM_TOKEN needed! Provenance is published automatically.
#
# REQUIRES on npm side (per package):
# Settings → Publishing access → Trusted Publisher
# Publisher: GitHub Actions
# Organization or user: FractalizeR (case-sensitive!)
# Repository: mcp_servers
# Workflow filename: release.yml (just the filename, no path)
# Environment name: npm-publish
#
# Common gotcha: Organization is case-sensitive. `fractalizer` lowercase
# silently 404s while OIDC claims carry `FractalizeR` from GitHub.
- name: Publish packages to NPM (OIDC Trusted Publishing)
env:
RELEASE_VERSION: ${{ needs.release.outputs.new_release_version }}
# Override setup-node's placeholder. setup-node@v4 exports
# NODE_AUTH_TOKEN=XXXXX-XXXXX-XXXXX-XXXXX as a literal placeholder.
# If npm CLI picks this up from env (independently of .npmrc), it
# treats it as a valid bearer token and never attempts OIDC.
NODE_AUTH_TOKEN: ''
run: |
set -euo pipefail
# Packages published in dependency order:
# framework (infrastructure → cli/core → search)
# → scoped servers → unscoped wrappers
PACKAGES=(
"@fractalizer/mcp-infrastructure"
"@fractalizer/mcp-cli"
"@fractalizer/mcp-core"
"@fractalizer/mcp-search"
"@fractalizer/mcp-server-yandex-tracker"
"@fractalizer/mcp-server-yandex-wiki"
"@fractalizer/mcp-server-ticktick"
"mcp-server-yandex-tracker"
"mcp-server-yandex-wiki"
"mcp-server-ticktick"
)
TOTAL=${#PACKAGES[@]}
echo "📦 Publishing $TOTAL packages @ $RELEASE_VERSION"
echo "🔐 Using GitHub OIDC (no NPM_TOKEN)"
echo ""
# Phase 1: publish (idempotent — skip if already on registry)
for i in "${!PACKAGES[@]}"; do
PKG="${PACKAGES[$i]}"
NUM=$((i + 1))
printf "[%d/%d] %s@%s ... " "$NUM" "$TOTAL" "$PKG" "$RELEASE_VERSION"
if npm view "$PKG@$RELEASE_VERSION" version \
--registry=https://registry.npmjs.org/ >/dev/null 2>&1; then
echo "already published, skipping"
continue
fi
echo "publishing..."
# No `||` masking: any failure aborts the job (set -e).
npm publish --workspace="$PKG" --access public
echo " ✅ published"
done
# Phase 2: verify all versions are visible on registry with retry.
# npm publish may take a few seconds to propagate; downstream jobs
# (build-mcpb) need packages resolvable before they `npm ci`.
echo ""
echo "🔍 Verifying propagation on registry (timeout 60s per package)..."
for PKG in "${PACKAGES[@]}"; do
printf " %s@%s ... " "$PKG" "$RELEASE_VERSION"
for attempt in 1 2 3 4 5 6 7 8 9 10 11 12; do
if npm view "$PKG@$RELEASE_VERSION" version \
--registry=https://registry.npmjs.org/ >/dev/null 2>&1; then
echo "ok"
break
fi
if [ "$attempt" = "12" ]; then
echo "NOT VISIBLE after 12 attempts (60s)"
exit 1
fi
sleep 5
done
done
echo ""
echo "✅ All $TOTAL packages published and verified @ $RELEASE_VERSION"
# Job 3: Build MCPB bundles for all servers and attach to GitHub release
# Note: Depends on publish-npm to ensure internal dependencies are available on npm registry
build-mcpb:
name: Build MCPB Bundles
needs: [release, publish-npm]
runs-on: ubuntu-latest
if: needs.release.outputs.new_release_published == 'true'
steps:
- name: Checkout code
uses: actions/checkout@v4
with:
ref: v${{ needs.release.outputs.new_release_version }}
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '22.x'
cache: 'npm'
- name: Install dependencies
# publish-npm verifies each package is visible on registry before
# completing, so no extra propagation wait is needed here.
run: npm ci
- name: Build all packages first
run: npm run build
- name: Build all MCPB bundles
# No `||` masking: any MCPB build failure aborts the job.
run: |
set -euo pipefail
echo "📦 Building MCPB bundles for all servers..."
npm run build:mcpb --workspace=@fractalizer/mcp-server-yandex-tracker
npm run build:mcpb --workspace=@fractalizer/mcp-server-yandex-wiki
npm run build:mcpb --workspace=@fractalizer/mcp-server-ticktick
- name: Rename and upload MCPB files
run: |
VERSION="${{ needs.release.outputs.new_release_version }}"
UPLOAD_FILES=""
# Yandex Tracker
YT_FILE=$(ls fractalizer_mcp_yandex_tracker-*.mcpb 2>/dev/null | head -n 1)
if [ -n "$YT_FILE" ]; then
mv "$YT_FILE" "mcp-server-yandex-tracker.mcpb"
UPLOAD_FILES="$UPLOAD_FILES mcp-server-yandex-tracker.mcpb"
echo "✅ yandex-tracker MCPB ready"
fi
# Yandex Wiki
YW_FILE=$(ls fractalizer_mcp_yandex_wiki-*.mcpb 2>/dev/null | head -n 1)
if [ -n "$YW_FILE" ]; then
mv "$YW_FILE" "mcp-server-yandex-wiki.mcpb"
UPLOAD_FILES="$UPLOAD_FILES mcp-server-yandex-wiki.mcpb"
echo "✅ yandex-wiki MCPB ready"
fi
# TickTick
TT_FILE=$(ls fractalizer_mcp_ticktick-*.mcpb 2>/dev/null | head -n 1)
if [ -n "$TT_FILE" ]; then
mv "$TT_FILE" "mcp-server-ticktick.mcpb"
UPLOAD_FILES="$UPLOAD_FILES mcp-server-ticktick.mcpb"
echo "✅ ticktick MCPB ready"
fi
if [ -z "$UPLOAD_FILES" ]; then
echo "⚠️ No MCPB files found, skipping upload"
exit 0
fi
echo ""
echo "📤 Uploading to release v${VERSION}..."
# Upload all MCPB files to GitHub release
gh release upload "v${VERSION}" $UPLOAD_FILES --clobber
echo "✅ All MCPB bundles uploaded!"
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
# Job 4: Notify success
notify-success:
name: Notify Release Success
needs: [release, publish-npm, build-mcpb]
runs-on: ubuntu-latest
if: needs.release.outputs.new_release_published == 'true'
steps:
- name: Success message
run: |
echo "🎉 Release ${{ needs.release.outputs.new_release_version }} completed successfully!"
echo "✅ Semantic Release: version determined and tagged"
echo "✅ NPM packages published with OIDC Trusted Publishing"
echo "✅ Provenance attestations generated automatically"
echo "✅ MCPB bundle attached to release"