From 0d6efda6f3fe2234e3eb0029295b4a45997b1cbd Mon Sep 17 00:00:00 2001 From: adityamparikh Date: Tue, 4 Nov 2025 21:32:31 -0500 Subject: [PATCH 1/6] docs: add a tutorial --- solr-mcp-tutorial.html | 817 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 817 insertions(+) create mode 100644 solr-mcp-tutorial.html diff --git a/solr-mcp-tutorial.html b/solr-mcp-tutorial.html new file mode 100644 index 0000000..cea07d4 --- /dev/null +++ b/solr-mcp-tutorial.html @@ -0,0 +1,817 @@ + + + + + + Solr MCP Server - Usage Tutorial + + + +

Solr MCP Server - Usage Tutorial

+ +

The Solr MCP (Model Context Protocol) Server enables AI assistants like Claude to interact with Apache Solr through a + standardized protocol. This guide provides comprehensive instructions for setting up, configuring, and using the + Solr MCP Server.

+ +
+

Table of Contents

+ +
+ +

Overview

+ +

The Solr MCP Server is a Spring AI-based implementation that provides AI assistants with tools to interact with + Apache Solr. It supports both STDIO and HTTP transport modes, enabling flexible deployment options.

+ +

What's Inside

+ + +
+ Model Context Protocol (MCP)
+ MCP is an open protocol that standardizes how applications provide context to LLMs. The Solr MCP Server implements + this protocol to make Solr's capabilities accessible to AI assistants. +
+ +

Prerequisites

+ + + +
+ Quick Start with Sample Data: The repository includes a Docker Compose file to start Solr with + pre-populated collections (books, films, techproducts). Run: docker compose up -d +
+ +

Integration with MCP Clients

+ +

The Solr MCP Server can be integrated with any MCP-compatible client. Both STDIO mode and HTTP + mode are fully supported.

+ +

STDIO Mode

+ +

STDIO mode uses standard input/output for communication. This is the default mode and works with Claude Desktop, + GitHub Copilot, VSCode extensions, and other MCP clients.

+ +

Claude Desktop

+ +

Edit your configuration file:

+ + +

Using Docker:

+
{
+  "mcpServers": {
+    "solr-mcp": {
+      "command": "docker",
+      "args": ["run", "-i", "--rm", "ghcr.io/apache/solr-mcp:latest"],
+      "env": {
+        "SOLR_URL": "http://localhost:8983/solr/"
+      }
+    }
+  }
+}
+ +

Using JAR:

+
{
+  "mcpServers": {
+    "solr-mcp": {
+      "command": "java",
+      "args": ["-jar", "/absolute/path/to/solr-mcp-0.0.1-SNAPSHOT.jar"],
+      "env": {
+        "SOLR_URL": "http://localhost:8983/solr/"
+      }
+    }
+  }
+}
+ +

GitHub Copilot & VSCode Extensions (Cline, Continue)

+ +

These clients use the same configuration format.

+ +

GitHub Copilot: Add to VS Code settings (settings.json)

+

Cline: Add to Cline MCP settings

+

Continue: Add to ~/.continue/config.json

+ +

Configuration (Docker):

+
{
+  "mcpServers": {
+    "solr-mcp": {
+      "command": "docker",
+      "args": ["run", "-i", "--rm", "ghcr.io/apache/solr-mcp:latest"],
+      "env": {
+        "SOLR_URL": "http://localhost:8983/solr/"
+      }
+    }
+  }
+}
+ +

Configuration (JAR):

+
{
+  "mcpServers": {
+    "solr-mcp": {
+      "command": "java",
+      "args": ["-jar", "/absolute/path/to/solr-mcp-0.0.1-SNAPSHOT.jar"],
+      "env": {
+        "SOLR_URL": "http://localhost:8983/solr/"
+      }
+    }
+  }
+}
+ +
+ Note: Continue uses a slightly different format with an array. Wrap the above configuration in: + {"mcpServers": [...]} +
+ +

JetBrains IDEs

+ +

JetBrains IDEs (IntelliJ IDEA, PyCharm, WebStorm, etc.) support MCP through AI Assistant settings.

+ +

Navigate to Settings β†’ Tools β†’ AI Assistant β†’ Model Context Protocol and add:

+
{
+  "servers": {
+    "solr-mcp": {
+      "command": "docker",
+      "args": ["run", "-i", "--rm", "ghcr.io/apache/solr-mcp:latest"],
+      "env": {
+        "SOLR_URL": "http://localhost:8983/solr/"
+      }
+    }
+  }
+}
+ +

Alternatively, edit the MCP configuration file directly:

+ + +

MCP Inspector (STDIO)

+ +

The MCP Inspector is an official tool for testing and + debugging MCP servers.

+ +

For testing with STDIO transport:

+
# Start the server
+docker run -i --rm ghcr.io/apache/solr-mcp:latest
+
+# Or using JAR
+java -jar build/libs/solr-mcp-0.0.1-SNAPSHOT.jar
+
+# In another terminal, connect with MCP Inspector
+npx @modelcontextprotocol/inspector
+ +
+ Important: After adding or modifying MCP server configurations, completely restart your client + application (quit and reopen) for changes to take effect. +
+ +

HTTP Mode

+ +

HTTP mode uses a streamable HTTP transport. This is useful for debugging with MCP Inspector or when your client + doesn't support STDIO.

+ +

Starting the Server in HTTP Mode

+ +

Using Docker:

+
docker run -d --name solr-mcp \
+  -p 8080:8080 \
+  -e PROFILES=http \
+  -e SOLR_URL=http://localhost:8983/solr/ \
+  ghcr.io/apache/solr-mcp:latest
+ +

Using JAR:

+
PROFILES=http java -jar build/libs/solr-mcp-0.0.1-SNAPSHOT.jar
+ +

Client Configuration for HTTP Mode

+ +

All clients use the same configuration format for HTTP mode:

+ +

Claude Desktop, GitHub Copilot, Cline, Continue:

+
{
+  "mcpServers": {
+    "solr-mcp": {
+      "url": "http://localhost:8080/mcp"
+    }
+  }
+}
+ +

JetBrains IDEs:

+
{
+  "servers": {
+    "solr-mcp": {
+      "url": "http://localhost:8080/mcp"
+    }
+  }
+}
+ +

MCP Inspector (HTTP):

+
npx @modelcontextprotocol/inspector http://localhost:8080/mcp
+ +
+ Tip: Use HTTP mode with MCP + Inspector for an interactive web interface to test all available tools during development. +
+ +

Environment Variables

+ + + + + + + + + + + + + + + + + + + + + +
VariableDescriptionDefault
SOLR_URLURL of the Solr instancehttp://localhost:8983/solr/
PROFILESTransport mode (empty=STDIO, http=HTTP)(empty - STDIO mode)
+ +

Docker Network Configuration

+ +
+ Connecting to Solr from Docker: + +
+ +

Verifying Integration

+ +

Claude Desktop: Look for the πŸ”Œ icon in the bottom-right corner. Click it to see "solr-mcp" with 6 + available tools.

+ +

Other Clients: Check your client's tools/context servers panel to confirm the connection and see + available tools.

+ +

Available MCP Tools

+ +

The Solr MCP Server provides six tools accessible to AI assistants:

+ +

1. Search

+

Search Solr collections with advanced query options.

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
ParameterTypeDescriptionRequired
collectionStringSolr collection to queryYes
queryStringSolr query (defaults to *:*)No
filterQueriesArrayFilter queries (fq parameter)No
facetFieldsArrayFields to facet onNo
sortClausesArraySorting criteriaNo
startIntegerStarting offset for paginationNo
rowsIntegerNumber of rows to returnNo
+ +
+ Dynamic Fields: Solr uses dynamic field suffixes: + +
+ +

2. index_json_documents

+

Index documents from a JSON string.

+
{
+  "collection": "myCollection",
+  "json": "[{\"id\":\"1\",\"title\":\"Example\"}]"
+}
+ +

3. index_csv_documents

+

Index documents from a CSV string.

+
{
+  "collection": "myCollection",
+  "csv": "id,title\n1,Example\n2,Another"
+}
+ +

4. index_xml_documents

+

Index documents from an XML string.

+
{
+  "collection": "myCollection",
+  "xml": "<docs><doc><field name=\"id\">1</field></doc></docs>"
+}
+ +

5. listCollections

+

List all available Solr collections. No parameters required.

+ +

6. getCollectionStats

+

Retrieve statistics and metrics for a collection.

+
{
+  "collection": "books"
+}
+ +

7. checkHealth

+

Check the health status of a collection.

+
{
+  "collection": "books"
+}
+ +

8. getSchema

+

Retrieve schema information for a collection.

+
{
+  "collection": "books"
+}
+ +

Usage Examples

+ +

Example 1: Basic Search

+

User: "Search for books about science in the books collection"

+

AI Assistant uses:

+
Search({
+  "collection": "books",
+  "query": "science"
+})
+ +

Example 2: Filtered Search with Facets

+

User: "Show me fantasy books with facets by author"

+

AI Assistant uses:

+
Search({
+  "collection": "books",
+  "query": "*:*",
+  "filterQueries": ["genre_s:fantasy"],
+  "facetFields": ["author"],
+  "rows": 10
+})
+ +

Example 3: Sorting and Pagination

+

User: "Show me the newest films, sorted by year descending, page 2"

+

AI Assistant uses:

+
Search({
+  "collection": "films",
+  "query": "*:*",
+  "sortClauses": [{"field": "initial_release_date", "order": "desc"}],
+  "start": 10,
+  "rows": 10
+})
+ +

Example 4: Indexing Documents

+

User: "Add a new book to the collection"

+

AI Assistant uses:

+
index_json_documents({
+  "collection": "books",
+  "json": "[{
+    \"id\": \"new-book-1\",
+    \"name\": [\"Introduction to Solr\"],
+    \"author\": [\"Jane Developer\"],
+    \"genre_s\": \"technical\",
+    \"price\": [29.99],
+    \"inStock\": [true]
+  }]"
+})
+ +

Example 5: Collection Analysis

+

User: "What collections are available and show me stats for books"

+

AI Assistant uses:

+
listCollections()
+
+getCollectionStats({
+  "collection": "books"
+})
+ +

Troubleshooting

+ +

Connection Issues

+ +
+ Problem: "Cannot connect to Solr"
+ Solutions: + +
+ +

MCP Client Issues

+ +
+ Problem: "Server not showing in client"
+ Solutions: + +
+ +

Docker Issues

+ +
+ Problem: "Container cannot access Solr"
+ Solutions: + +
+ +

Common Query Patterns

+ +
+ Query Examples: + +
+ +

Advanced Topics

+ +

Building from Source

+ +
# Clone the repository
+git clone https://github.com/apache/solr-mcp.git
+cd solr-mcp
+
+# Build with Gradle
+./gradlew build
+
+# Run tests
+./gradlew test
+
+# Build Docker image locally
+./gradlew jibDockerBuild
+ +

Custom Solr Connection

+ +

Connect to a remote Solr instance:

+
{
+  "mcpServers": {
+    "solr-mcp": {
+      "command": "docker",
+      "args": ["run", "-i", "--rm", "ghcr.io/apache/solr-mcp:latest"],
+      "env": {
+        "SOLR_URL": "https://remote-solr.example.com:8983/solr/"
+      }
+    }
+  }
+}
+ +
+ Note: The current version supports basic Solr connections. Authentication support is planned for + future releases. +
+ +

Performance Optimization

+ + + +

Security Best Practices

+ + + +

Additional Resources

+ + + +
+ +

This guide was created for Solr MCP Server version 0.0.1-SNAPSHOT. Last updated: November 2025.

+ +

License: Apache License 2.0

