Skip to content

Commit b0b5d51

Browse files
committed
feat: Add GitHub Actions for CI/CD and security scanning
- Add publish workflow for automatic npm publishing - Add CI workflow for PR validation - Add version bump workflow for easy releases - Add security scanning with TruffleHog and Trivy - Add pre-commit hooks for local secret detection - Fix Bing Webmaster API client lifecycle issue - Add internal docs directory for sensitive documentation - Add version sync script to keep package.json and Python versions aligned
1 parent f908e55 commit b0b5d51

29 files changed

+3501
-458
lines changed

.env.example

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,4 +4,4 @@
44
BING_WEBMASTER_API_KEY=your_api_key_here
55

66
# Optional: Logging level (DEBUG, INFO, WARNING, ERROR)
7-
# LOG_LEVEL=INFO
7+
# LOG_LEVEL=INFO

.github/workflows/README.md

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
# GitHub Actions Workflows
2+
3+
This directory contains automated workflows for CI/CD:
4+
5+
## Workflows
6+
7+
### 1. CI (`ci.yml`)
8+
- **Triggers**: Pull requests and pushes to non-main branches
9+
- **Purpose**: Run tests and validation on multiple OS and runtime versions
10+
- **Matrix**: Tests on Ubuntu, Windows, macOS with Node.js 18.x/20.x and Python 3.10/3.11/3.12
11+
12+
### 2. Publish (`publish.yml`)
13+
- **Triggers**:
14+
- Push to main branch
15+
- GitHub release creation
16+
- Manual workflow dispatch
17+
- **Purpose**: Automatically publish to npm when version changes
18+
- **Features**:
19+
- Checks if version already exists on npm
20+
- Only publishes new versions
21+
- Creates GitHub releases automatically
22+
23+
### 3. Version Bump (`version-bump.yml`)
24+
- **Triggers**: Manual workflow dispatch
25+
- **Purpose**: Bump version numbers in both package.json and Python files
26+
- **Options**: patch, minor, or major version bumps
27+
28+
## Setup Required
29+
30+
### 1. NPM Token
31+
1. Go to https://www.npmjs.com/
32+
2. Sign in to your account
33+
3. Click on your profile → Access Tokens
34+
4. Generate a new Classic Token with "Automation" type
35+
5. Copy the token
36+
37+
### 2. Add Secret to GitHub
38+
1. Go to your repository settings
39+
2. Navigate to Secrets and variables → Actions
40+
3. Click "New repository secret"
41+
4. Name: `NPM_TOKEN`
42+
5. Value: Paste your npm token
43+
6. Click "Add secret"
44+
45+
## Usage
46+
47+
### Automatic Publishing
48+
1. Update version in `package.json`
49+
2. Update version in `mcp_server_bwt/version.py`
50+
3. Commit and push to main
51+
4. GitHub Actions will automatically publish to npm
52+
53+
### Manual Version Bump
54+
1. Go to Actions tab in GitHub
55+
2. Select "Version Bump" workflow
56+
3. Click "Run workflow"
57+
4. Select version type (patch/minor/major)
58+
5. The workflow will:
59+
- Bump versions in both files
60+
- Create commits
61+
- Push changes back to main
62+
- Trigger the publish workflow
63+
64+
### Creating a Release
65+
1. Go to Releases in GitHub
66+
2. Click "Create a new release"
67+
3. Create a tag (e.g., v1.0.1)
68+
4. The publish workflow will automatically run
69+
70+
## Best Practices
71+
72+
1. Always ensure tests pass before merging to main
73+
2. Use semantic versioning (major.minor.patch)
74+
3. Keep package.json and Python versions in sync
75+
4. Add `[skip ci]` to commit messages to skip CI runs

