Generate Windmill MCP Server Version #7
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: Generate Windmill MCP Server Version | |
| on: | |
| workflow_dispatch: | |
| inputs: | |
| windmill_version: | |
| description: 'Windmill version (e.g., 1.520.1 or "latest")' | |
| required: true | |
| default: "latest" | |
| type: string | |
| schedule: | |
| - cron: "0 0 * * 1" # Run weekly on Mondays at midnight UTC (generates latest) | |
| permissions: | |
| contents: write | |
| jobs: | |
| generate: | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: Checkout repository | |
| uses: actions/checkout@v4 | |
| - name: Setup Node.js | |
| uses: actions/setup-node@v4 | |
| with: | |
| node-version: "18" | |
| cache: "npm" | |
| - name: Install dependencies | |
| run: npm ci | |
| - name: Start Windmill instance | |
| run: | | |
| echo "🚀 Starting Windmill instance..." | |
| npm run docker:up | |
| - name: Wait for Windmill to be ready | |
| run: | | |
| echo "⏳ Waiting for Windmill to be ready..." | |
| npm run docker:wait | |
| timeout-minutes: 5 | |
| - name: Fetch OpenAPI spec from Windmill | |
| id: fetch-spec | |
| run: | | |
| echo "📥 Fetching OpenAPI spec from running Windmill instance..." | |
| # Ensure cache directory exists | |
| mkdir -p cache | |
| # Fetch from local Windmill instance | |
| curl -f http://localhost:8000/api/openapi.json -o cache/openapi-spec.json | |
| # Extract version from spec | |
| SPEC_VERSION=$(node -p "JSON.parse(require('fs').readFileSync('cache/openapi-spec.json', 'utf8')).info.version") | |
| echo "spec_version=$SPEC_VERSION" >> $GITHUB_OUTPUT | |
| echo "✅ Fetched OpenAPI spec version: $SPEC_VERSION" | |
| - name: Generate and build MCP server | |
| id: generate | |
| run: | | |
| echo "🔧 Generating and building MCP server from OpenAPI spec..." | |
| npm run generate | |
| # Verify generation succeeded | |
| if [ ! -f "build/src/index.ts" ]; then | |
| echo "❌ Generation failed - index.ts not found" | |
| exit 1 | |
| fi | |
| # Verify build succeeded (postgenerate hook builds automatically) | |
| if [ ! -f "build/dist/index.js" ]; then | |
| echo "❌ Build failed - build/dist/index.js not found" | |
| exit 1 | |
| fi | |
| echo "✅ MCP server generated and built successfully" | |
| - name: Run unit tests | |
| id: unit-test | |
| run: | | |
| echo "🧪 Running unit tests..." | |
| npm run test:unit 2>&1 | tee unit-test-output.txt | |
| TEST_EXIT_CODE=${PIPESTATUS[0]} | |
| echo "exit_code=$TEST_EXIT_CODE" >> $GITHUB_OUTPUT | |
| if [ "$TEST_EXIT_CODE" -eq 0 ]; then | |
| echo "✅ Unit tests passed" | |
| else | |
| echo "❌ Unit tests failed" | |
| fi | |
| exit $TEST_EXIT_CODE | |
| continue-on-error: true | |
| - name: Run E2E tests | |
| id: e2e-test | |
| env: | |
| E2E_WINDMILL_URL: http://localhost:8000 | |
| E2E_WINDMILL_TOKEN: test-super-secret | |
| E2E_WORKSPACE: admins | |
| WINDMILL_BASE_URL: http://localhost:8000 | |
| run: | | |
| echo "🧪 Running E2E tests..." | |
| npm run test:e2e 2>&1 | tee e2e-test-output.txt | |
| TEST_EXIT_CODE=${PIPESTATUS[0]} | |
| echo "exit_code=$TEST_EXIT_CODE" >> $GITHUB_OUTPUT | |
| if [ "$TEST_EXIT_CODE" -eq 0 ]; then | |
| echo "✅ E2E tests passed" | |
| else | |
| echo "⚠️ E2E tests completed with warnings" | |
| fi | |
| exit $TEST_EXIT_CODE | |
| continue-on-error: true | |
| - name: Stop Windmill | |
| if: always() | |
| run: | | |
| echo "🛑 Stopping Windmill instance..." | |
| npm run docker:down | |
| - name: Determine test status | |
| id: test-status | |
| run: | | |
| UNIT_EXIT=${{ steps.unit-test.outputs.exit_code || '1' }} | |
| E2E_EXIT=${{ steps.e2e-test.outputs.exit_code || '1' }} | |
| # STRICT: Both unit AND E2E tests must pass for release | |
| if [ "$UNIT_EXIT" = "0" ] && [ "$E2E_EXIT" = "0" ]; then | |
| echo "passed=true" >> $GITHUB_OUTPUT | |
| echo "✅ All tests passed - ready for release" | |
| else | |
| echo "passed=false" >> $GITHUB_OUTPUT | |
| echo "❌ Tests failed - no release will be created" | |
| if [ "$UNIT_EXIT" != "0" ]; then | |
| echo " - Unit tests: FAILED" | |
| fi | |
| if [ "$E2E_EXIT" != "0" ]; then | |
| echo " - E2E tests: FAILED" | |
| fi | |
| exit 1 | |
| fi | |
| - name: Get package version | |
| id: package-version | |
| if: steps.test-status.outputs.passed == 'true' | |
| run: | | |
| PKG_VERSION=$(node -p "require('./package.json').version") | |
| echo "version=$PKG_VERSION" >> $GITHUB_OUTPUT | |
| echo "📦 Package version: $PKG_VERSION" | |
| - name: Create tarball of generated code | |
| if: steps.test-status.outputs.passed == 'true' | |
| run: | | |
| echo "📦 Creating tarball of generated code..." | |
| cd build | |
| tar --exclude='./runtime' -czf ../generated-mcp-server.tar.gz . | |
| cd .. | |
| echo "✅ Tarball created" | |
| - name: Determine release tag | |
| id: release-tag | |
| if: steps.test-status.outputs.passed == 'true' | |
| run: | | |
| SPEC_VERSION="${{ steps.fetch-spec.outputs.spec_version }}" | |
| PKG_VERSION="${{ steps.package-version.outputs.version }}" | |
| INPUT_VERSION="${{ github.event.inputs.windmill_version || 'latest' }}" | |
| if [ "$INPUT_VERSION" = "latest" ]; then | |
| TAG="windmill-latest" | |
| else | |
| TAG="windmill-v${SPEC_VERSION}-mcp-${PKG_VERSION}" | |
| fi | |
| echo "tag=$TAG" >> $GITHUB_OUTPUT | |
| echo "🏷️ Release tag: $TAG" | |
| - name: Create or update release | |
| if: steps.test-status.outputs.passed == 'true' | |
| uses: softprops/action-gh-release@v1 | |
| with: | |
| tag_name: ${{ steps.release-tag.outputs.tag }} | |
| name: Windmill ${{ steps.fetch-spec.outputs.spec_version }} MCP Server | |
| body: | | |
| ## Windmill MCP Server | |
| **Windmill API Version**: ${{ steps.fetch-spec.outputs.spec_version }} | |
| **MCP Package Version**: ${{ steps.package-version.outputs.version }} | |
| **Generated**: ${{ github.event.repository.updated_at }} | |
| ### Test Results | |
| - ✅ Unit tests passed | |
| - ✅ E2E tests passed | |
| ### Installation | |
| This is a pre-generated MCP server artifact. The main package will automatically download this when you specify: | |
| ```bash | |
| WINDMILL_VERSION=${{ steps.fetch-spec.outputs.spec_version }} npx windmill-mcp | |
| ``` | |
| Or use latest: | |
| ```bash | |
| npx windmill-mcp | |
| ``` | |
| ### Files | |
| - `generated-mcp-server.tar.gz` - Generated MCP server code | |
| - `openapi-spec.json` - OpenAPI specification used for generation | |
| --- | |
| Generated by workflow: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }} | |
| files: | | |
| generated-mcp-server.tar.gz | |
| cache/openapi-spec.json | |
| draft: false | |
| prerelease: false | |
| make_latest: ${{ github.event.inputs.windmill_version == 'latest' || github.event_name == 'schedule' }} | |
| - name: Upload test results as artifacts | |
| if: always() | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: test-results-${{ steps.fetch-spec.outputs.spec_version }} | |
| path: | | |
| unit-test-output.txt | |
| e2e-test-output.txt | |
| retention-days: 30 | |
| - name: Workflow Summary | |
| if: always() | |
| run: | | |
| echo "## Workflow Summary" >> $GITHUB_STEP_SUMMARY | |
| echo "" >> $GITHUB_STEP_SUMMARY | |
| echo "- **Windmill API Version**: ${{ steps.fetch-spec.outputs.spec_version }}" >> $GITHUB_STEP_SUMMARY | |
| echo "- **MCP Package Version**: ${{ steps.package-version.outputs.version }}" >> $GITHUB_STEP_SUMMARY | |
| echo "- **Release Tag**: \`${{ steps.release-tag.outputs.tag }}\`" >> $GITHUB_STEP_SUMMARY | |
| echo "- **Tests Passed**: ${{ steps.test-status.outputs.passed == 'true' && '✅ Yes' || '❌ No' }}" >> $GITHUB_STEP_SUMMARY | |
| echo "" >> $GITHUB_STEP_SUMMARY | |
| if [ "${{ steps.test-status.outputs.passed }}" = "true" ]; then | |
| echo "### ✅ Success!" >> $GITHUB_STEP_SUMMARY | |
| echo "" >> $GITHUB_STEP_SUMMARY | |
| echo "The MCP server was generated, tested, and released successfully." >> $GITHUB_STEP_SUMMARY | |
| echo "" >> $GITHUB_STEP_SUMMARY | |
| echo "**Installation:**" >> $GITHUB_STEP_SUMMARY | |
| echo "\`\`\`bash" >> $GITHUB_STEP_SUMMARY | |
| echo "# Use this version" >> $GITHUB_STEP_SUMMARY | |
| echo "WINDMILL_VERSION=${{ steps.fetch-spec.outputs.spec_version }} npx windmill-mcp" >> $GITHUB_STEP_SUMMARY | |
| echo "\`\`\`" >> $GITHUB_STEP_SUMMARY | |
| else | |
| echo "### ❌ Tests Failed" >> $GITHUB_STEP_SUMMARY | |
| echo "" >> $GITHUB_STEP_SUMMARY | |
| echo "The MCP server was generated but tests failed. No release was created." >> $GITHUB_STEP_SUMMARY | |
| fi |