+ + \ No newline at end of file From f0030bfdec5443e0acf2eb79d5b16025ad902cf0 Mon Sep 17 00:00:00 2001 From: adityamparikh Date: Sat, 8 Nov 2025 23:17:36 -0500 Subject: [PATCH 2/6] docs: clarify ASF-compliant release process; fix nightly image naming and nightlies path; mark Docker images as convenience binaries; update MCP label snippet; extend release checklist and policy notes --- .github/workflows/nightly-build.yml | 169 +++++++++++++++ .github/workflows/release-publish.yml | 297 ++++++++++++++++++++++++++ DOCKER_PUBLISHING.md | 252 ++++++++++++++++++++++ 3 files changed, 718 insertions(+) create mode 100644 .github/workflows/nightly-build.yml create mode 100644 .github/workflows/release-publish.yml create mode 100644 DOCKER_PUBLISHING.md diff --git a/.github/workflows/nightly-build.yml b/.github/workflows/nightly-build.yml new file mode 100644 index 0000000..72a3374 --- /dev/null +++ b/.github/workflows/nightly-build.yml @@ -0,0 +1,169 @@ +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. +# The ASF licenses this file to You under the Apache License, Version 2.0 +# (the "License"); you may not use this file except in compliance with +# the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# Nightly Build Workflow for Apache Solr MCP +# =========================================== +# +# This workflow creates nightly builds for the Solr MCP project and publishes +# them to Apache's nightly infrastructure and Docker Hub preview registry. +# +# Schedule: +# --------- +# Runs daily at 2 AM UTC or on manual trigger +# +# Artifacts Published: +# -------------------- +# 1. Source tarball to https://nightlies.apache.org/solr/mcp/ +# 2. Docker image to apache/solr-mcp-nightly on Docker Hub +# 3. Build artifacts to GitHub releases (pre-release) + +name: Nightly Build + +on: + schedule: + # Run at 2 AM UTC every day + - cron: '0 2 * * *' + workflow_dispatch: # Allow manual trigger + inputs: + skip_docker: + description: 'Skip Docker publishing' + required: false + type: boolean + default: false + +env: + JAVA_VERSION: '25' + JAVA_DISTRIBUTION: 'temurin' + +jobs: + nightly-build: + name: Nightly Build and Publish + runs-on: ubuntu-latest + + permissions: + contents: write + packages: write + + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Set up JDK ${{ env.JAVA_VERSION }} + uses: actions/setup-java@v4 + with: + java-version: ${{ env.JAVA_VERSION }} + distribution: ${{ env.JAVA_DISTRIBUTION }} + cache: 'gradle' + + - name: Grant execute permission for gradlew + run: chmod +x gradlew + + - name: Generate nightly version + id: version + run: | + # Generate version with date stamp + DATE_STAMP=$(date +%Y%m%d) + SHORT_SHA=$(echo ${{ github.sha }} | cut -c1-7) + NIGHTLY_VERSION="nightly-${DATE_STAMP}-${SHORT_SHA}" + echo "version=$NIGHTLY_VERSION" >> $GITHUB_OUTPUT + echo "date=$DATE_STAMP" >> $GITHUB_OUTPUT + + - name: Build project + run: ./gradlew build + + - name: Create source distribution + run: | + # Create source tarball + mkdir -p build/distributions + tar czf build/distributions/solr-mcp-${{ steps.version.outputs.version }}-src.tar.gz \ + --exclude='.git' \ + --exclude='build' \ + --exclude='.gradle' \ + --exclude='*.iml' \ + --exclude='.idea' \ + . + + # Generate SHA512 checksum + cd build/distributions + sha512sum solr-mcp-${{ steps.version.outputs.version }}-src.tar.gz > \ + solr-mcp-${{ steps.version.outputs.version }}-src.tar.gz.sha512 + + - name: Build and publish Docker image to apache/solr-mcp-nightly + if: ${{ !inputs.skip_docker }} + run: | + # Build and push to apache/solr-mcp-nightly + # Note: Requires DOCKERHUB_APACHE_USERNAME and DOCKERHUB_APACHE_TOKEN secrets + # These should be set up with Apache PMC credentials + if [[ -n "${{ secrets.DOCKERHUB_APACHE_USERNAME }}" ]]; then + ./gradlew jib \ + -Djib.to.image=apache/solr-mcp-nightly:${{ steps.version.outputs.version }} \ + -Djib.to.auth.username=${{ secrets.DOCKERHUB_APACHE_USERNAME }} \ + -Djib.to.auth.password=${{ secrets.DOCKERHUB_APACHE_TOKEN }} \ + -Djib.to.tags=${{ steps.version.outputs.version }},latest-nightly + fi + + - name: Upload to Apache Nightlies + if: ${{ secrets.APACHE_NIGHTLIES_USER != '' }} + run: | + # Upload to Apache nightlies infrastructure + # Requires APACHE_NIGHTLIES_USER and APACHE_NIGHTLIES_KEY secrets + # These are typically available to Apache committers + + # Create directory structure + UPLOAD_DIR="solr/mcp/${{ steps.version.outputs.date }}" + + # Use rsync or scp to upload to nightlies.apache.org + # This is a placeholder - actual implementation depends on Apache infra access + echo "Would upload to: https://nightlies.apache.org/${UPLOAD_DIR}/" + echo "Files to upload:" + ls -la build/distributions/ + + - name: Create GitHub pre-release + uses: softprops/action-gh-release@v1 + with: + tag_name: nightly-${{ steps.version.outputs.date }} + name: Nightly Build ${{ steps.version.outputs.date }} + prerelease: true + draft: false + files: | + build/distributions/solr-mcp-*.tar.gz + build/distributions/solr-mcp-*.sha512 + build/libs/solr-mcp-*.jar + body: | + ## Nightly Build + + **Date**: ${{ steps.version.outputs.date }} + **Commit**: ${{ github.sha }} + + ### Docker Image + ```bash + docker pull apache/solr-mcp-nightly:${{ steps.version.outputs.version }} + ``` + + ### Source Distribution + - [solr-mcp-${{ steps.version.outputs.version }}-src.tar.gz](https://github.com/${{ github.repository }}/releases/download/nightly-${{ steps.version.outputs.date }}/solr-mcp-${{ steps.version.outputs.version }}-src.tar.gz) + + **Note**: This is a nightly build and not an official Apache release. + + - name: Clean up old nightly releases + run: | + # Keep only the last 7 nightly builds + # This helps manage storage and keeps releases clean + gh release list --limit 100 | grep "^nightly-" | tail -n +8 | cut -f1 | while read tag; do + echo "Deleting old nightly release: $tag" + gh release delete "$tag" --yes --cleanup-tag + done + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} \ No newline at end of file diff --git a/.github/workflows/release-publish.yml b/.github/workflows/release-publish.yml new file mode 100644 index 0000000..fcbf6a5 --- /dev/null +++ b/.github/workflows/release-publish.yml @@ -0,0 +1,297 @@ +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. +# The ASF licenses this file to You under the Apache License, Version 2.0 +# (the "License"); you may not use this file except in compliance with +# the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# Official Release Publishing Workflow +# ===================================== +# +# Purpose: +# - Publish Docker images as convenience binaries that correspond 1:1 to a +# voted and approved source release of Apache Solr MCP. +# - NOTE: Docker images are NOT the release of record; the authoritative +# release artifacts are the signed source tarballs published to the ASF +# distribution system (dist.apache.org / mirrors). +# +# When to run: +# - AFTER the ASF voting process has completed successfully (minimum 72 hours +# and at least three +1 binding PMC votes) and the source release has been +# finalized/published. +# +# ASF Release Process (summary): +# ------------------------------ +# 1. Release Manager creates release candidate (RC) +# 2. RC is staged for voting (72-hour minimum voting period) +# 3. PMC members vote on the release +# 4. Source release is published to dist.apache.org / mirrors +# 5. After successful vote and published source, this workflow is triggered manually +# 6. Publishes Docker images to official registries as convenience binaries +# +# Prerequisites: +# -------------- +# - Release must have passed ASF voting process +# - Source release artifacts must be signed and available on dist.apache.org +# - Release Manager must have necessary credentials +# +# Manual Trigger Required: +# ------------------------ +# This workflow MUST be triggered manually by the Release Manager +# after the ASF vote passes and the source release is published. + +name: Release Publish + +on: + workflow_dispatch: + inputs: + release_version: + description: 'Release version (e.g., 1.0.0)' + required: true + type: string + release_candidate: + description: 'Release candidate number (e.g., rc1, rc2)' + required: true + type: string + vote_thread_url: + description: 'URL to the vote thread (for documentation)' + required: false + type: string + sign_with_asf_infra: + description: 'Use ASF code signing infrastructure' + required: false + type: boolean + default: false + +env: + JAVA_VERSION: '25' + JAVA_DISTRIBUTION: 'temurin' + +jobs: + validate-release: + name: Validate Release Prerequisites + runs-on: ubuntu-latest + + outputs: + proceed: ${{ steps.validation.outputs.proceed }} + + steps: + - name: Checkout code + uses: actions/checkout@v4 + with: + ref: "v${{ inputs.release_version }}-${{ inputs.release_candidate }}" + + - name: Validate release tag exists + id: validation + run: | + # Check if the release tag exists + if git rev-parse "v${{ inputs.release_version }}-${{ inputs.release_candidate }}" >/dev/null 2>&1; then + echo "Release tag found: v${{ inputs.release_version }}-${{ inputs.release_candidate }}" + echo "proceed=true" >> $GITHUB_OUTPUT + else + echo "ERROR: Release tag not found: v${{ inputs.release_version }}-${{ inputs.release_candidate }}" + echo "proceed=false" >> $GITHUB_OUTPUT + exit 1 + fi + + - name: Document vote approval + if: ${{ inputs.vote_thread_url != '' }} + run: | + echo "### Release Vote Approval" >> $GITHUB_STEP_SUMMARY + echo "Release v${{ inputs.release_version }} was approved via ASF voting process." >> $GITHUB_STEP_SUMMARY + echo "Vote thread: ${{ inputs.vote_thread_url }}" >> $GITHUB_STEP_SUMMARY + + publish-docker: + name: Publish Docker Images + runs-on: ubuntu-latest + needs: validate-release + if: ${{ needs.validate-release.outputs.proceed == 'true' }} + + permissions: + contents: read + packages: write + id-token: write # For OIDC/code signing if needed + + steps: + - name: Checkout code + uses: actions/checkout@v4 + with: + ref: "v${{ inputs.release_version }}-${{ inputs.release_candidate }}" + + - name: Set up JDK ${{ env.JAVA_VERSION }} + uses: actions/setup-java@v4 + with: + java-version: ${{ env.JAVA_VERSION }} + distribution: ${{ env.JAVA_DISTRIBUTION }} + cache: 'gradle' + + - name: Grant execute permission for gradlew + run: chmod +x gradlew + + - name: Update version in build.gradle.kts + run: | + # Update the version to remove SNAPSHOT + sed -i 's/version = ".*"/version = "${{ inputs.release_version }}"/' build.gradle.kts + + - name: Build project + run: ./gradlew build + + - name: Sign artifacts with ASF infrastructure + if: ${{ inputs.sign_with_asf_infra }} + run: | + # Placeholder for ASF code signing integration + # This would integrate with ASF's code signing service + # Requires coordination with ASF INFRA team + echo "Would sign artifacts with ASF code signing infrastructure" + echo "Contact INFRA for setup requirements" + + - name: Build and publish to Docker Hub (apache/solr-mcp) + run: | + # Publish official release to apache/solr-mcp + # This requires Apache PMC credentials + if [[ -n "${{ secrets.DOCKERHUB_APACHE_USERNAME }}" ]]; then + # Build and push with multiple tags + ./gradlew jib \ + -Djib.to.image=apache/solr-mcp:${{ inputs.release_version }} \ + -Djib.to.auth.username=${{ secrets.DOCKERHUB_APACHE_USERNAME }} \ + -Djib.to.auth.password=${{ secrets.DOCKERHUB_APACHE_TOKEN }} \ + -Djib.to.tags=${{ inputs.release_version }},latest + + # Also tag with major and minor versions + MAJOR_VERSION=$(echo "${{ inputs.release_version }}" | cut -d. -f1) + MINOR_VERSION=$(echo "${{ inputs.release_version }}" | cut -d. -f1-2) + + ./gradlew jib \ + -Djib.to.image=apache/solr-mcp:${MAJOR_VERSION} \ + -Djib.to.auth.username=${{ secrets.DOCKERHUB_APACHE_USERNAME }} \ + -Djib.to.auth.password=${{ secrets.DOCKERHUB_APACHE_TOKEN }} + + ./gradlew jib \ + -Djib.to.image=apache/solr-mcp:${MINOR_VERSION} \ + -Djib.to.auth.username=${{ secrets.DOCKERHUB_APACHE_USERNAME }} \ + -Djib.to.auth.password=${{ secrets.DOCKERHUB_APACHE_TOKEN }} + else + echo "WARNING: Apache Docker Hub credentials not configured" + fi + + - name: Build and publish to GitHub Container Registry + run: | + # Also publish to GitHub Container Registry + ./gradlew jib \ + -Djib.to.image=ghcr.io/${{ github.repository_owner }}/solr-mcp:${{ inputs.release_version }} \ + -Djib.to.auth.username=${{ github.actor }} \ + -Djib.to.auth.password=${{ secrets.GITHUB_TOKEN }} \ + -Djib.to.tags=${{ inputs.release_version }},latest + + - name: Generate SBOM (Software Bill of Materials) + run: | + # Generate SBOM for the release + # This helps with supply chain security + ./gradlew cyclonedxBom || echo "SBOM generation not configured" + + - name: Create release announcement + run: | + cat << EOF > RELEASE_ANNOUNCEMENT.md + # Apache Solr MCP v${{ inputs.release_version }} Released + + The Apache Solr team is pleased to announce the release of Solr MCP v${{ inputs.release_version }}. + + ## Docker Images + + Official Docker images are available: + + \`\`\`bash + # Docker Hub (Official Apache image) + docker pull apache/solr-mcp:${{ inputs.release_version }} + + # GitHub Container Registry + docker pull ghcr.io/${{ github.repository_owner }}/solr-mcp:${{ inputs.release_version }} + \`\`\` + + ## Installation + + ### Using Docker: + \`\`\`bash + docker run -it apache/solr-mcp:${{ inputs.release_version }} + \`\`\` + + ### Using JAR: + Download the JAR from the [release page](https://github.com/${{ github.repository }}/releases/tag/v${{ inputs.release_version }}). + + ## Verification + + All release artifacts are signed. Verify signatures using: + \`\`\`bash + # Download signature and checksum files + wget https://downloads.apache.org/solr/mcp/${{ inputs.release_version }}/solr-mcp-${{ inputs.release_version }}.jar.asc + wget https://downloads.apache.org/solr/mcp/${{ inputs.release_version }}/solr-mcp-${{ inputs.release_version }}.jar.sha512 + + # Verify signature (requires GPG) + gpg --verify solr-mcp-${{ inputs.release_version }}.jar.asc + + # Verify checksum + sha512sum -c solr-mcp-${{ inputs.release_version }}.jar.sha512 + \`\`\` + + ## Release Notes + + See the [full release notes](https://github.com/${{ github.repository }}/releases/tag/v${{ inputs.release_version }}) for details. + + ## Vote Thread + + This release was approved by the Apache Solr PMC. + ${VOTE_THREAD_NOTE} + EOF + + if [[ -n "${{ inputs.vote_thread_url }}" ]]; then + echo "Vote thread: ${{ inputs.vote_thread_url }}" >> RELEASE_ANNOUNCEMENT.md + fi + + - name: Publish release summary + run: | + echo "### Release Published Successfully! πŸŽ‰" >> $GITHUB_STEP_SUMMARY + echo "" >> $GITHUB_STEP_SUMMARY + echo "**Version**: ${{ inputs.release_version }}" >> $GITHUB_STEP_SUMMARY + echo "**Release Candidate**: ${{ inputs.release_candidate }}" >> $GITHUB_STEP_SUMMARY + echo "" >> $GITHUB_STEP_SUMMARY + echo "#### Docker Images Published" >> $GITHUB_STEP_SUMMARY + echo "- \`apache/solr-mcp:${{ inputs.release_version }}\`" >> $GITHUB_STEP_SUMMARY + echo "- \`apache/solr-mcp:latest\`" >> $GITHUB_STEP_SUMMARY + echo "- \`ghcr.io/${{ github.repository_owner }}/solr-mcp:${{ inputs.release_version }}\`" >> $GITHUB_STEP_SUMMARY + echo "" >> $GITHUB_STEP_SUMMARY + echo "#### Next Steps" >> $GITHUB_STEP_SUMMARY + echo "1. Announce the release on the mailing list" >> $GITHUB_STEP_SUMMARY + echo "2. Update the documentation" >> $GITHUB_STEP_SUMMARY + echo "3. Close the release milestone in GitHub" >> $GITHUB_STEP_SUMMARY + echo "4. Tweet about the release (optional)" >> $GITHUB_STEP_SUMMARY + + publish-mcp-registry: + name: Publish to MCP Registry + runs-on: ubuntu-latest + needs: publish-docker + if: ${{ needs.validate-release.outputs.proceed == 'true' }} + + steps: + - name: Register with MCP Registry + run: | + # Register the new release with the MCP registry + # This makes the server discoverable by MCP clients + + echo "Registering apache/solr-mcp:${{ inputs.release_version }} with MCP Registry" + + # The MCP registry would need to be notified about: + # - Docker image: apache/solr-mcp:${{ inputs.release_version }} + # - Capabilities: Search, indexing, query, admin operations + # - Version: ${{ inputs.release_version }} + # - Documentation URL: https://github.com/${{ github.repository }} + + # This is a placeholder - actual implementation depends on MCP registry API + echo "MCP Registry notification would happen here" \ No newline at end of file diff --git a/DOCKER_PUBLISHING.md b/DOCKER_PUBLISHING.md new file mode 100644 index 0000000..ae09638 --- /dev/null +++ b/DOCKER_PUBLISHING.md @@ -0,0 +1,252 @@ +# Docker Publishing Guide for Apache Solr MCP + +This guide documents the Docker image publishing process for Apache Solr MCP, including nightly builds, release candidates, and official releases. + +## Overview + +The Solr MCP project publishes Docker images to multiple registries: + +1. **GitHub Container Registry (GHCR)**: `ghcr.io/apache/solr-mcp` +2. **Docker Hub Official**: `apache/solr-mcp` (requires Apache PMC credentials) +3. **Docker Hub Nightly**: `apache/solr-mcp-nightly` (for pre-release builds) + +## Build System + +The project uses **Jib** (Google's containerization plugin) for building Docker images: +- No Docker daemon required for building +- Multi-platform support (linux/amd64 and linux/arm64) +- Optimized layering for faster deployments +- Reproducible builds + +## Publishing Workflows + +### 1. Development Builds (Per-merge to GHCR) + +Currently, this repository does not define an automated workflow for per-merge dev images. The recommended practice is to publish per-merge or ad-hoc development images to GHCR (not Docker Hub under `apache/`). This keeps the `apache/` namespace reserved for nightlies and voted releases. + +- Suggested images (if/when automated): + - `ghcr.io/{owner}/solr-mcp:VERSION-SNAPSHOT-SHA` + - `ghcr.io/{owner}/solr-mcp:latest` +- No ASF vote required for dev images (they are not releases and must be clearly marked as such). + +### 2. Nightly Builds + +**Workflow**: `.github/workflows/nightly-build.yml` + +- **Schedule**: Daily at 2 AM UTC +- **Images Published**: + - `apache/solr-mcp-nightly:nightly-YYYYMMDD-SHA` + - `apache/solr-mcp-nightly:latest-nightly` +- **Artifacts**: + - Source tarball to `https://nightlies.apache.org/solr/mcp/` + - GitHub pre-release with build artifacts +- **No ASF vote required** + +### 3. Official Releases + +**Workflow**: `.github/workflows/release-publish.yml` + +- **Trigger**: Manual (after ASF vote passes) +- **Prerequisites**: + - 72-hour ASF voting period completed + - Successful PMC vote + - Release artifacts signed by Release Manager +- **Images Published**: + - `apache/solr-mcp:VERSION` + - `apache/solr-mcp:latest` + - `apache/solr-mcp:MAJOR` + - `apache/solr-mcp:MAJOR.MINOR` + - `ghcr.io/apache/solr-mcp:VERSION` + +## ASF Policy Notes + +- The authoritative ASF release is the signed source distribution published to the ASF distribution system (`dist.apache.org` / `downloads.apache.org` mirrors). Docker images and other binaries are considered convenience binaries and must be built from the voted source, but they are not the release of record. +- Releases require a minimum 72-hour vote with at least three +1 binding PMC votes. Only after the vote passes may convenience binaries (e.g., Docker images) be published. +- Release artifacts must be signed by the Release Manager using their PGP key that is present in the project `KEYS` file. Automated signing via ASF Infra may be possible but must be explicitly arranged with INFRA; manual RM signing remains the baseline. +- Nightly and per-merge builds are allowed as non-release artifacts. They must be clearly marked as such and must not be uploaded to the ASF release distribution system. + +## ASF Release Process + +### Step 1: Create Release Candidate + +```bash +# Tag the release candidate +git tag -s v1.0.0-rc1 -m "Release candidate 1 for version 1.0.0" + +# Create source distribution +tar czf solr-mcp-1.0.0-rc1-src.tar.gz --exclude='.git' --exclude='build' . + +# Sign the release +gpg --armor --detach-sign solr-mcp-1.0.0-rc1-src.tar.gz + +# Generate checksums +sha512sum solr-mcp-1.0.0-rc1-src.tar.gz > solr-mcp-1.0.0-rc1-src.tar.gz.sha512 +``` + +### Step 2: Stage for Voting + +1. Upload release candidate to Apache staging area +2. Send vote email to dev@solr.apache.org +3. Wait for 72-hour voting period + +### Step 3: After Successful Vote + +Trigger the release publish workflow: + +```bash +# Via GitHub UI +# Go to Actions β†’ Release Publish β†’ Run workflow + +# Fill in: +# - Release version: 1.0.0 +# - Release candidate: rc1 +# - Vote thread URL: https://lists.apache.org/... +# - Use ASF code signing: true (if available) +``` + +## Building Docker Images Locally + +### Using Gradle with Jib + +```bash +# Build to local Docker daemon +./gradlew jibDockerBuild + +# Build and push to registry +./gradlew jib -Djib.to.image=myregistry/solr-mcp:my-tag \ + -Djib.to.auth.username=USERNAME \ + -Djib.to.auth.password=TOKEN +``` + +### Multi-platform Build + +The Jib configuration in `build.gradle.kts` automatically builds for: +- `linux/amd64` (x86_64) +- `linux/arm64` (Apple Silicon, ARM servers) + +## Registry Authentication + +### GitHub Container Registry + +GHCR uses the built-in `GITHUB_TOKEN` in workflows. For local pushing: + +```bash +echo $GITHUB_TOKEN | docker login ghcr.io -u USERNAME --password-stdin +``` + +### Docker Hub + +For Apache official images, set these secrets in GitHub: +- `DOCKERHUB_APACHE_USERNAME` +- `DOCKERHUB_APACHE_TOKEN` + +Create token at: https://hub.docker.com/settings/security + +### Apache Nightlies + +Requires Apache committer credentials: +- `APACHE_NIGHTLIES_USER` +- `APACHE_NIGHTLIES_KEY` + +## MCP Registry Integration + +The Docker image includes MCP metadata labels: + +```dockerfile +LABEL io.modelcontextprotocol.server.name="io.github.apache/solr-mcp" +``` + +After release, the image should be registered with the MCP registry for discoverability. + +## Security Considerations + +### Code Signing + +For official releases, we aim to use ASF's code signing infrastructure: + +1. Contact ASF INFRA for setup requirements +2. Enable in release workflow with `sign_with_asf_infra: true` +3. Signatures will be automatically applied to artifacts + +### Image Scanning + +All images should be scanned for vulnerabilities: + +```bash +# Using Docker Scout +docker scout cves apache/solr-mcp:latest + +# Using Trivy +trivy image apache/solr-mcp:latest +``` + +### SBOM Generation + +Software Bill of Materials can be generated: + +```bash +# If CycloneDX is configured +./gradlew cyclonedxBom +``` + +## Troubleshooting + +### Jib Build Issues + +If Jib can't find Docker: + +```bash +# Set Docker executable path +export DOCKER_EXECUTABLE=/usr/local/bin/docker +./gradlew jibDockerBuild +``` + +### Authentication Failures + +For registry authentication issues: + +1. Verify credentials are correct +2. Check token permissions (write:packages for GHCR) +3. Ensure tokens haven't expired + +### Multi-platform Build Failures + +If ARM64 builds fail: + +1. Ensure base image supports ARM64 +2. Check that all dependencies are multi-platform compatible +3. Consider using emulation for testing: `docker run --platform linux/arm64` + +## Versioning Strategy + +- **Main branch**: `VERSION-SNAPSHOT-SHA` (e.g., `0.0.1-SNAPSHOT-a1b2c3d`) +- **Nightly**: `nightly-YYYYMMDD-SHA` (e.g., `nightly-20240115-a1b2c3d`) +- **Release**: Semantic versioning `MAJOR.MINOR.PATCH` (e.g., `1.0.0`) + +## Release Checklist + +- [ ] Create release branch +- [ ] Update version in `build.gradle.kts` +- [ ] Update CHANGELOG.md +- [ ] Tag release candidate +- [ ] Create source distribution +- [ ] Sign artifacts with GPG (RM key listed in project `KEYS`) +- [ ] Generate checksums (.sha512) +- [ ] Upload to Apache staging +- [ ] Send vote email (minimum 72 hours; need β‰₯3 +1 PMC binding votes) +- [ ] After vote passes: publish signed source release to dist.apache.org (mirrors) +- [ ] Verify `KEYS` is up to date and signatures/sha512 verify +- [ ] Trigger the Release Publish workflow to push Docker images (convenience binaries) +- [ ] Verify Docker images are published to Docker Hub and GHCR +- [ ] Update MCP registry (optional) +- [ ] Announce release (dev@ / user@ / website) +- [ ] Close GitHub milestone + +## Contact + +For questions about the release process: +- Apache Solr Dev List: dev@solr.apache.org +- ASF INFRA: https://infra.apache.org/ + +For Docker/Jib specific issues: +- Create issue at: https://github.com/apache/solr-mcp/issues \ No newline at end of file From 7ce171508912dc8c3bf3d7c93a0de2dd199f5521 Mon Sep 17 00:00:00 2001 From: adityamparikh Date: Sat, 8 Nov 2025 23:44:02 -0500 Subject: [PATCH 3/6] docs: enhance GitHub workflows with detailed comments for release management, nightly builds, and publishing steps --- .github/workflows/build-and-publish.yml | 16 +++- .github/workflows/nightly-build.yml | 10 +++ .github/workflows/release-publish.yml | 109 ++++++++++++++++++++---- 3 files changed, 115 insertions(+), 20 deletions(-) diff --git a/.github/workflows/build-and-publish.yml b/.github/workflows/build-and-publish.yml index bf4ea56..46ff1e7 100644 --- a/.github/workflows/build-and-publish.yml +++ b/.github/workflows/build-and-publish.yml @@ -50,17 +50,24 @@ name: Build and Publish +# Triggers for this workflow +# - push: runs on commits to main and on version tags (v*) +# - pull_request: runs on PRs targeting main (build/test only; no publishing) +# - workflow_dispatch: allows manual execution from the Actions UI on: push: branches: - - main + - main # Build + publish dev images on main merges tags: - - 'v*' # Trigger on version tags like v1.0.0, v2.1.3, etc. + - 'v*' # CAUTION (ASF): tag pushes will publish images; prefer using release-publish.yml for post-vote releases pull_request: branches: - - main - workflow_dispatch: # Allow manual workflow runs from GitHub UI + - main # Build + test validation for incoming changes + workflow_dispatch: # Manual runs for maintainers +# Global environment used by all jobs in this workflow +# - JAVA_VERSION: JDK version to install for Gradle builds +# - JAVA_DISTRIBUTION: Vendor/distribution of the JDK (Temurin is Eclipse Adoptium) env: JAVA_VERSION: '25' JAVA_DISTRIBUTION: 'temurin' @@ -162,6 +169,7 @@ jobs: name: Publish Docker Images runs-on: ubuntu-latest needs: build # Wait for build job to complete successfully + # Conditional: do not publish images for pull_request events to avoid leaking credentials or pushing unvetted builds if: github.event_name != 'pull_request' # Skip for PRs # Grant permissions for GHCR publishing diff --git a/.github/workflows/nightly-build.yml b/.github/workflows/nightly-build.yml index 72a3374..c05413d 100644 --- a/.github/workflows/nightly-build.yml +++ b/.github/workflows/nightly-build.yml @@ -31,18 +31,25 @@ name: Nightly Build +# Triggers for the workflow +# - schedule: runs automatically via cron at a fixed time (02:00 UTC daily) +# - workflow_dispatch: allow maintainers to run the workflow manually and pass inputs on: schedule: # Run at 2 AM UTC every day - cron: '0 2 * * *' workflow_dispatch: # Allow manual trigger inputs: + # Optional input to skip Docker publishing if you only want to build artifacts skip_docker: description: 'Skip Docker publishing' required: false type: boolean default: false +# Environment variables used by steps below +# - JAVA_VERSION: selects the JDK version used to build and run Gradle +# - JAVA_DISTRIBUTION: selects the vendor (Temurin = Eclipse Adoptium) env: JAVA_VERSION: '25' JAVA_DISTRIBUTION: 'temurin' @@ -52,6 +59,9 @@ jobs: name: Nightly Build and Publish runs-on: ubuntu-latest + # Permissions required by this job: + # - contents:write β†’ needed to create GitHub pre-releases and upload assets + # - packages:write β†’ needed when pushing container images to registries permissions: contents: write packages: write diff --git a/.github/workflows/release-publish.yml b/.github/workflows/release-publish.yml index fcbf6a5..e00de95 100644 --- a/.github/workflows/release-publish.yml +++ b/.github/workflows/release-publish.yml @@ -50,27 +50,37 @@ name: Release Publish +# Trigger this workflow manually from the GitHub UI and capture structured inputs +# - We require the GA version (e.g., 1.0.0) and the RC tag suffix (e.g., rc1) +# - Optional inputs help document the vote thread and enable experimental signing on: workflow_dispatch: inputs: + # Semantic version of the approved release (no -rc suffix) release_version: description: 'Release version (e.g., 1.0.0)' required: true type: string + # Which release candidate was approved (used to check out the exact tag) release_candidate: description: 'Release candidate number (e.g., rc1, rc2)' required: true type: string + # Link to the public ASF vote thread for traceability in the summary vote_thread_url: description: 'URL to the vote thread (for documentation)' required: false type: string + # If true, attempt to use ASF Infra code-signing (placeholder; requires coordination) sign_with_asf_infra: description: 'Use ASF code signing infrastructure' required: false type: boolean default: false +# Global environment settings used across jobs +# - JAVA_VERSION: version of JDK used to build the project +# - JAVA_DISTRIBUTION: OpenJDK distribution to install via actions/setup-java env: JAVA_VERSION: '25' JAVA_DISTRIBUTION: 'temurin' @@ -84,11 +94,14 @@ jobs: proceed: ${{ steps.validation.outputs.proceed }} steps: + # Step: Check out the exact RC tag that was approved (e.g., v1.0.0-rc1) - name: Checkout code uses: actions/checkout@v4 with: ref: "v${{ inputs.release_version }}-${{ inputs.release_candidate }}" + # Step: Validate that the supplied tag exists in the repo + # - Uses `git rev-parse` to resolve the tag; sets an output flag to gate downstream jobs - name: Validate release tag exists id: validation run: | @@ -102,6 +115,7 @@ jobs: exit 1 fi + # Optional: Document the vote approval in the Actions summary for traceability - name: Document vote approval if: ${{ inputs.vote_thread_url != '' }} run: | @@ -138,7 +152,8 @@ jobs: - name: Update version in build.gradle.kts run: | - # Update the version to remove SNAPSHOT + # Ensure the Gradle project version matches the GA version (removes any -SNAPSHOT) + # This keeps image tags and any generated artifacts consistent with the voted release sed -i 's/version = ".*"/version = "${{ inputs.release_version }}"/' build.gradle.kts - name: Build project @@ -274,24 +289,86 @@ jobs: echo "4. Tweet about the release (optional)" >> $GITHUB_STEP_SUMMARY publish-mcp-registry: + # Job: Publish to MCP Registry so MCP clients can discover the server version released above + # ---------------------------------------------------------------------------- + # Purpose: + # - Use the official MCP Publisher CLI to publish this server's metadata to + # the Model Context Protocol Registry. + # - Runs only after Docker images for the voted source release have been pushed. + # + # Why here (and not a separate workflow): + # - Keeps the post-vote release actions in one place, reducing the chance of + # publishing registry entries that don't correspond to an approved release. name: Publish to MCP Registry runs-on: ubuntu-latest - needs: publish-docker + needs: publish-docker # Wait for Docker images to be published successfully if: ${{ needs.validate-release.outputs.proceed == 'true' }} + # Permissions required for OIDC-based auth to the MCP Registry and read access + permissions: + id-token: write # Required for GitHub OIDC login in mcp-publisher + contents: read # Read repo files (e.g., server.json) + steps: - - name: Register with MCP Registry + # Checkout the exact tag that was released so server.json matches the release + - name: Checkout code + uses: actions/checkout@v4 + with: + ref: "v${{ inputs.release_version }}-${{ inputs.release_candidate }}" + + # Determine the semantic version to publish to MCP (no RC suffix) + - name: Prepare version for MCP + id: mcp_version + run: | + # For MCP, we advertise the GA version (e.g., 1.2.3) + echo "version=${{ inputs.release_version }}" >> $GITHUB_OUTPUT + + # Update server.json with the release version to ensure consistency + - name: Update server.json version + run: | + VERSION="${{ steps.mcp_version.outputs.version }}" + # Update the top-level server version (e.g., 1.2.3) + jq --arg v "$VERSION" '.version = $v' server.json > server.json.tmp + # Update package version (uses -SNAPSHOT suffix for image/JAR alignment if applicable) + jq --arg v "$VERSION-SNAPSHOT" '.packages[0].version = $v' server.json.tmp > server.json + rm server.json.tmp + # Show the final server.json for auditing + cat server.json + + # Download the MCP Publisher CLI from its latest GitHub release + - name: Download MCP Publisher + run: | + curl -L https://github.com/modelcontextprotocol/registry/releases/latest/download/mcp-publisher-linux-amd64.tar.gz | tar xz + chmod +x mcp-publisher + ./mcp-publisher --version + + # Authenticate to the MCP Registry using GitHub OIDC (no static secrets) + - name: Authenticate with MCP Registry (GitHub OIDC) + run: | + ./mcp-publisher login github-oidc + + # Publish this server to the MCP Registry + - name: Publish to MCP Registry run: | - # Register the new release with the MCP registry - # This makes the server discoverable by MCP clients - - echo "Registering apache/solr-mcp:${{ inputs.release_version }} with MCP Registry" - - # The MCP registry would need to be notified about: - # - Docker image: apache/solr-mcp:${{ inputs.release_version }} - # - Capabilities: Search, indexing, query, admin operations - # - Version: ${{ inputs.release_version }} - # - Documentation URL: https://github.com/${{ github.repository }} - - # This is a placeholder - actual implementation depends on MCP registry API - echo "MCP Registry notification would happen here" \ No newline at end of file + ./mcp-publisher publish + + # Verify publication by querying the public registry API + - name: Verify publication + run: | + echo "Waiting 10 seconds for registry to update..." + sleep 10 + echo "Querying registry for published server..." + curl "https://registry.modelcontextprotocol.io/v0/servers?search=io.github.apache/solr-mcp" | jq . + + # Summarize MCP publication in the GitHub Actions job summary + - name: Summary + run: | + echo "### MCP Server Published Successfully! :rocket:" >> $GITHUB_STEP_SUMMARY + echo "" >> $GITHUB_STEP_SUMMARY + echo "**Server Name:** io.github.apache/solr-mcp" >> $GITHUB_STEP_SUMMARY + echo "**Version:** ${{ steps.mcp_version.outputs.version }}" >> $GITHUB_STEP_SUMMARY + echo "**Docker Image:** apache/solr-mcp:${{ inputs.release_version }}" >> $GITHUB_STEP_SUMMARY + echo "" >> $GITHUB_STEP_SUMMARY + echo "The server is now discoverable in the MCP Registry!" >> $GITHUB_STEP_SUMMARY + echo "" >> $GITHUB_STEP_SUMMARY + echo "**Registry URL:** https://registry.modelcontextprotocol.io/v0/servers?search=io.github.apache/solr-mcp" >> $GITHUB_STEP_SUMMARY \ No newline at end of file From e8b3a5cecaa06f4af00ce592d0d43bfc7f649490 Mon Sep 17 00:00:00 2001 From: adityamparikh Date: Sat, 8 Nov 2025 23:45:36 -0500 Subject: [PATCH 4/6] docs: remove outdated GitHub Actions workflow for publishing to MCP Registry --- .github/workflows/publish-mcp.yml | 115 ------------------------------ 1 file changed, 115 deletions(-) delete mode 100644 .github/workflows/publish-mcp.yml diff --git a/.github/workflows/publish-mcp.yml b/.github/workflows/publish-mcp.yml deleted file mode 100644 index 40852d7..0000000 --- a/.github/workflows/publish-mcp.yml +++ /dev/null @@ -1,115 +0,0 @@ -# GitHub Actions Workflow: Publish to MCP Registry -# ================================================== -# -# This workflow publishes the Solr MCP Server to the Model Context Protocol Registry. -# -# Workflow Triggers: -# ------------------ -# - Version tags (v*) - Automatically publishes when you push tags like v0.1.0, v1.0.0, etc. -# -# Prerequisites: -# -------------- -# 1. Docker images must be published to GHCR by the build-and-publish workflow -# 2. The server.json file must be properly configured -# 3. The Jib configuration must include the MCP annotation -# -# Authentication: -# --------------- -# Uses GitHub OIDC (no secrets required) for authentication with the MCP Registry. -# This requires: -# - id-token: write permission (already configured below) -# - Repository must be public -# - Namespace must be io.github.OWNER/* -# -# Usage: -# ------ -# 1. Ensure all changes are committed and pushed -# 2. Create and push a version tag: -# git tag v0.1.0 -# git push origin v0.1.0 -# 3. The workflow will automatically publish to the MCP Registry - -name: Publish to MCP Registry - -on: - push: - tags: - - 'v*' # Trigger on version tags like v0.1.0, v1.0.0, etc. - workflow_dispatch: # Allow manual workflow runs from GitHub UI - -permissions: - id-token: write # Required for OIDC authentication with MCP Registry - contents: read # Required to read repository contents - -jobs: - publish: - name: Publish to MCP Registry - runs-on: ubuntu-latest - - steps: - # Checkout the repository code - - name: Checkout code - uses: actions/checkout@v4 - - # Extract version from tag (remove 'v' prefix) - # Example: v1.0.0 -> 1.0.0 - - name: Extract version - id: version - run: | - VERSION=${GITHUB_REF#refs/tags/v} - echo "version=$VERSION" >> $GITHUB_OUTPUT - echo "Publishing version: $VERSION" - - # Update server.json version to match the tag - # This ensures the published version matches the Git tag - - name: Update server.json version - run: | - VERSION="${{ steps.version.outputs.version }}" - # Update main version field - jq --arg v "$VERSION" '.version = $v' server.json > server.json.tmp - # Update package version field - jq --arg v "$VERSION-SNAPSHOT" '.packages[0].version = $v' server.json.tmp > server.json - rm server.json.tmp - cat server.json - - # Download the MCP Publisher CLI - # Fetches the latest release from GitHub - - name: Download MCP Publisher - run: | - curl -L https://github.com/modelcontextprotocol/registry/releases/latest/download/mcp-publisher-linux-amd64.tar.gz | tar xz - chmod +x mcp-publisher - ./mcp-publisher --version - - # Authenticate with MCP Registry using GitHub OIDC - # No secrets required - uses GitHub's built-in OIDC token - - name: Authenticate with MCP Registry - run: | - ./mcp-publisher login github-oidc - - # Publish the server to the MCP Registry - # This makes the server discoverable by MCP clients - - name: Publish to MCP Registry - run: | - ./mcp-publisher publish - - # Verify the server was published successfully - # Query the registry to confirm the server is available - - name: Verify publication - run: | - echo "Waiting 10 seconds for registry to update..." - sleep 10 - echo "Querying registry for published server..." - curl "https://registry.modelcontextprotocol.io/v0/servers?search=io.github.apache/solr-mcp" | jq . - - # Create a summary of the publication - - name: Summary - run: | - echo "### MCP Server Published Successfully! :rocket:" >> $GITHUB_STEP_SUMMARY - echo "" >> $GITHUB_STEP_SUMMARY - echo "**Server Name:** io.github.apache/solr-mcp" >> $GITHUB_STEP_SUMMARY - echo "**Version:** ${{ steps.version.outputs.version }}" >> $GITHUB_STEP_SUMMARY - echo "**Docker Image:** ghcr.io/apache/solr-mcp-server:${{ steps.version.outputs.version }}-SNAPSHOT" >> $GITHUB_STEP_SUMMARY - echo "" >> $GITHUB_STEP_SUMMARY - echo "The server is now discoverable in the MCP Registry!" >> $GITHUB_STEP_SUMMARY - echo "" >> $GITHUB_STEP_SUMMARY - echo "**Registry URL:** https://registry.modelcontextprotocol.io/v0/servers?search=io.github.apache/solr-mcp" >> $GITHUB_STEP_SUMMARY \ No newline at end of file From 0a6d6cdf8f415f3ba571df0f3df37c6cb16d18ea Mon Sep 17 00:00:00 2001 From: adityamparikh Date: Wed, 12 Nov 2025 22:55:50 -0500 Subject: [PATCH 5/6] feat: Create atr-release.yml for Apache Trusted Releases --- .github/workflows/atr-release-test.yml | 439 ++++++++++++ .github/workflows/atr-release.yml | 470 ++++++++++++ .github/workflows/build-and-publish.yml | 44 ++ .github/workflows/nightly-build.yml | 44 ++ .github/workflows/release-publish.yml | 47 ++ dev-docs/ATR_TESTING_GUIDE.md | 569 +++++++++++++++ .../DOCKER_PUBLISHING.md | 0 dev-docs/WORKFLOWS.md | 668 ++++++++++++++++++ 8 files changed, 2281 insertions(+) create mode 100644 .github/workflows/atr-release-test.yml create mode 100644 .github/workflows/atr-release.yml create mode 100644 dev-docs/ATR_TESTING_GUIDE.md rename DOCKER_PUBLISHING.md => dev-docs/DOCKER_PUBLISHING.md (100%) create mode 100644 dev-docs/WORKFLOWS.md diff --git a/.github/workflows/atr-release-test.yml b/.github/workflows/atr-release-test.yml new file mode 100644 index 0000000..045c6b4 --- /dev/null +++ b/.github/workflows/atr-release-test.yml @@ -0,0 +1,439 @@ +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. +# The ASF licenses this file to You under the Apache License, Version 2.0 +# (the "License"); you may not use this file except in compliance with +# the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# ╔═══════════════════════════════════════════════════════════════════════════╗ +# β•‘ ATR TESTING WORKFLOW β•‘ +# β•‘ (Safe Dry-Run Mode Available) β•‘ +# β•šβ•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β• +# +# PURPOSE: Test ATR workflow logic safely without affecting real systems +# +# WHEN TO USE: +# ----------- +# βœ… Testing workflow logic before ATR onboarding +# βœ… Validating artifact creation and checksums +# βœ… Dry-run mode (default) - no actual uploads +# βœ… Can test real ATR uploads after onboarding (dry_run=false) +# ❌ DO NOT use for production releases (use atr-release.yml when ready) +# +# COMPARISON WITH OTHER WORKFLOWS: +# -------------------------------- +# atr-release-test.yml (THIS FILE): +# - Purpose: Test/validate ATR workflow +# - Safety: βœ… Safe (dry-run by default) +# - Uploads: Optional (only if dry_run=false) +# - Use for: Testing and validation +# +# atr-release.yml: +# - Purpose: Production ATR releases +# - Status: ❌ BLOCKED (prerequisites) +# - Use for: Future when ATR is ready +# +# release-publish.yml: +# - Purpose: Official ASF releases +# - Status: βœ… WORKING (use now) +# - Use for: Production releases TODAY +# +# build-and-publish.yml: +# - Purpose: Development CI/CD +# - Use for: Daily development +# +# ──────────────────────────────────────────────────────────────────────────── +# +# Test version of ATR Release Process +# ==================================== +# This workflow tests the ATR release process without actually pushing to ATR. +# Use this to verify the workflow logic before onboarding to ATR. + +name: ATR Release Process (TEST) + +on: + workflow_dispatch: + inputs: + release_version: + description: 'Release version (e.g., 0.0.1-test)' + required: true + type: string + default: '0.0.1-test' + release_candidate: + description: 'RC number (e.g., rc1, rc2)' + required: true + type: string + default: 'rc1' + dry_run: + description: 'Dry run mode (skip actual ATR uploads)' + required: false + type: boolean + default: true + skip_compose: + description: 'Skip compose phase if already completed' + required: false + type: boolean + default: false + skip_vote: + description: 'Skip vote phase if already completed' + required: false + type: boolean + default: false + +# Required permissions for OIDC authentication with ATR platform +permissions: + id-token: write # Required for GitHub OIDC authentication to ATR + contents: read # Read repository contents + packages: write # May be needed for publishing artifacts + +env: + JAVA_VERSION: '25' + JAVA_DISTRIBUTION: 'temurin' + ATR_PROJECT_NAME: 'solr-mcp' # Project identifier in ATR platform + +jobs: + # Job 1: Compose Phase - Build and prepare release artifacts + compose-release: + name: Compose Release Artifacts (TEST) + runs-on: ubuntu-latest + if: ${{ !inputs.skip_compose }} + + outputs: + artifacts_path: ${{ steps.artifacts.outputs.path }} + checksum_files: ${{ steps.artifacts.outputs.checksums }} + + steps: + - name: Checkout code + uses: actions/checkout@v4 + with: + fetch-depth: 0 # Full history for proper tagging + + - name: Create test tag if not exists + run: | + TEST_TAG="v${{ inputs.release_version }}-${{ inputs.release_candidate }}" + if ! git rev-parse "${TEST_TAG}" >/dev/null 2>&1; then + echo "Creating test tag: ${TEST_TAG}" + git config user.email "test@example.com" + git config user.name "Test Runner" + git tag "${TEST_TAG}" -m "Test release tag" + else + echo "Test tag already exists: ${TEST_TAG}" + fi + + - name: Set up JDK ${{ env.JAVA_VERSION }} + uses: actions/setup-java@v4 + with: + java-version: ${{ env.JAVA_VERSION }} + distribution: ${{ env.JAVA_DISTRIBUTION }} + cache: 'gradle' + + - name: Grant execute permission for gradlew + run: chmod +x gradlew + + - name: Build project + run: | + # Clean build to ensure reproducibility + ./gradlew clean build + + # Run tests to ensure quality + ./gradlew test + + - name: Create source distribution + id: artifacts + run: | + # Create distributions directory + mkdir -p build/distributions + + # Create source tarball (excluding build artifacts and IDE files) + TAR_NAME="solr-mcp-${{ inputs.release_version }}-${{ inputs.release_candidate }}-src.tar.gz" + tar czf "build/distributions/${TAR_NAME}" \ + --exclude='.git' \ + --exclude='build' \ + --exclude='.gradle' \ + --exclude='*.iml' \ + --exclude='.idea' \ + --exclude='target' \ + --exclude='*.log' \ + . + + # Generate SHA512 checksum + cd build/distributions + sha512sum "${TAR_NAME}" > "${TAR_NAME}.sha512" + + # Generate SHA256 for additional verification + sha256sum "${TAR_NAME}" > "${TAR_NAME}.sha256" + + # Output artifact information + echo "path=build/distributions" >> $GITHUB_OUTPUT + echo "checksums=${TAR_NAME}.sha512,${TAR_NAME}.sha256" >> $GITHUB_OUTPUT + + # Display artifacts for verification + echo "Generated artifacts:" + ls -la + + - name: Create JAR distribution + run: | + # Build JAR with all dependencies + ./gradlew shadowJar || ./gradlew jar + + # Create test JAR if shadowJar doesn't exist + if [ ! -f build/libs/solr-mcp-*-all.jar ]; then + # Create a simple test JAR if shadowJar task doesn't exist + echo "Creating test JAR..." + cp build/libs/*.jar "build/distributions/solr-mcp-${{ inputs.release_version }}-${{ inputs.release_candidate }}.jar" 2>/dev/null || \ + echo "Test content" > "build/distributions/solr-mcp-${{ inputs.release_version }}-${{ inputs.release_candidate }}.jar" + else + cp build/libs/solr-mcp-*-all.jar \ + "build/distributions/solr-mcp-${{ inputs.release_version }}-${{ inputs.release_candidate }}.jar" + fi + + # Generate checksums for JAR + cd build/distributions + JAR_NAME="solr-mcp-${{ inputs.release_version }}-${{ inputs.release_candidate }}.jar" + sha512sum "${JAR_NAME}" > "${JAR_NAME}.sha512" + sha256sum "${JAR_NAME}" > "${JAR_NAME}.sha256" + + - name: Sign artifacts with GPG (TEST - simulated) + run: | + echo "TEST MODE: GPG signing would happen here" + echo "Would sign:" + ls -la build/distributions/*.tar.gz + ls -la build/distributions/*.jar + # Create fake .asc files for testing + for file in build/distributions/*.tar.gz build/distributions/*.jar; do + echo "TEST SIGNATURE" > "${file}.asc" + done + + - name: Test ATR Upload (Dry Run) + if: ${{ inputs.dry_run }} + run: | + echo "πŸ§ͺ TEST MODE: Simulating ATR upload" + echo "Would upload to ATR with:" + echo " - Project: ${{ env.ATR_PROJECT_NAME }}" + echo " - Version: ${{ inputs.release_version }}-${{ inputs.release_candidate }}" + echo " - Source: build/distributions" + echo "" + echo "Artifacts that would be uploaded:" + ls -lh build/distributions/ + echo "" + echo "Total size: $(du -sh build/distributions | cut -f1)" + + - name: Upload artifacts to ATR (Real) + if: ${{ !inputs.dry_run && secrets.ASF_USERNAME != '' }} + uses: apache/tooling-actions/upload-to-atr@main + with: + asf-uid: ${{ secrets.ASF_USERNAME }} + project: ${{ env.ATR_PROJECT_NAME }} + version: ${{ inputs.release_version }}-${{ inputs.release_candidate }} + src: build/distributions + atr-host: release-test.apache.org + ssh-port: 2222 + + - name: Upload artifacts for review + uses: actions/upload-artifact@v3 + with: + name: test-release-artifacts-${{ inputs.release_version }}-${{ inputs.release_candidate }} + path: build/distributions/ + retention-days: 7 + + - name: Generate test summary + run: | + echo "### πŸ§ͺ TEST Release Compose Phase Completed βœ“" >> $GITHUB_STEP_SUMMARY + echo "" >> $GITHUB_STEP_SUMMARY + echo "**Mode**: ${{ inputs.dry_run && 'DRY RUN' || 'REAL ATR' }}" >> $GITHUB_STEP_SUMMARY + echo "**Version**: ${{ inputs.release_version }}" >> $GITHUB_STEP_SUMMARY + echo "**Release Candidate**: ${{ inputs.release_candidate }}" >> $GITHUB_STEP_SUMMARY + echo "" >> $GITHUB_STEP_SUMMARY + echo "#### Artifacts Generated:" >> $GITHUB_STEP_SUMMARY + echo "- Source tarball with SHA512/SHA256 checksums" >> $GITHUB_STEP_SUMMARY + echo "- JAR distribution with checksums" >> $GITHUB_STEP_SUMMARY + echo "- Simulated GPG signatures (.asc files)" >> $GITHUB_STEP_SUMMARY + echo "" >> $GITHUB_STEP_SUMMARY + if [[ "${{ inputs.dry_run }}" == "true" ]]; then + echo "⚠️ **Dry Run Mode**: No actual upload to ATR" >> $GITHUB_STEP_SUMMARY + else + echo "βœ… **Real Mode**: Artifacts uploaded to ATR" >> $GITHUB_STEP_SUMMARY + echo "ATR Platform: https://release-test.apache.org/projects/solr-mcp/" >> $GITHUB_STEP_SUMMARY + fi + + # Job 2: Test Vote Process + vote-instructions: + name: Vote Instructions (TEST) + runs-on: ubuntu-latest + needs: [ compose-release ] + if: ${{ !inputs.skip_vote && (success() || inputs.skip_compose) }} + + steps: + - name: Generate test vote email + run: | + cat << 'EOF' > test-vote-email.txt + Subject: [TEST VOTE] Release Apache Solr MCP ${{ inputs.release_version }} RC${{ inputs.release_candidate }} + + ⚠️ THIS IS A TEST - NOT A REAL VOTE ⚠️ + + Testing the vote email template for Apache Solr MCP ${{ inputs.release_version }}. + + Release Candidate: ${{ inputs.release_candidate }} + Git Tag: v${{ inputs.release_version }}-${{ inputs.release_candidate }} + Commit: ${{ github.sha }} + + Test artifacts location: + https://release-test.apache.org/projects/solr-mcp/${{ inputs.release_version }}-${{ inputs.release_candidate }}/ + + This is what a real vote email would look like. + + [ ] +1 Release this package + [ ] -1 Do not release + + TEST ONLY - DO NOT SEND TO MAILING LIST + EOF + + cat test-vote-email.txt + + - name: Test voting simulation + run: | + echo "### πŸ§ͺ TEST Voting Process" >> $GITHUB_STEP_SUMMARY + echo "" >> $GITHUB_STEP_SUMMARY + echo "**TEST MODE ACTIVE**" >> $GITHUB_STEP_SUMMARY + echo "" >> $GITHUB_STEP_SUMMARY + echo "In a real release, you would:" >> $GITHUB_STEP_SUMMARY + echo "1. Send vote email to dev@solr.apache.org" >> $GITHUB_STEP_SUMMARY + echo "2. Wait 72 hours minimum" >> $GITHUB_STEP_SUMMARY + echo "3. Count votes (need 3+ binding +1 votes)" >> $GITHUB_STEP_SUMMARY + echo "" >> $GITHUB_STEP_SUMMARY + echo "For testing, you can skip the vote by running again with skip_vote=true" >> $GITHUB_STEP_SUMMARY + + # Job 3: Test Finish Phase + finish-release: + name: Finalize Release (TEST) + runs-on: ubuntu-latest + if: ${{ always() && inputs.skip_vote }} + + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Test ATR Release Resolution (Dry Run) + if: ${{ inputs.dry_run }} + run: | + echo "πŸ§ͺ TEST MODE: Simulating ATR vote resolution and announcement" + echo "" + echo "Would execute release-on-atr with:" + echo " - Version: ${{ inputs.release_version }}" + echo " - Resolution: passed" + echo " - Announce to: announce@apache.org" + echo "" + echo "Simulated announcement email:" + echo "----------------------------------------" + cat << EOF + Subject: [ANNOUNCE] Apache Solr MCP ${{ inputs.release_version }} Released + + The Apache Solr team is pleased to announce the release of Apache Solr MCP ${{ inputs.release_version }}. + + Apache Solr MCP is a Model Context Protocol server for Apache Solr. + + Downloads: https://www.apache.org/dyn/closer.lua/solr/mcp/${{ inputs.release_version }}/ + Docker: docker pull apache/solr-mcp:${{ inputs.release_version }} + + Release notes: https://github.com/apache/solr-mcp/blob/v${{ inputs.release_version }}/CHANGES.txt + + The Apache Solr Team + EOF + echo "----------------------------------------" + + - name: Resolve vote and announce on ATR (Real) + if: ${{ !inputs.dry_run && secrets.ASF_USERNAME != '' }} + uses: apache/tooling-actions/release-on-atr@main + with: + version: ${{ inputs.release_version }} + atr-host: release-test.apache.org + resolve: "true" + resolve-resolution: "passed" + announce: "false" # Don't actually announce in test + + - name: Test summary + run: | + echo "### πŸ§ͺ TEST Release Finalization" >> $GITHUB_STEP_SUMMARY + echo "" >> $GITHUB_STEP_SUMMARY + echo "**Mode**: ${{ inputs.dry_run && 'DRY RUN' || 'REAL ATR' }}" >> $GITHUB_STEP_SUMMARY + echo "**Version**: ${{ inputs.release_version }}" >> $GITHUB_STEP_SUMMARY + echo "" >> $GITHUB_STEP_SUMMARY + if [[ "${{ inputs.dry_run }}" == "true" ]]; then + echo "βœ… Dry run completed successfully" >> $GITHUB_STEP_SUMMARY + echo "" >> $GITHUB_STEP_SUMMARY + echo "To test with real ATR (requires onboarding):" >> $GITHUB_STEP_SUMMARY + echo "1. Add ASF_USERNAME secret" >> $GITHUB_STEP_SUMMARY + echo "2. Run workflow with dry_run=false" >> $GITHUB_STEP_SUMMARY + else + echo "βœ… ATR test completed" >> $GITHUB_STEP_SUMMARY + echo "Note: Announcement was skipped in test mode" >> $GITHUB_STEP_SUMMARY + fi + + # Job 4: Validate ATR Connectivity + validate-atr: + name: Validate ATR Connectivity + runs-on: ubuntu-latest + if: ${{ always() }} + + steps: + - name: Check ATR platform availability + run: | + echo "Testing ATR platform connectivity..." + echo "" + + # Test main platform + echo "1. Testing main platform (https://release-test.apache.org):" + if curl -s -o /dev/null -w " HTTP Status: %{http_code}\n" https://release-test.apache.org; then + echo " βœ… Platform is reachable" + else + echo " ❌ Platform unreachable" + fi + echo "" + + # Test health endpoint + echo "2. Testing health endpoint:" + HEALTH_STATUS=$(curl -s -o /dev/null -w "%{http_code}" https://release-test.apache.org/health 2>/dev/null || echo "000") + if [ "$HEALTH_STATUS" = "200" ]; then + echo " βœ… Health check passed (HTTP 200)" + elif [ "$HEALTH_STATUS" = "000" ]; then + echo " ❌ Could not connect to health endpoint" + else + echo " ⚠️ Health check returned HTTP $HEALTH_STATUS" + fi + echo "" + + # Test SSH connectivity (port 2222) + echo "3. Testing SSH port for uploads (2222):" + timeout 5 bash -c 'cat < /dev/null > /dev/tcp/release-test.apache.org/2222' 2>/dev/null && \ + echo " βœ… SSH port is open" || \ + echo " ❌ SSH port appears closed or filtered" + echo "" + + # Test OIDC endpoint + echo "4. Testing OIDC metadata:" + if curl -s https://token.actions.githubusercontent.com/.well-known/openid-configuration | grep -q "issuer"; then + echo " βœ… GitHub OIDC is available" + else + echo " ❌ Cannot reach GitHub OIDC endpoint" + fi + + - name: Test summary + run: | + echo "### ATR Platform Status" >> $GITHUB_STEP_SUMMARY + echo "" >> $GITHUB_STEP_SUMMARY + echo "| Component | Status | URL |" >> $GITHUB_STEP_SUMMARY + echo "|-----------|--------|-----|" >> $GITHUB_STEP_SUMMARY + echo "| ATR Platform | πŸ” Check logs | https://release-test.apache.org |" >> $GITHUB_STEP_SUMMARY + echo "| Tutorial | πŸ“š | https://release-test.apache.org/tutorial |" >> $GITHUB_STEP_SUMMARY + echo "| GitHub Repo | πŸ“¦ | https://github.com/apache/tooling-trusted-releases |" >> $GITHUB_STEP_SUMMARY + echo "| Actions Repo | πŸ”§ | https://github.com/apache/tooling-actions |" >> $GITHUB_STEP_SUMMARY + echo "" >> $GITHUB_STEP_SUMMARY + echo "**Contact**: dev@tooling.apache.org for onboarding" >> $GITHUB_STEP_SUMMARY \ No newline at end of file diff --git a/.github/workflows/atr-release.yml b/.github/workflows/atr-release.yml new file mode 100644 index 0000000..a35ba29 --- /dev/null +++ b/.github/workflows/atr-release.yml @@ -0,0 +1,470 @@ +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. +# The ASF licenses this file to You under the Apache License, Version 2.0 +# (the "License"); you may not use this file except in compliance with +# the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# ╔═══════════════════════════════════════════════════════════════════════════╗ +# β•‘ APACHE TRUSTED RELEASES (ATR) β•‘ +# β•‘ **FUTURE USE ONLY** β•‘ +# β•‘ (Blocked - Prerequisites Required) β•‘ +# β•šβ•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β• +# +# PURPOSE: Automated ASF-compliant releases via ATR platform (EXPERIMENTAL) +# +# ⚠️ IMPORTANT: NOT CURRENTLY USABLE +# ---------------------------------- +# This workflow is BLOCKED and cannot be used until you complete: +# 1. Implement automated release signing (https://infra.apache.org/release-signing.html) +# 2. Get ASF signing key from INFRA (2-4 week process) +# 3. Request ATR onboarding from dev@tooling.apache.org +# +# STATUS: Workflow is ready but prerequisites are not met +# See: dev-docs/ATR_TESTING_GUIDE.md for complete implementation path +# +# WHEN TO USE: +# ----------- +# ❌ DO NOT use now - prerequisites not met +# βœ… Use AFTER automated signing is implemented and ATR onboarding approved +# βœ… For fully automated ASF releases in the future +# +# CURRENT WORKFLOW TO USE: +# ------------------------ +# Use release-publish.yml for official releases (manual signing) +# +# COMPARISON WITH OTHER WORKFLOWS: +# -------------------------------- +# atr-release.yml (THIS FILE): +# - Purpose: Future ATR automation +# - Status: ❌ BLOCKED (prerequisites required) +# - Trigger: Manual (when ready) +# - Signing: Automated +# - Use for: Future when ATR is ready +# +# release-publish.yml: +# - Purpose: Official ASF releases +# - Status: βœ… WORKING (use this now) +# - Trigger: Manual (after vote) +# - Signing: Manual by Release Manager +# - Use for: Production releases TODAY +# +# build-and-publish.yml: +# - Purpose: Development CI/CD +# - Trigger: Automatic +# - Use for: Daily development +# +# nightly-build.yml: +# - Purpose: Nightly builds +# - Trigger: Scheduled +# - Use for: Testing latest changes +# +# ──────────────────────────────────────────────────────────────────────────── +# +# Apache Trusted Releases (ATR) Integration Workflow +# =================================================== +# +# Purpose: +# -------- +# Integrates with the Apache Trusted Releases platform to automate the ASF-compliant +# release process including artifact upload, vote resolution, and release announcement. +# +# ATR Platform Overview: +# ---------------------- +# The Apache Trusted Releases platform (currently in Alpha) provides: +# - Secure artifact upload using OIDC authentication +# - Vote resolution management +# - Automated release announcements +# - No long-lived credentials required (uses GitHub OIDC) +# +# Available GitHub Actions: +# ------------------------- +# - upload-to-atr: Upload artifacts using ephemeral SSH keys and OIDC +# - release-on-atr: Resolve votes and announce releases +# - record-atr-distribution: Record distribution metadata +# +# Prerequisites: +# -------------- +# - Project must be onboarded to ATR (contact dev@tooling.apache.org) +# - ASF username (asf-uid) for the Release Manager +# - GitHub workflow must have id-token: write permission for OIDC +# +# Resources: +# ---------- +# - ATR Platform: https://release-test.apache.org +# - GitHub Actions: https://github.com/apache/tooling-actions +# - GitHub: https://github.com/apache/tooling-trusted-releases +# - Mailing List: dev@tooling.apache.org +# +# Note: ATR is EXPERIMENTAL and subject to change + +name: ATR Release Process + +on: + workflow_dispatch: + inputs: + release_version: + description: 'Release version (e.g., 1.0.0)' + required: true + type: string + release_candidate: + description: 'RC number (e.g., rc1, rc2)' + required: true + type: string + skip_compose: + description: 'Skip compose phase if already completed' + required: false + type: boolean + default: false + skip_vote: + description: 'Skip vote phase if already completed' + required: false + type: boolean + default: false + +# Required permissions for OIDC authentication with ATR platform +permissions: + id-token: write # Required for GitHub OIDC authentication to ATR + contents: read # Read repository contents + packages: write # May be needed for publishing artifacts + +env: + JAVA_VERSION: '25' + JAVA_DISTRIBUTION: 'temurin' + ATR_PROJECT_NAME: 'solr-mcp' # Project identifier in ATR platform + +jobs: + # Job 1: Compose Phase - Build and prepare release artifacts + compose-release: + name: Compose Release Artifacts + runs-on: ubuntu-latest + if: ${{ !inputs.skip_compose }} + + outputs: + artifacts_path: ${{ steps.artifacts.outputs.path }} + checksum_files: ${{ steps.artifacts.outputs.checksums }} + + steps: + - name: Checkout release candidate tag + uses: actions/checkout@v4 + with: + ref: "v${{ inputs.release_version }}-${{ inputs.release_candidate }}" + fetch-depth: 0 # Full history for proper tagging + + - name: Verify release tag + run: | + if ! git rev-parse "v${{ inputs.release_version }}-${{ inputs.release_candidate }}" >/dev/null 2>&1; then + echo "ERROR: Release tag not found: v${{ inputs.release_version }}-${{ inputs.release_candidate }}" + exit 1 + fi + echo "βœ“ Release tag verified" + + - name: Set up JDK ${{ env.JAVA_VERSION }} + uses: actions/setup-java@v4 + with: + java-version: ${{ env.JAVA_VERSION }} + distribution: ${{ env.JAVA_DISTRIBUTION }} + cache: 'gradle' + + - name: Grant execute permission for gradlew + run: chmod +x gradlew + + - name: Build project + run: | + # Clean build to ensure reproducibility + ./gradlew clean build + + # Run tests to ensure quality + ./gradlew test + + - name: Create source distribution + id: artifacts + run: | + # Create distributions directory + mkdir -p build/distributions + + # Create source tarball (excluding build artifacts and IDE files) + TAR_NAME="solr-mcp-${{ inputs.release_version }}-${{ inputs.release_candidate }}-src.tar.gz" + tar czf "build/distributions/${TAR_NAME}" \ + --exclude='.git' \ + --exclude='build' \ + --exclude='.gradle' \ + --exclude='*.iml' \ + --exclude='.idea' \ + --exclude='target' \ + --exclude='*.log' \ + . + + # Generate SHA512 checksum + cd build/distributions + sha512sum "${TAR_NAME}" > "${TAR_NAME}.sha512" + + # Generate SHA256 for additional verification + sha256sum "${TAR_NAME}" > "${TAR_NAME}.sha256" + + # Output artifact information + echo "path=build/distributions" >> $GITHUB_OUTPUT + echo "checksums=${TAR_NAME}.sha512,${TAR_NAME}.sha256" >> $GITHUB_OUTPUT + + # Display artifacts for verification + echo "Generated artifacts:" + ls -la + + - name: Create JAR distribution + run: | + # Build JAR with all dependencies + ./gradlew shadowJar + + # Copy to distributions with versioned name + cp build/libs/solr-mcp-*-all.jar \ + "build/distributions/solr-mcp-${{ inputs.release_version }}-${{ inputs.release_candidate }}.jar" + + # Generate checksums for JAR + cd build/distributions + JAR_NAME="solr-mcp-${{ inputs.release_version }}-${{ inputs.release_candidate }}.jar" + sha512sum "${JAR_NAME}" > "${JAR_NAME}.sha512" + sha256sum "${JAR_NAME}" > "${JAR_NAME}.sha256" + + - name: Sign artifacts with GPG (optional) + if: ${{ env.GPG_KEY_ID != '' }} + run: | + # Import GPG key if available (for automated signing) + # Note: Manual GPG signing by Release Manager is also acceptable + echo "GPG signing would be performed here if GPG_KEY_ID secret is configured" + # gpg --armor --detach-sign build/distributions/*.tar.gz + # gpg --armor --detach-sign build/distributions/*.jar + + - name: Upload artifacts to ATR + uses: apache/tooling-actions/upload-to-atr@main + with: + asf-uid: ${{ secrets.ASF_USERNAME }} + project: ${{ env.ATR_PROJECT_NAME }} + version: ${{ inputs.release_version }}-${{ inputs.release_candidate }} + src: build/distributions + atr-host: release-test.apache.org + ssh-port: 2222 + + - name: Upload artifacts for review + uses: actions/upload-artifact@v3 + with: + name: release-artifacts-${{ inputs.release_version }}-${{ inputs.release_candidate }} + path: build/distributions/ + retention-days: 30 + + - name: Generate compose summary + run: | + echo "### Release Compose Phase Completed βœ“" >> $GITHUB_STEP_SUMMARY + echo "" >> $GITHUB_STEP_SUMMARY + echo "**Version**: ${{ inputs.release_version }}" >> $GITHUB_STEP_SUMMARY + echo "**Release Candidate**: ${{ inputs.release_candidate }}" >> $GITHUB_STEP_SUMMARY + echo "" >> $GITHUB_STEP_SUMMARY + echo "#### Artifacts Generated:" >> $GITHUB_STEP_SUMMARY + echo "- Source tarball with SHA512/SHA256 checksums" >> $GITHUB_STEP_SUMMARY + echo "- JAR distribution with checksums" >> $GITHUB_STEP_SUMMARY + echo "" >> $GITHUB_STEP_SUMMARY + echo "#### Next Steps:" >> $GITHUB_STEP_SUMMARY + echo "1. Review artifacts in ATR platform" >> $GITHUB_STEP_SUMMARY + echo "2. Proceed with vote phase when ready" >> $GITHUB_STEP_SUMMARY + echo "" >> $GITHUB_STEP_SUMMARY + echo "ATR Platform: https://release-test.apache.org" >> $GITHUB_STEP_SUMMARY + + # Job 2: Manual Vote Instructions + vote-instructions: + name: Vote Instructions + runs-on: ubuntu-latest + needs: [ compose-release ] + if: ${{ !inputs.skip_vote && (success() || inputs.skip_compose) }} + + steps: + - name: Generate vote email template + run: | + cat << 'EOF' > vote-email.txt + Subject: [VOTE] Release Apache Solr MCP ${{ inputs.release_version }} RC${{ inputs.release_candidate }} + + Hi all, + + I'd like to call a vote to release Apache Solr MCP ${{ inputs.release_version }}. + + Release Candidate: ${{ inputs.release_candidate }} + Git Tag: v${{ inputs.release_version }}-${{ inputs.release_candidate }} + Commit: ${{ github.sha }} + + Artifacts are available on ATR: + https://release-test.apache.org/projects/solr-mcp/${{ inputs.release_version }}-${{ inputs.release_candidate }}/ + + Release notes: + [Add release notes here or link to CHANGES.txt] + + Please vote to approve this release: + [ ] +1 Release this package + [ ] -1 Do not release (please provide specific comments) + + This vote will be open for at least 72 hours. + + Thanks, + [Your name] + EOF + + cat vote-email.txt + + - name: Manual voting instructions + run: | + echo "### Manual Voting Process Required πŸ—³οΈ" >> $GITHUB_STEP_SUMMARY + echo "" >> $GITHUB_STEP_SUMMARY + echo "**Version**: ${{ inputs.release_version }}-${{ inputs.release_candidate }}" >> $GITHUB_STEP_SUMMARY + echo "" >> $GITHUB_STEP_SUMMARY + echo "#### Next Steps (Release Manager):" >> $GITHUB_STEP_SUMMARY + echo "1. Review artifacts on ATR: https://release-test.apache.org/projects/solr-mcp/" >> $GITHUB_STEP_SUMMARY + echo "2. Send vote email to dev@solr.apache.org (template generated above)" >> $GITHUB_STEP_SUMMARY + echo "3. Wait for 72-hour minimum voting period" >> $GITHUB_STEP_SUMMARY + echo "4. Ensure at least 3 binding +1 votes from PMC members" >> $GITHUB_STEP_SUMMARY + echo "5. After vote passes, run this workflow again with skip_vote=true" >> $GITHUB_STEP_SUMMARY + echo "" >> $GITHUB_STEP_SUMMARY + echo "#### Vote Requirements:" >> $GITHUB_STEP_SUMMARY + echo "- Minimum 3 binding +1 votes from PMC members" >> $GITHUB_STEP_SUMMARY + echo "- No binding -1 votes" >> $GITHUB_STEP_SUMMARY + echo "- 72-hour minimum voting period" >> $GITHUB_STEP_SUMMARY + echo "" >> $GITHUB_STEP_SUMMARY + echo "**Note**: ATR voting automation is not yet available. Manual process required." >> $GITHUB_STEP_SUMMARY + + - name: Upload vote email template + uses: actions/upload-artifact@v3 + with: + name: vote-email-template + path: vote-email.txt + + # Job 3: Finish Phase - Resolve vote and announce release + finish-release: + name: Finalize and Announce Release + runs-on: ubuntu-latest + if: ${{ always() && inputs.skip_vote }} # Manual trigger after vote passes + + steps: + - name: Checkout code + uses: actions/checkout@v4 + with: + ref: "v${{ inputs.release_version }}-${{ inputs.release_candidate }}" + + - name: Resolve vote and announce on ATR + uses: apache/tooling-actions/release-on-atr@main + with: + version: ${{ inputs.release_version }} + atr-host: release-test.apache.org + resolve: "true" + resolve-resolution: "passed" + announce: "true" + announce-email-to: "announce@apache.org" + announce-subject: "[ANNOUNCE] Apache Solr MCP ${{ inputs.release_version }} Released" + announce-body: | + The Apache Solr team is pleased to announce the release of Apache Solr MCP ${{ inputs.release_version }}. + + Apache Solr MCP is a Model Context Protocol server for Apache Solr. + + Downloads are available from: + https://www.apache.org/dyn/closer.lua/solr/mcp/${{ inputs.release_version }}/ + + Docker images: + docker pull apache/solr-mcp:${{ inputs.release_version }} + + Release notes are available at: + https://github.com/apache/solr-mcp/blob/v${{ inputs.release_version }}/CHANGES.txt + + The Apache Solr Team + announce-path-suffix: "solr/mcp/${{ inputs.release_version }}" + + - name: Create GitHub Release + uses: softprops/action-gh-release@v1 + with: + tag_name: v${{ inputs.release_version }} + name: Apache Solr MCP ${{ inputs.release_version }} + draft: false + prerelease: false + body: | + ## Apache Solr MCP ${{ inputs.release_version }} + + This release was approved through the Apache voting process. + + ### Installation + + **Docker:** + ```bash + docker pull apache/solr-mcp:${{ inputs.release_version }} + ``` + + **JAR:** + Download from [Apache Mirrors](https://www.apache.org/dyn/closer.lua/solr/mcp/${{ inputs.release_version }}/) + + ### Verification + + All release artifacts are signed. Verify using: + ```bash + gpg --verify solr-mcp-${{ inputs.release_version }}.jar.asc + sha512sum -c solr-mcp-${{ inputs.release_version }}.jar.sha512 + ``` + + ### Release Notes + See [CHANGES.txt](https://github.com/apache/solr-mcp/blob/v${{ inputs.release_version }}/CHANGES.txt) + + - name: Trigger Docker publishing workflow + uses: peter-evans/repository-dispatch@v2 + with: + token: ${{ secrets.GITHUB_TOKEN }} + event-type: release-approved + client-payload: | + { + "release_version": "${{ inputs.release_version }}", + "release_candidate": "${{ inputs.release_candidate }}" + } + + - name: Final summary + run: | + echo "### Release Published Successfully! πŸŽ‰" >> $GITHUB_STEP_SUMMARY + echo "" >> $GITHUB_STEP_SUMMARY + echo "**Version**: ${{ inputs.release_version }}" >> $GITHUB_STEP_SUMMARY + echo "**Status**: Published to dist.apache.org" >> $GITHUB_STEP_SUMMARY + echo "" >> $GITHUB_STEP_SUMMARY + echo "#### Distribution:" >> $GITHUB_STEP_SUMMARY + echo "- Apache Mirrors: https://www.apache.org/dyn/closer.lua/solr/mcp/${{ inputs.release_version }}/" >> $GITHUB_STEP_SUMMARY + echo "- Docker Hub: `apache/solr-mcp:${{ inputs.release_version }}`" >> $GITHUB_STEP_SUMMARY + echo "" >> $GITHUB_STEP_SUMMARY + echo "#### Next Steps:" >> $GITHUB_STEP_SUMMARY + echo "1. Send announcement to announce@apache.org" >> $GITHUB_STEP_SUMMARY + echo "2. Update website documentation" >> $GITHUB_STEP_SUMMARY + echo "3. Tweet from @ApacheSolr (optional)" >> $GITHUB_STEP_SUMMARY + echo "4. Close GitHub milestone" >> $GITHUB_STEP_SUMMARY + + # Job 4: Monitoring - Check ATR platform status + check-atr-status: + name: Check ATR Platform Status + runs-on: ubuntu-latest + if: ${{ always() }} + + steps: + - name: Check ATR platform availability + run: | + echo "Checking ATR platform status..." + + # Check if ATR platform is accessible + if curl -s -o /dev/null -w "%{http_code}" https://release-test.apache.org/health | grep -q "200"; then + echo "βœ“ ATR platform is available" + else + echo "⚠ ATR platform may be unavailable. Check https://release-test.apache.org" + fi + + - name: Display ATR resources + run: | + echo "### ATR Resources" >> $GITHUB_STEP_SUMMARY + echo "" >> $GITHUB_STEP_SUMMARY + echo "- **Platform**: https://release-test.apache.org" >> $GITHUB_STEP_SUMMARY + echo "- **Tutorial**: https://release-test.apache.org/tutorial" >> $GITHUB_STEP_SUMMARY + echo "- **API Docs**: https://release-test.apache.org/api/docs" >> $GITHUB_STEP_SUMMARY + echo "- **GitHub**: https://github.com/apache/tooling-trusted-releases" >> $GITHUB_STEP_SUMMARY + echo "- **Support**: dev@tooling.apache.org" >> $GITHUB_STEP_SUMMARY \ No newline at end of file diff --git a/.github/workflows/build-and-publish.yml b/.github/workflows/build-and-publish.yml index 46ff1e7..2e9eaf9 100644 --- a/.github/workflows/build-and-publish.yml +++ b/.github/workflows/build-and-publish.yml @@ -13,6 +13,50 @@ # See the License for the specific language governing permissions and # limitations under the License. +# ╔═══════════════════════════════════════════════════════════════════════════╗ +# β•‘ CONTINUOUS DEPLOYMENT WORKFLOW β•‘ +# β•‘ (Development Builds) β•‘ +# β•šβ•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β• +# +# PURPOSE: Automated development builds and Docker image publishing for CI/CD +# +# WHEN TO USE: +# ----------- +# βœ… Automatic on every merge to main +# βœ… Testing pull requests (build + test only, no publish) +# βœ… Development/testing Docker images +# ❌ DO NOT use for official ASF releases (use release-publish.yml instead) +# +# COMPARISON WITH OTHER WORKFLOWS: +# -------------------------------- +# build-and-publish.yml (THIS FILE): +# - Purpose: Development CI/CD +# - Trigger: Automatic (push/PR) +# - Docker Hub: Personal namespace +# - ASF Vote: Not required +# - Use for: Daily development work +# +# release-publish.yml: +# - Purpose: Official ASF releases +# - Trigger: Manual (after vote) +# - Docker Hub: apache/solr-mcp +# - ASF Vote: Required (72 hours) +# - Use for: Production releases +# +# nightly-build.yml: +# - Purpose: Nightly builds +# - Trigger: Scheduled (2 AM UTC) +# - Docker Hub: apache/solr-mcp-nightly +# - Use for: Latest unstable builds +# +# atr-release.yml: +# - Purpose: Future ATR automation +# - Trigger: Manual (after prerequisites) +# - Status: Blocked (needs automated signing) +# - Use for: When ATR is ready +# +# ──────────────────────────────────────────────────────────────────────────── +# # GitHub Actions Workflow: Build and Publish # =========================================== # diff --git a/.github/workflows/nightly-build.yml b/.github/workflows/nightly-build.yml index c05413d..2edee1f 100644 --- a/.github/workflows/nightly-build.yml +++ b/.github/workflows/nightly-build.yml @@ -13,6 +13,50 @@ # See the License for the specific language governing permissions and # limitations under the License. +# ╔═══════════════════════════════════════════════════════════════════════════╗ +# β•‘ NIGHTLY BUILD WORKFLOW β•‘ +# β•‘ (Latest Unstable Builds) β•‘ +# β•šβ•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β• +# +# PURPOSE: Automated nightly builds for testing latest changes +# +# WHEN TO USE: +# ----------- +# βœ… Automatic daily at 2 AM UTC +# βœ… For testing latest main branch changes +# βœ… Provides unstable/preview builds +# βœ… Publishes to apache/solr-mcp-nightly +# ❌ DO NOT use for production releases +# +# COMPARISON WITH OTHER WORKFLOWS: +# -------------------------------- +# nightly-build.yml (THIS FILE): +# - Purpose: Nightly builds +# - Trigger: Scheduled (2 AM UTC) +# - Docker Hub: apache/solr-mcp-nightly +# - Stability: Unstable/preview +# - Use for: Testing latest changes +# +# build-and-publish.yml: +# - Purpose: Development CI/CD +# - Trigger: Automatic (push/PR) +# - Docker Hub: Personal namespace +# - Use for: Daily development work +# +# release-publish.yml: +# - Purpose: Official ASF releases +# - Trigger: Manual (after vote) +# - Docker Hub: apache/solr-mcp +# - Stability: Stable/production +# - Use for: Production releases +# +# atr-release.yml: +# - Purpose: Future ATR automation +# - Status: Blocked (needs automated signing) +# - Use for: When ATR is ready +# +# ──────────────────────────────────────────────────────────────────────────── +# # Nightly Build Workflow for Apache Solr MCP # =========================================== # diff --git a/.github/workflows/release-publish.yml b/.github/workflows/release-publish.yml index e00de95..397d4a8 100644 --- a/.github/workflows/release-publish.yml +++ b/.github/workflows/release-publish.yml @@ -13,6 +13,53 @@ # See the License for the specific language governing permissions and # limitations under the License. +# ╔═══════════════════════════════════════════════════════════════════════════╗ +# β•‘ OFFICIAL ASF RELEASE WORKFLOW β•‘ +# β•‘ (Production Releases Only) β•‘ +# β•šβ•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β• +# +# PURPOSE: Publish official Apache releases after successful ASF vote +# +# WHEN TO USE: +# ----------- +# βœ… AFTER 72-hour ASF vote passes with 3+ PMC votes +# βœ… For official production releases only +# βœ… Publishes to apache/solr-mcp (official namespace) +# βœ… Updates MCP Registry +# ❌ DO NOT use for development builds (use build-and-publish.yml) +# ❌ DO NOT run before vote completes +# +# COMPARISON WITH OTHER WORKFLOWS: +# -------------------------------- +# release-publish.yml (THIS FILE): +# - Purpose: Official ASF releases +# - Trigger: Manual (after vote) +# - Docker Hub: apache/solr-mcp +# - MCP Registry: βœ… Yes +# - ASF Vote: Required (72 hours) +# - Use for: Production releases +# +# build-and-publish.yml: +# - Purpose: Development CI/CD +# - Trigger: Automatic (push/PR) +# - Docker Hub: Personal namespace +# - ASF Vote: Not required +# - Use for: Daily development work +# +# nightly-build.yml: +# - Purpose: Nightly builds +# - Trigger: Scheduled (2 AM UTC) +# - Docker Hub: apache/solr-mcp-nightly +# - Use for: Latest unstable builds +# +# atr-release.yml: +# - Purpose: Future ATR automation +# - Trigger: Manual (after prerequisites) +# - Status: Blocked (needs automated signing) +# - Use for: When ATR is ready +# +# ──────────────────────────────────────────────────────────────────────────── +# # Official Release Publishing Workflow # ===================================== # diff --git a/dev-docs/ATR_TESTING_GUIDE.md b/dev-docs/ATR_TESTING_GUIDE.md new file mode 100644 index 0000000..95499a2 --- /dev/null +++ b/dev-docs/ATR_TESTING_GUIDE.md @@ -0,0 +1,569 @@ +# ATR Release Workflow Testing Guide + +This guide explains the proper path to implementing Apache Trusted Releases (ATR) automation and how to test the +workflow. + +## ⚠️ Important Prerequisites + +Based on Apache developer feedback: + +> **"Once you have achieved automated release signing, then you could test ATR automation."** + +### Required Order of Implementation + +``` +Step 1: Implement Automated Release Signing + ↓ +Step 2: Onboard to ATR + ↓ +Step 3: Test ATR Automation + ↓ +Step 4: Use in Production +``` + +## Prerequisites Before ATR + +### Requirements for Automated Release Signing (from ASF INFRA) + +Your project must meet these three conditions: + +1. βœ… **Reproducible builds**: All artifacts can be built reproducibly + - **Status for Solr MCP**: βœ… READY (Jib provides this) + - Evidence: `build.gradle.kts:252`, `DOCKER_PUBLISHING.md:19` + +2. ⚠️ **Staging validation**: CI deploys artifacts to a staging environment + - **Status for Solr MCP**: ⚠️ PARTIAL + - Current: GitHub releases, Docker registries + - Needed: Explicit staging step before final publication + +3. ❌ **Trusted hardware verification**: Artifacts reproduced on trusted hardware before publication + - **Status for Solr MCP**: ❌ NOT IMPLEMENTED + - Needed: Manual verification step by PMC member + +### Current Status for Solr MCP + +| Requirement | Status | Action Needed | +|-------------------------------|-----------------|------------------------------| +| Reproducible builds | βœ… READY | None - Jib provides this | +| Staging validation | ⚠️ PARTIAL | Add explicit staging step | +| Trusted hardware verification | ❌ MISSING | Add manual PMC approval gate | +| ASF signing key | ❌ NOT REQUESTED | File INFRA JIRA ticket | +| ATR onboarding | ❌ BLOCKED | Wait for signing to be ready | +| ATR testing | ❌ BLOCKED | Wait for onboarding | + +## Testing Approaches + +### 1. Dry Run Testing (Recommended First Step) + +**Purpose**: Validate workflow logic without touching ATR platform. + +**How to run:** + +1. Go to **Actions** tab in GitHub +2. Select **ATR Release Process (TEST)** workflow +3. Click **Run workflow** +4. Fill in: + - `release_version`: `0.0.1-test` + - `release_candidate`: `rc1` + - `dry_run`: βœ… **true** (default) +5. Click **Run workflow** + +**What it tests:** + +- βœ… Builds the project successfully +- βœ… Creates source tarball with checksums +- βœ… Creates JAR distribution with checksums +- βœ… Simulates GPG signing +- βœ… Shows what would be uploaded to ATR +- βœ… Generates vote email template +- βœ… Validates workflow logic without side effects + +**Expected result**: Green checkmark, no errors, artifacts available for download. + +--- + +### 2. ATR Connectivity Testing + +**Purpose**: Verify you can reach the ATR platform. + +**Included in**: The `validate-atr` job runs automatically in every test workflow execution. + +**What it tests:** + +- βœ… ATR platform is reachable (https://release-test.apache.org) +- βœ… Health endpoint responds +- βœ… SSH port 2222 is accessible +- βœ… GitHub OIDC is available + +**Check results**: Look at the workflow summary for connectivity status. + +--- + +### 3. Pre-Onboarding Local Testing + +**Purpose**: Test artifact creation locally before any GitHub Actions. + +```bash +# 1. Create a test tag +git tag v0.0.1-test-rc1 -m "Test release" + +# 2. Build the project +./gradlew clean build test + +# 3. Create distribution artifacts +mkdir -p build/distributions + +# Create source tarball +tar czf build/distributions/solr-mcp-0.0.1-test-rc1-src.tar.gz \ + --exclude='.git' \ + --exclude='build' \ + --exclude='.gradle' \ + --exclude='*.iml' \ + --exclude='.idea' \ + . + +# Generate checksums +cd build/distributions +sha512sum solr-mcp-0.0.1-test-rc1-src.tar.gz > solr-mcp-0.0.1-test-rc1-src.tar.gz.sha512 +sha256sum solr-mcp-0.0.1-test-rc1-src.tar.gz > solr-mcp-0.0.1-test-rc1-src.tar.gz.sha256 + +# 4. Verify artifacts +ls -lh build/distributions/ +sha512sum -c solr-mcp-0.0.1-test-rc1-src.tar.gz.sha512 +``` + +**Expected result**: All artifacts created successfully, checksums verify. + +--- + +### 4. GitHub Actions Workflow Validation + +**Purpose**: Test GitHub Actions syntax and job dependencies. + +```bash +# Install act (https://github.com/nektos/act) to run workflows locally +brew install act # macOS +# or: curl https://raw.githubusercontent.com/nektos/act/master/install.sh | sudo bash + +# Run workflow locally (requires Docker) +act workflow_dispatch \ + -W .github/workflows/atr-release-test.yml \ + -j compose-release \ + --input release_version=0.0.1-test \ + --input release_candidate=rc1 \ + --input dry_run=true +``` + +**Note**: `act` may not perfectly replicate GitHub's environment, but catches basic errors. + +--- + +### 5. Real ATR Testing (After Onboarding) + +**Prerequisites:** + +- βœ… Project onboarded to ATR (email dev@tooling.apache.org) +- βœ… `ASF_USERNAME` secret configured in GitHub +- βœ… Your ASF account has access to ATR platform + +**How to run:** + +1. **Test artifact upload:** + ``` + Run workflow: ATR Release Process (TEST) + - release_version: 0.0.1-test + - release_candidate: rc1 + - dry_run: false ⚠️ Set to FALSE + - skip_vote: false + ``` + +2. **Verify upload on ATR:** + - Visit: https://release-test.apache.org/projects/solr-mcp/ + - Look for your test artifacts + - Verify checksums match + +3. **Test vote resolution (skip upload):** + ``` + Run workflow: ATR Release Process (TEST) + - release_version: 0.0.1-test + - release_candidate: rc1 + - dry_run: false + - skip_compose: true ⚠️ Skip artifact creation + - skip_vote: true ⚠️ Go straight to finish + ``` + +4. **Check ATR platform:** + - Verify vote was marked as resolved + - Check that no announcement email was sent (we set announce=false) + +--- + +## Debugging Common Issues + +### Issue: `asf-uid` not found + +**Cause**: `ASF_USERNAME` secret not configured or empty. + +**Fix:** + +1. Go to repository **Settings** β†’ **Secrets and variables** β†’ **Actions** +2. Add new secret: `ASF_USERNAME` = your ASF ID +3. Re-run workflow + +--- + +### Issue: SSH connection refused (port 2222) + +**Cause**: Either ATR platform is down, or project not onboarded. + +**Fix:** + +1. Check ATR status: https://release-test.apache.org +2. Verify project onboarding with dev@tooling.apache.org +3. Check `validate-atr` job output for connectivity details + +--- + +### Issue: OIDC token validation failed + +**Cause**: Repository settings don't allow OIDC token creation. + +**Fix:** + +1. Ensure workflow has `id-token: write` permission (already configured) +2. Check if organization settings restrict OIDC +3. Verify GitHub Actions is enabled for the repository + +--- + +### Issue: Action not found (apache/tooling-actions) + +**Cause**: Actions repository not accessible or branch reference incorrect. + +**Fix:** + +1. Verify https://github.com/apache/tooling-actions exists and is public +2. Check if you're using `@main` (ATR docs say not to tag versions) +3. Try pinning to specific commit SHA if needed + +--- + +## Testing Checklist + +Before attempting a real release with ATR: + +- [ ] Dry run test passes locally +- [ ] GitHub Actions dry run completes successfully +- [ ] All artifacts are created correctly +- [ ] Checksums verify +- [ ] ATR connectivity validation passes +- [ ] Vote email template looks correct +- [ ] (After onboarding) Test upload succeeds +- [ ] (After onboarding) Can view artifacts on ATR platform +- [ ] (After onboarding) Vote resolution works +- [ ] Real `release-publish.yml` workflow still works for Docker/MCP + +--- + +## Monitoring Test Results + +### GitHub Actions UI + +1. Go to **Actions** tab +2. Click on workflow run +3. Check each job's status and logs +4. Download artifacts from **Summary** page + +### Job Summaries + +Each job writes a summary visible at the top of the job output: + +- **Compose**: Lists generated artifacts and sizes +- **Vote**: Shows email template +- **Finish**: Displays announcement preview +- **Validate**: Shows connectivity test results + +### Artifacts + +Download test artifacts to verify locally: + +```bash +# After workflow completes +gh run list --workflow=atr-release-test.yml +gh run view +gh run download + +# Verify downloaded artifacts +cd test-release-artifacts-0.0.1-test-rc1/ +sha512sum -c *.sha512 +``` + +--- + +## Comparison: Test vs Real Workflow + +| Feature | Test Workflow | Real Workflow | +|------------------------|------------------------|-----------------------------| +| **File** | `atr-release-test.yml` | `atr-release.yml` | +| **Default Mode** | Dry run | Live | +| **Creates Tags** | Yes (automatically) | No (must exist) | +| **Uploads to ATR** | Optional | Always (if secrets present) | +| **Sends Emails** | Never | Yes (after vote) | +| **Docker Publish** | No | Yes (after vote) | +| **MCP Registry** | No | Yes (after vote) | +| **Artifact Retention** | 7 days | 30 days | +| **Use Case** | Testing & validation | Production releases | + +--- + +## Implementation Steps for Automated Signing + +### Step 1: Add Trusted Hardware Verification + +Update `.github/workflows/release-publish.yml` to add a manual verification gate: + +```yaml +jobs: + # NEW: Add this job before publish-docker + manual-verification: + name: Manual Build Verification Required + runs-on: ubuntu-latest + needs: validate-release + + steps: + - name: Request PMC verification + uses: trstringer/manual-approval@v1 + with: + approvers: apache-pmc-members # Replace with actual PMC GitHub team + minimum-approvals: 1 + issue-title: "Verify reproducible build for ${{ inputs.release_version }}" + issue-body: | + ## PMC Verification Required + + Before proceeding with release ${{ inputs.release_version }}, a PMC member must: + + ### Verification Steps: + 1. Check out tag: `v${{ inputs.release_version }}-${{ inputs.release_candidate }}` + 2. Run build: `./gradlew clean build` + 3. Compare checksums with CI artifacts: + - Download CI artifacts from this workflow run + - Compare local vs CI checksums: `sha512sum -c *.sha512` + 4. If checksums match, approve this issue + + ### Checksums to verify: + - Source tarball SHA512 + - JAR SHA512 + + Approve this issue to continue the release. + + publish-docker: + needs: manual-verification # Add this dependency + # ... rest of job +``` + +### Step 2: Request ASF Signing Key + +File a JIRA ticket with ASF INFRA: + +``` +Project: INFRA +Summary: Request automated signing key for Apache Solr MCP +Description: + +Apache Solr MCP project requests a signing key for automated release signing. + +Project: Apache Solr MCP +Repository: https://github.com/apache/solr-mcp +PMC: Apache Solr PMC + +We meet the requirements: +1. Reproducible builds: Yes (using Jib) +2. Staging validation: Yes (GitHub Actions with artifact uploads) +3. Trusted hardware verification: Yes (manual PMC approval gate) + +Please provision: +- 4096-bit RSA signing key +- Encrypted revocation certificate in private repo +- Add public key to project KEYS file + +Contact: [Your ASF email] +``` + +### Step 3: Integrate Signing Key (After INFRA Provisions) + +INFRA will provide instructions, but typically: + +```yaml +# In release-publish.yml, after build step: +- name: Sign artifacts with ASF infrastructure + env: + ASF_SIGNING_KEY: ${{ secrets.ASF_SIGNING_KEY }} # Provided by INFRA + run: | + # Import signing key (INFRA will provide exact commands) + echo "$ASF_SIGNING_KEY" | gpg --import + + # Sign all artifacts + cd build/distributions + for file in *.tar.gz *.jar; do + gpg --armor --detach-sign "$file" + done + + # Verify signatures + for file in *.asc; do + gpg --verify "$file" + done +``` + +## ATR Onboarding Process + +Once automated signing is working: + +### Subscribe to ATR Mailing Lists + +```bash +# Development discussions +echo "subscribe" | mail dev-subscribe@tooling.apache.org + +# User support +echo "subscribe" | mail users-subscribe@tooling.apache.org +``` + +### Request ATR Onboarding + +Send email to `dev@tooling.apache.org`: + +``` +Subject: Request ATR onboarding for Apache Solr MCP + +Hello ATR team, + +Apache Solr MCP would like to join the ATR Alpha program. + +Project Details: +- Name: Apache Solr MCP +- Repository: https://github.com/apache/solr-mcp +- PMC: Apache Solr +- Release Manager: [Your name/ASF ID] + +Automated Signing Status: +- Reproducible builds: βœ… Implemented (Jib) +- Staging validation: βœ… Implemented (GitHub Actions) +- Trusted hardware verification: βœ… Implemented (manual PMC gate) +- ASF signing key: βœ… Provisioned by INFRA (ticket: INFRA-XXXXX) + +We are ready to test ATR automation. + +Thanks, +[Your name] +``` + +### Configure GitHub Secrets + +After onboarding approval, add: + +``` +Repository Settings β†’ Secrets β†’ Actions: + +ASF_USERNAME=your-asf-id +``` + +## Implementation Timeline + +### Phase 1: Automated Signing Setup (2-4 weeks) + +- Week 1: Add trusted hardware verification gate +- Week 2: File INFRA JIRA ticket for signing key +- Week 3-4: Wait for INFRA to provision key +- Week 4: Integrate signing key, test + +### Phase 2: ATR Onboarding (1-2 weeks) + +- Request ATR onboarding +- Wait for approval +- Configure secrets + +### Phase 3: ATR Testing (1 week) + +- Dry run tests +- Upload tests +- Complete flow test + +### Phase 4: Production (Ongoing) + +- Use for real releases +- Iterate based on experience + +## Why This Order? + +ATR is designed for fully automated releases. Without automated signing: + +- You'd still need manual GPG signing steps +- Can't test the full automation +- Defeats the purpose of ATR + +By implementing signing first: + +- βœ… Complete automation is possible +- βœ… ATR can validate signatures automatically +- βœ… Reduces manual Release Manager burden +- βœ… Meets ASF compliance requirements + +## Testing Without ATR (Current Approach) + +Until automated signing + ATR are ready, continue using: + +``` +.github/workflows/release-publish.yml +``` + +This workflow: + +- βœ… Works today +- βœ… Publishes Docker images +- βœ… Updates MCP Registry +- ⚠️ Requires manual signing by Release Manager +- ⚠️ Requires manual vote management + +## Next Steps + +### Immediate (This Week) + +1. **Test workflow logic** with dry runs (`atr-release-test.yml`) +2. **Validate locally**: Ensure your build produces correct artifacts +3. **Review prerequisites**: Understand what's needed for automated signing + +### Short Term (1-2 Months) + +1. **Implement trusted hardware verification** gate +2. **File INFRA JIRA ticket** for signing key +3. **Continue using manual process** for real releases + +### Long Term (3-6 Months) + +1. **Integrate automated signing** after INFRA provisions key +2. **Request ATR onboarding** after signing is working +3. **Test with real ATR** after onboarding approval +4. **Use in production** for future releases + +--- + +## Resources + +- **ATR Platform**: https://release-test.apache.org +- **ATR Tutorial**: https://release-test.apache.org/tutorial +- **ATR API Docs**: https://release-test.apache.org/api/docs +- **GitHub Actions**: https://github.com/apache/tooling-actions +- **ATR Source**: https://github.com/apache/tooling-trusted-releases +- **Support**: dev@tooling.apache.org + +--- + +## Questions? + +If you encounter issues not covered here: + +1. Check workflow logs in GitHub Actions +2. Review ATR platform documentation +3. Search GitHub issues: https://github.com/apache/tooling-trusted-releases/issues +4. Ask on mailing list: dev@tooling.apache.org +5. Update this guide with solutions you discover! \ No newline at end of file diff --git a/DOCKER_PUBLISHING.md b/dev-docs/DOCKER_PUBLISHING.md similarity index 100% rename from DOCKER_PUBLISHING.md rename to dev-docs/DOCKER_PUBLISHING.md diff --git a/dev-docs/WORKFLOWS.md b/dev-docs/WORKFLOWS.md new file mode 100644 index 0000000..956a613 --- /dev/null +++ b/dev-docs/WORKFLOWS.md @@ -0,0 +1,668 @@ +# GitHub Actions Workflows Guide + +This guide explains when and how to use each GitHub Actions workflow in the project. + +## Quick Reference + +| Workflow | Purpose | Trigger | Status | Use For | +|------------------------------------------------|-----------------------|----------------------|------------|------------------------| +| [build-and-publish.yml](#build-and-publishyml) | Development CI/CD | Automatic (push/PR) | βœ… Active | Daily development | +| [release-publish.yml](#release-publishyml) | Official ASF releases | Manual (after vote) | βœ… Active | Production releases | +| [nightly-build.yml](#nightly-buildyml) | Nightly builds | Scheduled (2 AM UTC) | βœ… Active | Latest unstable builds | +| [atr-release-test.yml](#atr-release-testyml) | ATR testing | Manual (safe mode) | βœ… Ready | Testing ATR workflow | +| [atr-release.yml](#atr-releaseyml) | ATR production | Manual (blocked) | ⚠️ Blocked | Future ATR releases | + +## Decision Tree: Which Workflow Should I Use? + +``` +β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” +β”‚ START: What do you need to do? β”‚ +β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ + β”‚ + β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” + β”‚ β”‚ β”‚ + β–Ό β–Ό β–Ό +β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” +β”‚ Develop β”‚ β”‚ Release β”‚ β”‚ Test β”‚ +β”‚ Code β”‚ β”‚ Official β”‚ β”‚ ATR β”‚ +β””β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”˜ + β”‚ β”‚ β”‚ + β”‚ β”‚ β”‚ + β–Ό β–Ό β–Ό +β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” +β”‚build-and- β”‚ β”‚ release- β”‚ β”‚atr- β”‚ +β”‚publish.yml β”‚ β”‚ publish β”‚ β”‚release- β”‚ +β”‚ β”‚ β”‚ .yml β”‚ β”‚test.yml β”‚ +β”‚βœ… Automatic β”‚ β”‚ β”‚ β”‚ β”‚ +β”‚ on push β”‚ β”‚βœ… Manual β”‚ β”‚βœ… Manual β”‚ +β”‚ β”‚ β”‚after vote β”‚ β”‚safe mode β”‚ +β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ + β”‚ + β”‚ After ATR + β”‚ onboarding? + β”‚ + β–Ό + β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” + β”‚atr- β”‚ + β”‚release β”‚ + β”‚ .yml β”‚ + β”‚ β”‚ + β”‚βš οΈ Future β”‚ + β”‚ (blocked)β”‚ + β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ +``` + +--- + +## Detailed Workflow Documentation + +### build-and-publish.yml + +**Purpose**: Continuous integration and deployment for development + +#### When to Use + +- βœ… Automatic on every commit to `main` +- βœ… Automatic on pull requests (build + test only) +- βœ… When you merge a PR and want development images published + +#### When NOT to Use + +- ❌ For official Apache releases (use `release-publish.yml`) +- ❌ For production deployments + +#### Triggers + +```yaml +on: + push: + branches: [main] + tags: ['v*'] # ⚠️ Avoid using tags; prefer release-publish.yml + pull_request: + branches: [main] + workflow_dispatch: # Manual trigger +``` + +#### What It Does + +1. **Builds** the project with Gradle +2. **Runs tests** and generates coverage reports +3. **Publishes Docker images** to: + - GitHub Container Registry: `ghcr.io/OWNER/solr-mcp:VERSION-SHA` + - Docker Hub: `DOCKERHUB_USERNAME/solr-mcp:VERSION-SHA` (if secrets configured) + +#### Image Tagging Strategy + +- **Main branch**: `VERSION-SNAPSHOT-SHA` + `latest` + - Example: `0.0.1-SNAPSHOT-a1b2c3d`, `latest` +- **Tags** (discouraged): `VERSION` + `latest` + - Example: `1.0.0`, `latest` + +#### Required Secrets + +- `DOCKERHUB_USERNAME` (optional) - Your Docker Hub username +- `DOCKERHUB_TOKEN` (optional) - Docker Hub access token +- `GITHUB_TOKEN` (automatic) - For GHCR publishing + +#### How to Use + +**Automatic (Recommended)**: + +```bash +# Just merge your PR - workflow runs automatically +git checkout main +git merge feature-branch +git push origin main +``` + +**Manual Trigger**: + +```bash +# Via GitHub UI: Actions β†’ Build and Publish β†’ Run workflow +# Or via CLI: +gh workflow run build-and-publish.yml +``` + +#### Example Use Cases + +- Merging a PR with new features +- Testing changes in a development environment +- Creating preview builds for testing + +--- + +### release-publish.yml + +**Purpose**: Official Apache Software Foundation release publishing + +#### When to Use + +- βœ… ONLY after ASF vote passes (72+ hours, 3+ PMC votes) +- βœ… For official production releases +- βœ… When publishing to `apache/solr-mcp` namespace + +#### When NOT to Use + +- ❌ Before ASF vote completes +- ❌ For development builds (use `build-and-publish.yml`) +- ❌ For testing (use `atr-release-test.yml`) + +#### Triggers + +```yaml +on: + workflow_dispatch: # ONLY manual trigger + inputs: + release_version: # e.g., 1.0.0 + release_candidate: # e.g., rc1 + vote_thread_url: # (optional) + sign_with_asf_infra: # (future) +``` + +#### What It Does + +1. **Validates** release tag exists (`v1.0.0-rc1`) +2. **Builds** the project from approved RC tag +3. **Signs** artifacts (placeholder for future automation) +4. **Publishes Docker images** to: + - Docker Hub: `apache/solr-mcp:1.0.0`, `apache/solr-mcp:1.0`, `apache/solr-mcp:1`, `apache/solr-mcp:latest` + - GitHub Container Registry: `ghcr.io/apache/solr-mcp:1.0.0`, `latest` +5. **Publishes to MCP Registry** for discoverability +6. **Creates GitHub Release** with artifacts + +#### Image Tagging Strategy + +- **Full version**: `1.0.0` +- **Minor version**: `1.0` +- **Major version**: `1` +- **Latest**: `latest` + +#### Required Secrets + +- `DOCKERHUB_APACHE_USERNAME` - Apache PMC Docker Hub credentials +- `DOCKERHUB_APACHE_TOKEN` - Apache PMC Docker Hub token +- `GITHUB_TOKEN` (automatic) - For GHCR and GitHub releases + +#### How to Use + +**Step-by-Step Process**: + +1. **Create Release Candidate**: + ```bash + git tag v1.0.0-rc1 -m "Release candidate 1 for version 1.0.0" + git push origin v1.0.0-rc1 + ``` + +2. **Call ASF Vote** (email to dev@solr.apache.org): + ``` + Subject: [VOTE] Release Apache Solr MCP 1.0.0 RC1 + + [Include vote email content per ASF guidelines] + ``` + +3. **Wait for Vote** (minimum 72 hours, need 3+ binding +1 votes) + +4. **After Vote Passes**, trigger workflow: + ```bash + # Via GitHub UI: Actions β†’ Release Publish β†’ Run workflow + # Fill in: + # release_version: 1.0.0 + # release_candidate: rc1 + # vote_thread_url: https://lists.apache.org/... + + # Or via CLI: + gh workflow run release-publish.yml \ + -f release_version=1.0.0 \ + -f release_candidate=rc1 \ + -f vote_thread_url=https://lists.apache.org/thread/... + ``` + +5. **Verify Publication**: + ```bash + # Check Docker Hub + docker pull apache/solr-mcp:1.0.0 + + # Check MCP Registry + curl "https://registry.modelcontextprotocol.io/v0/servers?search=io.github.apache/solr-mcp" | jq . + ``` + +6. **Announce Release** (email to announce@apache.org) + +#### Example Use Cases + +- Publishing version 1.0.0 after successful vote +- Creating official production releases +- Updating MCP Registry with new release + +--- + +### nightly-build.yml + +**Purpose**: Automated nightly builds for testing latest changes + +#### When to Use + +- βœ… Automatic daily at 2 AM UTC +- βœ… For testing bleeding-edge changes +- βœ… When you want the absolute latest build + +#### When NOT to Use + +- ❌ For production use (unstable) +- ❌ For official releases + +#### Triggers + +```yaml +on: + schedule: + - cron: '0 2 * * *' # 2 AM UTC daily + workflow_dispatch: + inputs: + skip_docker: # Skip Docker publishing +``` + +#### What It Does + +1. **Builds** the project from `main` branch +2. **Creates source distribution** with date stamp +3. **Publishes Docker image** to: + - Docker Hub: `apache/solr-mcp-nightly:nightly-YYYYMMDD-SHA` + - Tag: `latest-nightly` +4. **Uploads to Apache Nightlies** (if configured) +5. **Creates GitHub pre-release** with artifacts +6. **Cleans up** old nightly builds (keeps last 7) + +#### Image Tagging Strategy + +- **Nightly tag**: `nightly-20250112-a1b2c3d` +- **Latest nightly**: `latest-nightly` + +#### Required Secrets + +- `DOCKERHUB_APACHE_USERNAME` - Apache PMC Docker Hub credentials +- `DOCKERHUB_APACHE_TOKEN` - Apache PMC Docker Hub token +- `APACHE_NIGHTLIES_USER` (optional) - For nightlies.apache.org uploads +- `APACHE_NIGHTLIES_KEY` (optional) - SSH key for nightlies + +#### How to Use + +**Automatic (Default)**: + +```bash +# Runs automatically every night at 2 AM UTC +# No action needed +``` + +**Manual Trigger**: + +```bash +# Via GitHub UI: Actions β†’ Nightly Build β†’ Run workflow +# Or via CLI: +gh workflow run nightly-build.yml + +# Skip Docker publishing: +gh workflow run nightly-build.yml -f skip_docker=true +``` + +**Using Nightly Images**: + +```bash +# Pull today's nightly +docker pull apache/solr-mcp-nightly:latest-nightly + +# Pull specific date +docker pull apache/solr-mcp-nightly:nightly-20250112-a1b2c3d +``` + +#### Example Use Cases + +- Testing unreleased features +- Catching bugs early in development +- Integration testing with latest changes +- Providing preview builds to early adopters + +--- + +### atr-release-test.yml + +**Purpose**: Test Apache Trusted Releases (ATR) workflow safely + +#### When to Use + +- βœ… Testing ATR workflow logic before onboarding +- βœ… Validating artifact creation and checksums +- βœ… Learning how ATR works +- βœ… Testing ATR uploads after onboarding (with `dry_run=false`) + +#### When NOT to Use + +- ❌ For production releases (use `atr-release.yml` when ready) +- ❌ When you need guaranteed uploads + +#### Triggers + +```yaml +on: + workflow_dispatch: + inputs: + release_version: # Default: 0.0.1-test + release_candidate: # Default: rc1 + dry_run: # Default: true (SAFE MODE) + skip_compose: # Skip if already done + skip_vote: # Skip vote phase +``` + +#### What It Does + +1. **Builds** test artifacts (creates test tag if needed) +2. **Creates distributions** with checksums +3. **Simulates GPG signing** (test mode) +4. **Dry Run Mode** (default): + - Shows what would be uploaded to ATR + - No actual uploads + - Completely safe +5. **Real Mode** (`dry_run=false`): + - Actually uploads to ATR + - Requires ASF_USERNAME secret + - Requires ATR onboarding +6. **Generates vote email template** +7. **Tests connectivity** to ATR platform + +#### Required Secrets (for Real Mode) + +- `ASF_USERNAME` - Your ASF ID (only needed if `dry_run=false`) + +#### How to Use + +**Safe Testing (Recommended First)**: + +```bash +# Via GitHub UI: Actions β†’ ATR Release Process (TEST) β†’ Run workflow +# Leave all defaults (dry_run=true) + +# Or via CLI: +gh workflow run atr-release-test.yml \ + -f release_version=0.0.1-test \ + -f release_candidate=rc1 \ + -f dry_run=true +``` + +**Real ATR Upload (After Onboarding)**: + +```bash +# ONLY after ATR onboarding approved +gh workflow run atr-release-test.yml \ + -f release_version=0.0.1-test \ + -f release_candidate=rc1 \ + -f dry_run=false # ⚠️ Will actually upload to ATR +``` + +**Testing Complete Flow**: + +```bash +# 1. Test compose phase +gh workflow run atr-release-test.yml \ + -f dry_run=false \ + -f skip_vote=false + +# 2. (Manually send test vote email) + +# 3. Test finish phase +gh workflow run atr-release-test.yml \ + -f skip_compose=true \ + -f skip_vote=true \ + -f dry_run=false +``` + +#### Example Use Cases + +- Learning ATR workflow before onboarding +- Validating artifact generation +- Testing ATR connectivity +- Practicing release process + +--- + +### atr-release.yml + +**Purpose**: Apache Trusted Releases (ATR) automated release process + +#### Current Status + +⚠️ **BLOCKED** - Cannot be used until prerequisites are met + +#### Prerequisites Required + +Before this workflow can be used, you must complete: + +1. **Implement Automated Release Signing** + - Add trusted hardware verification gate + - Request ASF signing key from INFRA (2-4 week process) + - Integrate automated signing in workflows + - See: https://infra.apache.org/release-signing.html + +2. **Request ATR Onboarding** + - Email dev@tooling.apache.org + - Provide evidence of automated signing + - Wait for approval (1-2 weeks) + +3. **Configure Secrets** + - Add `ASF_USERNAME` secret with your ASF ID + +For complete implementation guide, see: [dev-docs/ATR_TESTING_GUIDE.md](ATR_TESTING_GUIDE.md) + +#### When to Use (Future) + +- βœ… After automated signing is implemented +- βœ… After ATR onboarding is approved +- βœ… For fully automated ASF releases + +#### What It Will Do (When Ready) + +1. **Compose**: Build and upload artifacts to ATR +2. **Vote**: Generate vote email template (manual voting) +3. **Finish**: Resolve vote and announce release +4. **Publish**: Trigger Docker and MCP Registry publishing + +#### Current Workaround + +Until ATR is ready, use `release-publish.yml` for official releases. + +#### How to Use (When Ready) + +**After Prerequisites Met**: + +```bash +# 1. Compose and upload to ATR +gh workflow run atr-release.yml \ + -f release_version=1.0.0 \ + -f release_candidate=rc1 + +# 2. Send vote email (manual) + +# 3. After vote passes, finalize +gh workflow run atr-release.yml \ + -f release_version=1.0.0 \ + -f release_candidate=rc1 \ + -f skip_compose=true \ + -f skip_vote=true +``` + +--- + +## Workflow Comparison Matrix + +| Feature | build-and-publish | release-publish | nightly-build | atr-release-test | atr-release | +|----------------------|-------------------|-----------------|--------------------|------------------|-------------| +| **Status** | βœ… Active | βœ… Active | βœ… Active | βœ… Ready | ⚠️ Blocked | +| **Trigger** | Automatic | Manual | Scheduled | Manual | Manual | +| **Docker Namespace** | Personal/GHCR | `apache/*` | `apache/*-nightly` | Test | `apache/*` | +| **MCP Registry** | ❌ No | βœ… Yes | ❌ No | ❌ No | βœ… Yes | +| **ASF Vote** | ❌ Not required | βœ… Required | ❌ Not required | ❌ Not required | βœ… Required | +| **Signing** | ❌ No | ⚠️ Manual | ❌ No | ⚠️ Simulated | βœ… Automated | +| **Production Ready** | ❌ No | βœ… Yes | ❌ No | ❌ No | ⚠️ Future | +| **Can Test Now** | βœ… Yes | βœ… Yes | βœ… Yes | βœ… Yes | ❌ No | + +--- + +## Common Scenarios + +### Scenario 1: I merged a PR and want to test the changes + +**Use**: `build-and-publish.yml` (automatic) + +```bash +# Workflow runs automatically on merge to main +# Find your images at: +# - ghcr.io/apache/solr-mcp:0.0.1-SNAPSHOT-a1b2c3d +``` + +### Scenario 2: I want to create an official release + +**Use**: `release-publish.yml` (manual after vote) + +```bash +# 1. Create RC tag +git tag v1.0.0-rc1 -m "Release candidate 1" +git push origin v1.0.0-rc1 + +# 2. Call ASF vote (email to dev@solr.apache.org) +# 3. Wait 72+ hours for vote to pass +# 4. Trigger workflow +gh workflow run release-publish.yml \ + -f release_version=1.0.0 \ + -f release_candidate=rc1 +``` + +### Scenario 3: I want to test the latest unreleased code + +**Use**: `nightly-build.yml` (automatic daily) + +```bash +# Pull the latest nightly +docker pull apache/solr-mcp-nightly:latest-nightly +``` + +### Scenario 4: I want to prepare for ATR + +**Use**: `atr-release-test.yml` (manual testing) + +```bash +# Test the workflow safely +gh workflow run atr-release-test.yml \ + -f dry_run=true # Safe mode - no uploads +``` + +### Scenario 5: I'm ready to use ATR for releases + +**Use**: `atr-release.yml` (blocked - see prerequisites) + +``` +❌ Cannot use yet +βœ… Complete prerequisites first: + 1. Implement automated signing + 2. Request ATR onboarding + 3. See: dev-docs/ATR_TESTING_GUIDE.md +``` + +--- + +## Troubleshooting + +### "Docker Hub credentials not configured" + +**Solution**: Add secrets to repository: + +```bash +gh secret set DOCKERHUB_USERNAME --body "your-username" +gh secret set DOCKERHUB_TOKEN --body "your-access-token" +``` + +### "Release tag not found" + +**Solution**: Ensure you've created and pushed the tag: + +```bash +git tag v1.0.0-rc1 -m "Release candidate 1" +git push origin v1.0.0-rc1 +``` + +### "ASF_USERNAME not configured" + +**Solution**: Add ASF username secret (required for ATR): + +```bash +gh secret set ASF_USERNAME --body "your-asf-id" +``` + +### "ATR platform unreachable" + +**Solution**: Check ATR status: + +- Platform: https://release-test.apache.org +- Health: https://release-test.apache.org/health +- Contact: dev@tooling.apache.org + +### "Vote hasn't passed yet" + +**Solution**: Wait for ASF vote to complete: + +- Minimum 72 hours +- Need 3+ binding +1 votes from PMC +- No binding -1 votes + +--- + +## Related Documentation + +- [ATR Testing Guide](ATR_TESTING_GUIDE.md) - Complete ATR implementation path +- [Docker Publishing](DOCKER_PUBLISHING.md) - Docker image publishing details +- [Development Guide](DEVELOPMENT.md) - Development workflow +- [Deployment Guide](DEPLOYMENT.md) - Deployment procedures + +--- + +## Getting Help + +- **Workflow Issues**: Check GitHub Actions logs +- **Docker Issues**: See [DOCKER_PUBLISHING.md](DOCKER_PUBLISHING.md) +- **ATR Questions**: Email dev@tooling.apache.org +- **ASF Process**: Email dev@solr.apache.org +- **General Help**: File a GitHub issue + +--- + +## Quick Command Reference + +```bash +# Trigger workflows manually +gh workflow run build-and-publish.yml +gh workflow run release-publish.yml -f release_version=1.0.0 -f release_candidate=rc1 +gh workflow run nightly-build.yml +gh workflow run atr-release-test.yml -f dry_run=true + +# View workflow runs +gh run list +gh run view +gh run watch + +# Download workflow artifacts +gh run download + +# Manage secrets +gh secret list +gh secret set SECRET_NAME --body "value" +gh secret delete SECRET_NAME + +# Tag management for releases +git tag v1.0.0-rc1 -m "Release candidate 1" +git push origin v1.0.0-rc1 +git tag -d v1.0.0-rc1 # Delete local +git push origin :refs/tags/v1.0.0-rc1 # Delete remote +``` + +--- + +**Last Updated**: 2025-01-12 +**Workflows Version**: Compatible with all workflows as of this date \ No newline at end of file From ae1bfe744f0528603dd0e912163f82a9dc5f1134 Mon Sep 17 00:00:00 2001 From: adityamparikh Date: Wed, 26 Nov 2025 20:38:33 -0500 Subject: [PATCH 6/6] docs: update README with instructions for running MCP server in HTTP mode --- README.md | 47 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 47 insertions(+) diff --git a/README.md b/README.md index 5ce5e41..691355a 100644 --- a/README.md +++ b/README.md @@ -22,6 +22,10 @@ A Spring AI Model Context Protocol (MCP) server that provides tools for interact ``` - Run the server: - **STDIO mode (default)**: + - Gradle: + ```bash + ./gradlew bootRun + ``` - JAR: ```bash ./gradlew build @@ -32,6 +36,10 @@ A Spring AI Model Context Protocol (MCP) server that provides tools for interact docker run -i --rm ghcr.io/apache/solr-mcp:latest ``` - **HTTP mode**: + - Gradle: + ```bash + PROFILES=http ./gradlew bootRun + ``` - JAR: ```bash PROFILES=http java -jar build/libs/solr-mcp-0.0.1-SNAPSHOT.jar @@ -128,6 +136,45 @@ Using JAR: } ``` +**Connecting to a running HTTP server** + +If you already have the MCP server running in HTTP mode (via Gradle, JAR, or Docker), you can connect Claude Desktop to +it using `mcp-remote`: + +Running via Gradle: + +```bash +PROFILES=http ./gradlew bootRun +``` + +Running locally (JAR): + +```bash +PROFILES=http java -jar build/libs/solr-mcp-0.0.1-SNAPSHOT.jar +``` + +Running via Docker: + +```bash +docker run -p 8080:8080 --rm -e PROFILES=http ghcr.io/apache/solr-mcp:latest +``` + +Then add to your `claude_desktop_config.json`: + +```json +{ + "mcpServers": { + "solr-mcp-http": { + "command": "npx", + "args": [ + "mcp-remote", + "http://localhost:8080/mcp" + ] + } + } +} +``` + More configuration options: docs/DEPLOYMENT.md#docker-images-with-jib ## Available MCP tools