.github/workflows/ci.yml

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
name: CI
2+
3+
on:
4+
pull_request:
5+
branches: [main]
6+
push:
7+
branches-ignore: [main]
8+
9+
jobs:
10+
test:
11+
runs-on: ${{ matrix.os }}
12+
strategy:
13+
matrix:
14+
os: [ubuntu-latest, windows-latest, macos-latest]
15+
node-version: [18.x, 20.x]
16+
python-version: ['3.10', '3.11', '3.12']
17+
18+
steps:
19+
- uses: actions/checkout@v4
20+
21+
- name: Use Node.js ${{ matrix.node-version }}
22+
uses: actions/setup-node@v4
23+
with:
24+
node-version: ${{ matrix.node-version }}
25+
26+
- name: Set up Python ${{ matrix.python-version }}
27+
uses: actions/setup-python@v5
28+
with:
29+
python-version: ${{ matrix.python-version }}
30+
31+
- name: Install uv (Unix)
32+
if: runner.os != 'Windows'
33+
run: |
34+
curl -LsSf https://astral.sh/uv/install.sh | sh
35+
echo "$HOME/.cargo/bin" >> $GITHUB_PATH
36+
37+
- name: Install uv (Windows)
38+
if: runner.os == 'Windows'
39+
run: |
40+
irm https://astral.sh/uv/install.ps1 | iex
41+
echo "$env:USERPROFILE\.cargo\bin" | Out-File -FilePath $env:GITHUB_PATH -Encoding utf8 -Append
42+
43+
- name: Install dependencies
44+
run: |
45+
npm ci
46+
uv pip install --python python${{ matrix.python-version }} -e .
47+
48+
- name: Run validation
49+
run: npm run validate
50+
51+
- name: Run tests
52+
run: npm test
53+
54+
- name: Test Python import
55+
run: |
56+
python -c "from mcp_server_bwt import version; print('Version:', version.__version__)"
57+
58+
- name: Check package
59+
run: npm run check-publish

.github/workflows/publish.yml

