name: Publish Packages to GitHub Packages on: push: tags: - 'v[0-9]+.[0-9]+.[0-9]+' # Strict version pattern only workflow_dispatch: inputs: version: description: 'Version to publish (e.g., 1.0.0)' required: true default: '1.0.0' confirm_release: description: 'Type "release" to confirm' required: true jobs: security-validation: runs-on: ubuntu-latest outputs: should_publish: ${{ steps.validation.outputs.should_publish }} version: ${{ steps.validation.outputs.version }} steps: - name: Checkout code uses: actions/checkout@v4 - name: Validate Release Request id: validation run: | # Extract version from tag or input if [[ "${{ github.ref_type }}" == "tag" ]]; then VERSION="${{ github.ref_name }}" VERSION="${VERSION#v}" # Remove 'v' prefix else VERSION="${{ github.event.inputs.version }}" CONFIRM="${{ github.event.inputs.confirm_release }}" # Validate manual confirmation if [[ "$CONFIRM" != "release" ]]; then echo "❌ Manual confirmation failed" echo "should_publish=false" >> $GITHUB_OUTPUT exit 1 fi fi # Validate version format if [[ ! "$VERSION" =~ ^[0-9]+\.[0-9]+\.[0-9]+$ ]]; then echo "❌ Invalid version format: $VERSION" echo "should_publish=false" >> $GITHUB_OUTPUT exit 1 fi # Check if this is a new version (not already published) echo "✅ Version validation passed: $VERSION" echo "should_publish=true" >> $GITHUB_OUTPUT echo "version=$VERSION" >> $GITHUB_OUTPUT request-approval: runs-on: ubuntu-latest needs: security-validation if: needs.security-validation.outputs.should_publish == 'true' steps: - name: Request Manual Approval uses: trstringer/manual-approval@v1 with: secret: ${{ github.TOKEN }} approvers: security-team,release-managers minimum-approvals: 2 issue-title: "🚀 Release v${{ needs.security-validation.outputs.version }} Approval Required" issue-body: | ## 📦 Package Release Request **Version**: v${{ needs.security-validation.outputs.version }} **Triggered by**: ${{ github.actor }} **Commit**: ${{ github.sha }} ### 🔍 Security Checks - ✅ Version format validated - ✅ Release confirmation received - ✅ Security scan passed (if applicable) ### 📋 Packages to Publish - aitbc-agent-sdk (Python) - explorer-web (Node.js) --- **Approve this issue to allow the release to proceed.** **Reject this issue to block the release.** publish-agent-sdk: runs-on: ubuntu-latest needs: [security-validation, request-approval] if: needs.security-validation.outputs.should_publish == 'true' permissions: contents: read packages: write steps: - name: Checkout code uses: actions/checkout@v4 - name: Set up Python 3.13 uses: actions/setup-python@v4 with: python-version: '3.13' - name: Install dependencies run: | python -m pip install --upgrade pip pip install build twine - name: Build package run: | cd packages/py/aitbc-agent-sdk python -m build - name: Security Scan Package run: | echo "🔒 Scanning package for security issues..." cd packages/py/aitbc-agent-sdk # Check for hardcoded secrets if grep -r "password\|secret\|key\|token" --include="*.py" . | grep -v "__pycache__"; then echo "❌ Potential secrets found in package" exit 1 fi echo "✅ Package security scan passed" - name: Publish to GitHub Packages run: | echo "🚀 Publishing aitbc-agent-sdk v${{ needs.security-validation.outputs.version }}" cd packages/py/aitbc-agent-sdk # Use dedicated token if available, otherwise fallback to GitHub token TOKEN="${{ secrets.PYPI_TOKEN || secrets.GITHUB_TOKEN }}" python -m twine upload --repository-url https://npm.pkg.github.com/:_authToken=$TOKEN dist/* env: TWINE_USERNAME: ${{ secrets.PYPI_USERNAME || github.actor }} TWINE_PASSWORD: ${{ secrets.PYPI_TOKEN || secrets.GITHUB_TOKEN }} publish-explorer-web: runs-on: ubuntu-latest needs: [security-validation, request-approval] if: needs.security-validation.outputs.should_publish == 'true' permissions: contents: read packages: write steps: - name: Checkout code uses: actions/checkout@v4 - name: Set up Node.js uses: actions/setup-node@v4 with: node-version: '20' registry-url: 'https://npm.pkg.github.com' - name: Install dependencies run: | cd apps/explorer-web npm ci - name: Build package run: | cd apps/explorer-web npm run build - name: Security Scan Package run: | echo "🔒 Scanning package for security issues..." cd apps/explorer-web # Check for hardcoded secrets if grep -r "password\|secret\|key\|token" --include="*.js" --include="*.json" . | grep -v "node_modules"; then echo "❌ Potential secrets found in package" exit 1 fi echo "✅ Package security scan passed" - name: Publish to GitHub Packages run: | echo "🚀 Publishing explorer-web v${{ needs.security-validation.outputs.version }}" cd apps/explorer-web npm publish env: NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN || secrets.GITHUB_TOKEN }} release-notification: runs-on: ubuntu-latest needs: [security-validation, publish-agent-sdk, publish-explorer-web] if: always() && needs.security-validation.outputs.should_publish == 'true' steps: - name: Notify Release Success run: | echo "🎉 Release v${{ needs.security-validation.outputs.version }} completed successfully!" echo "📦 Published packages:" echo " - aitbc-agent-sdk (Python)" echo " - explorer-web (Node.js)" # Create release notification echo "## 🚀 Release v${{ needs.security-validation.outputs.version }} Published" >> $GITHUB_STEP_SUMMARY echo "" >> $GITHUB_STEP_SUMMARY echo "### ✅ Successfully Published" >> $GITHUB_STEP_SUMMARY echo "- aitbc-agent-sdk (Python package)" >> $GITHUB_STEP_SUMMARY echo "- explorer-web (Node.js package)" >> $GITHUB_STEP_SUMMARY echo "" >> $GITHUB_STEP_SUMMARY echo "### 🔒 Security Checks Passed" >> $GITHUB_STEP_SUMMARY echo "- Version format validated" >> $GITHUB_STEP_SUMMARY echo "- Manual approval received" >> $GITHUB_STEP_SUMMARY echo "- Package security scans passed" >> $GITHUB_STEP_SUMMARY echo "- Dedicated publishing tokens used" >> $GITHUB_STEP_SUMMARY