Lines changed: 118 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,118 @@
1+
name: Publish to npm
2+
3+
on:
4+
push:
5+
branches:
6+
- main
7+
release:
8+
types: [published]
9+
workflow_dispatch:
10+
11+
jobs:
12+
test:
13+
runs-on: ubuntu-latest
14+
strategy:
15+
matrix:
16+
node-version: [18.x, 20.x]
17+
python-version: ['3.10', '3.11', '3.12']
18+
19+
steps:
20+
- uses: actions/checkout@v4
21+
22+
- name: Use Node.js ${{ matrix.node-version }}
23+
uses: actions/setup-node@v4
24+
with:
25+
node-version: ${{ matrix.node-version }}
26+
27+
- name: Set up Python ${{ matrix.python-version }}
28+
uses: actions/setup-python@v5
29+
with:
30+
python-version: ${{ matrix.python-version }}
31+
32+
- name: Install uv
33+
run: |
34+
curl -LsSf https://astral.sh/uv/install.sh | sh
35+
echo "$HOME/.cargo/bin" >> $GITHUB_PATH
36+
37+
- name: Install dependencies
38+
run: |
39+
npm ci
40+
uv pip install --python python${{ matrix.python-version }} -e .
41+
42+
- name: Run validation
43+
run: npm run validate
44+
45+
- name: Test Python import
46+
run: |
47+
python -c "from mcp_server_bwt import version; print('Version:', version.__version__)"
48+
49+
publish:
50+
needs: test
51+
runs-on: ubuntu-latest
52+
if: github.event_name == 'release' || (github.event_name == 'push' && github.ref == 'refs/heads/main')
53+
54+
steps:
55+
- uses: actions/checkout@v4
56+
57+
- name: Setup Node.js
58+
uses: actions/setup-node@v4
59+
with:
60+
node-version: '20.x'
61+
registry-url: 'https://registry.npmjs.org'
62+
63+
- name: Set up Python
64+
uses: actions/setup-python@v5
65+
with:
66+
python-version: '3.11'
67+
68+
- name: Install uv
69+
run: |
70+
curl -LsSf https://astral.sh/uv/install.sh | sh
71+
echo "$HOME/.cargo/bin" >> $GITHUB_PATH
72+
73+
- name: Install dependencies
74+
run: |
75+
npm ci
76+
uv pip install --python python3.11 -e .
77+
78+
- name: Check if version changed
79+
id: version-check
80+
run: |
81+
# Get the current version from package.json
82+
CURRENT_VERSION=$(node -p "require('./package.json').version")
83+
echo "current_version=$CURRENT_VERSION" >> $GITHUB_OUTPUT
84+
85+
# Check if this version is already published
86+
if npm view @isiahw1/mcp-server-bing-webmaster@$CURRENT_VERSION version 2>/dev/null; then
87+
echo "Version $CURRENT_VERSION already exists on npm"
88+
echo "should_publish=false" >> $GITHUB_OUTPUT
89+
else
90+
echo "Version $CURRENT_VERSION not found on npm, will publish"
91+
echo "should_publish=true" >> $GITHUB_OUTPUT
92+
fi
93+
94+
- name: Build
95+
if: steps.version-check.outputs.should_publish == 'true'
96+
run: npm run build
97+
98+
- name: Publish to npm
99+
if: steps.version-check.outputs.should_publish == 'true'
100+
run: npm publish
101+
env:
102+
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
103+
104+
- name: Create GitHub Release (if push to main)
105+
if: github.event_name == 'push' && steps.version-check.outputs.should_publish == 'true'
106+
uses: actions/create-release@v1
107+
env:
108+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
109+
with:
110+
tag_name: v${{ steps.version-check.outputs.current_version }}
111+
release_name: Release v${{ steps.version-check.outputs.current_version }}
112+
body: |
113+
Automated release for version ${{ steps.version-check.outputs.current_version }}
114+
115+
## Changes
116+
See [commit history](https://github.com/${{ github.repository }}/compare/v${{ steps.version-check.outputs.previous_version }}...v${{ steps.version-check.outputs.current_version }}) for details.
117+
draft: false
118+
prerelease: false

.github/workflows/security.yml

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
name: Security Scan
2+
3+
on:
4+
pull_request:
5+
branches: [main]
6+
push:
7+
branches: [main]
8+
schedule:
9+
# Run weekly on Mondays at 9 AM UTC
10+
- cron: '0 9 * * 1'
11+
12+
jobs:
13+
trufflehog:
14+
name: Secret Scanning
15+
runs-on: ubuntu-latest
16+
steps:
17+
- uses: actions/checkout@v4
18+
with:
19+
fetch-depth: 0
20+
21+
- name: TruffleHog OSS
22+
uses: trufflesecurity/trufflehog@main
23+
with:
24+
path: ./
25+
base: ${{ github.event.repository.default_branch }}
26+
head: HEAD
27+
extra_args: --debug --only-verified
28+
29+
dependencies:
30+
name: Dependency Scanning
31+
runs-on: ubuntu-latest
32+
steps:
33+
- uses: actions/checkout@v4
34+
35+
- name: Run Trivy vulnerability scanner
36+
uses: aquasecurity/trivy-action@master
37+
with:
38+
scan-type: 'fs'
39+
scan-ref: '.'
40+
format: 'sarif'
41+
output: 'trivy-results.sarif'
42+
43+
- name: Upload Trivy scan results to GitHub Security tab
44+
uses: github/codeql-action/upload-sarif@v3
45+
if: always()
46+
with:
47+
sarif_file: 'trivy-results.sarif'

.github/workflows/version-bump.yml

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
name: Version Bump
2+
3+
on:
4+
workflow_dispatch:
5+
inputs:
6+
version:
7+
description: 'Version type (patch, minor, major)'
8+
required: true
9+
default: 'patch'
10+
type: choice
11+
options:
12+
- patch
13+
- minor
14+
- major
15+
16+
jobs:
17+
version-bump:
18+
runs-on: ubuntu-latest
19+
20+
steps:
21+
- uses: actions/checkout@v4
22+
with:
23+
token: ${{ secrets.GITHUB_TOKEN }}
24+
25+
- name: Setup Node.js
26+
uses: actions/setup-node@v4
27+
with:
28+
node-version: '20.x'
29+
30+
- name: Configure Git
31+
run: |
32+
git config --local user.email "github-actions[bot]@users.noreply.github.com"
33+
git config --local user.name "github-actions[bot]"
34+
35+
- name: Install dependencies
36+
run: npm ci
37+
38+
- name: Bump version
39+
run: |
40+
npm version ${{ github.event.inputs.version }} -m "chore: bump version to %s [skip ci]"
41+
VERSION=$(node -p "require('./package.json').version")
42+
echo "new_version=$VERSION" >> $GITHUB_ENV
43+
44+
- name: Update Python version file
45+
run: |
46+
echo "__version__ = \"${{ env.new_version }}\"" > mcp_server_bwt/version.py
47+
git add mcp_server_bwt/version.py
48+
git commit -m "chore: update Python version to ${{ env.new_version }} [skip ci]"
49+
50+
- name: Push changes
51+
run: |
52+
git push
53+
git push --tags

.gitignore

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -179,4 +179,7 @@ results/
179179
# API keys and secrets
180180
.env
181181
.env.*
182-
!.env.example
182+
!.env.example
183+
184+
# Internal documentation (not for public)
185+
.internal-docs/

0 commit comments

Comments
 (0)