feat(config): switch Solr wire format from JavaBin to JSON (#55) #169
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| # Licensed to the Apache Software Foundation (ASF) under one or more | ||
|
Check failure on line 1 in .github/workflows/build-and-publish.yml
|
||
| # 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. | ||
| # ╔═══════════════════════════════════════════════════════════════════════════╗ | ||
| # ║ 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 | ||
| # =========================================== | ||
| # | ||
| # This workflow builds the Solr MCP Server project and publishes Docker images | ||
| # to both GitHub Container Registry (GHCR) and Docker Hub. | ||
| # | ||
| # Workflow Triggers: | ||
| # ------------------ | ||
| # 1. Push to 'main' branch - Builds, tests, and publishes Docker images | ||
| # 2. Version tags (v*) - Builds and publishes release images with version tags | ||
| # 3. Pull requests to 'main' - Only builds and tests (no publishing) | ||
| # 4. Manual trigger via workflow_dispatch | ||
| # | ||
| # Jobs: | ||
| # ----- | ||
| # 1. build: Compiles the JAR, runs tests, and uploads artifacts | ||
| # 2. publish-docker: Publishes multi-platform Docker images using Jib | ||
| # | ||
| # Published Images: | ||
| # ---------------- | ||
| # - GitHub Container Registry: ghcr.io/OWNER/solr-mcp:TAG | ||
| # - Docker Hub: DOCKERHUB_USERNAME/solr-mcp:TAG | ||
| # | ||
| # Image Tagging Strategy: | ||
| # ---------------------- | ||
| # - Main branch: VERSION-SHORT_SHA (e.g., 1.0.0-SNAPSHOT-a1b2c3d) + latest | ||
| # - Version tags: VERSION (e.g., 1.0.0) + latest | ||
| # | ||
| # Required Secrets (for Docker Hub): | ||
| # ---------------------------------- | ||
| # - DOCKERHUB_USERNAME: Your Docker Hub username | ||
| # - DOCKERHUB_TOKEN: Docker Hub access token (https://hub.docker.com/settings/security) | ||
| # | ||
| # Note: GitHub Container Registry uses GITHUB_TOKEN automatically (no setup needed) | ||
| 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 # Build + publish dev images on main merges | ||
| tags: | ||
| - 'v*' # CAUTION (ASF): tag pushes will publish images; prefer using release-publish.yml for post-vote releases | ||
| pull_request: | ||
| branches: | ||
| - main # Build + test validation for incoming changes | ||
| workflow_dispatch: # Manual runs for maintainers | ||
| jobs: | ||
| # ============================================================================ | ||
| # Job 1: Build JAR | ||
| # ============================================================================ | ||
| # This job compiles the project, runs tests, and generates build artifacts. | ||
| # It runs on all triggers (push, PR, tags, manual). | ||
| # | ||
| # Outputs: | ||
| # - Spring Boot JAR with all dependencies (fat JAR) | ||
| # - Plain JAR without dependencies | ||
| # - JUnit test results | ||
| # - JaCoCo code coverage reports | ||
| # ============================================================================ | ||
| build: | ||
| name: Build JAR | ||
| runs-on: ubuntu-latest | ||
| steps: | ||
| # Checkout the repository code | ||
| - name: Checkout code | ||
| uses: actions/checkout@v4 | ||
| # Set up Java environment using centralized configuration | ||
| # See .github/actions/setup-java/action.yml to update Java version | ||
| - name: Set up Java | ||
| uses: ./.github/actions/setup-java | ||
| # Build the project with Gradle | ||
| # This runs: compilation, tests, spotless formatting, error-prone checks, | ||
| # JaCoCo coverage, and creates the JAR files | ||
| - name: Build with Gradle | ||
| run: ./gradlew build | ||
| # Upload the compiled JAR files as workflow artifacts | ||
| # These can be downloaded from the GitHub Actions UI | ||
| # Artifacts are retained for 7 days | ||
| - name: Upload JAR artifact | ||
| uses: actions/upload-artifact@v4 | ||
| with: | ||
| name: solr-mcp-jar | ||
| path: build/libs/solr-mcp-*.jar | ||
| retention-days: 7 | ||
| # Upload JUnit test results | ||
| # if: always() ensures this runs even if the build fails | ||
| # This allows viewing test results for failed builds | ||
| - name: Upload test results | ||
| if: always() | ||
| uses: actions/upload-artifact@v4 | ||
| with: | ||
| name: test-results | ||
| path: build/test-results/ | ||
| retention-days: 7 | ||
| # Upload JaCoCo code coverage report | ||
| # if: always() ensures this runs even if tests fail | ||
| # Coverage reports help identify untested code paths | ||
| - name: Upload coverage report | ||
| if: always() | ||
| uses: actions/upload-artifact@v4 | ||
| with: | ||
| name: coverage-report | ||
| path: build/reports/jacoco/ | ||
| retention-days: 7 | ||
| # ============================================================================ | ||
| # Job 2: Publish Docker Images | ||
| # ============================================================================ | ||
| # This job builds multi-platform Docker images using Jib and publishes them | ||
| # to GitHub Container Registry (GHCR) and Docker Hub. | ||
| # | ||
| # This job: | ||
| # - Only runs after 'build' job succeeds (needs: build) | ||
| # - Skips for pull requests (only runs on push to main and tags) | ||
| # - Uses Jib to build without requiring Docker daemon | ||
| # - Supports multi-platform: linux/amd64 and linux/arm64 | ||
| # - Publishes to both GHCR (always) and Docker Hub (if secrets configured) | ||
| # | ||
| # Security Note: | ||
| # - Secrets are passed to Jib CLI arguments for authentication | ||
| # - This is required for registry authentication and is handled securely | ||
| # - GitHub Actions masks secret values in logs automatically | ||
| # ============================================================================ | ||
| publish-docker: | ||
| 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 | ||
| # contents:read - Read repository contents | ||
| # packages:write - Publish to GitHub Container Registry | ||
| permissions: | ||
| contents: read | ||
| packages: write | ||
| steps: | ||
| # Checkout the repository code | ||
| - name: Checkout code | ||
| uses: actions/checkout@v4 | ||
| # Set up Java environment using centralized configuration | ||
| # See .github/actions/setup-java/action.yml to update Java version | ||
| - name: Set up Java | ||
| uses: ./.github/actions/setup-java | ||
| # Extract version and determine image tags | ||
| # Outputs: | ||
| # - version: Project version from build.gradle.kts | ||
| # - tags: Comma-separated list of Docker tags to apply | ||
| # - is_release: Whether this is a release build (from version tag) | ||
| - name: Extract metadata | ||
| id: meta | ||
| run: | | ||
| # Get version from build.gradle.kts | ||
| VERSION=$(grep '^version = ' build.gradle.kts | sed 's/version = "\(.*\)"/\1/') | ||
| echo "version=$VERSION" >> $GITHUB_OUTPUT | ||
| # Determine image tags based on trigger type | ||
| if [[ "${{ github.ref }}" == refs/tags/v* ]]; then | ||
| # For version tags (e.g., v1.0.0), use semantic version | ||
| TAG_VERSION=${GITHUB_REF#refs/tags/v} | ||
| echo "tags=$TAG_VERSION,latest" >> $GITHUB_OUTPUT | ||
| echo "is_release=true" >> $GITHUB_OUTPUT | ||
| else | ||
| # For main branch, append short commit SHA for traceability | ||
| SHORT_SHA=$(echo ${{ github.sha }} | cut -c1-7) | ||
| echo "tags=$VERSION-$SHORT_SHA,latest" >> $GITHUB_OUTPUT | ||
| echo "is_release=false" >> $GITHUB_OUTPUT | ||
| fi | ||
| # Authenticate to GitHub Container Registry | ||
| # Uses built-in GITHUB_TOKEN (no configuration needed) | ||
| - name: Log in to GitHub Container Registry | ||
| uses: docker/login-action@v3 | ||
| with: | ||
| registry: ghcr.io | ||
| username: ${{ github.actor }} | ||
| password: ${{ secrets.GITHUB_TOKEN }} | ||
| # Authenticate to Docker Hub | ||
| # Requires DOCKERHUB_USERNAME and DOCKERHUB_TOKEN secrets | ||
| # This step will fail silently if secrets are not configured | ||
| # Create a Docker Hub access token, then add two GitHub Actions secrets named `DOCKERHUB_USERNAME` and `DOCKERHUB_TOKEN`. | ||
| # | ||
| # Steps (web UI) | ||
| # - Create Docker Hub token: | ||
| # - Visit `https://hub.docker.com` | ||
| # - Account → Settings → Security → New Access Token | ||
| # - Copy the generated token (you can’t view it again). | ||
| # - Add secrets to the repository: | ||
| # - In GitHub, open the repo → `Settings` → `Secrets and variables` → `Actions` → `New repository secret` | ||
| # - Add secret `DOCKERHUB_USERNAME` with your Docker Hub username. | ||
| # - Add secret `DOCKERHUB_TOKEN` with the token from Docker Hub. | ||
| # | ||
| # Optional | ||
| # - To make secrets available to multiple repos, add them at the organization level: Org → `Settings` → `Secrets and variables` → `Actions`. | ||
| # - You can also add environment-level secrets if you use GitHub Environments. | ||
| # | ||
| # CLI example (GitHub CLI) | ||
| # ```bash | ||
| # gh secret set DOCKERHUB_USERNAME --body "your-docker-username" | ||
| # gh secret set DOCKERHUB_TOKEN --body "your-docker-access-token" | ||
| # ``` | ||
| # | ||
| # Note: `GITHUB_TOKEN` is provided automatically for GHCR; do not store it manually. | ||
| # - name: Log in to Docker Hub | ||
| # uses: docker/login-action@v3 | ||
| # with: | ||
| # username: ${{ secrets.DOCKERHUB_USERNAME }} | ||
| # password: ${{ secrets.DOCKERHUB_TOKEN }} | ||
| # Convert repository owner to lowercase | ||
| # Required because container registry names must be lowercase | ||
| # Example: "Apache" -> "apache" | ||
| - name: Determine repository owner (lowercase) | ||
| id: repo | ||
| run: | | ||
| echo "owner_lc=$(echo '${{ github.repository_owner }}' | tr '[:upper:]' '[:lower:]')" >> $GITHUB_OUTPUT | ||
| # Build and publish images to GitHub Container Registry | ||
| # Uses Jib Gradle plugin to build multi-platform images | ||
| # Jib creates optimized, layered images without Docker daemon | ||
| # Each tag is built and pushed separately | ||
| - name: Build and publish to GitHub Container Registry | ||
| run: | | ||
| TAGS="${{ steps.meta.outputs.tags }}" | ||
| IFS=',' read -ra TAG_ARRAY <<< "$TAGS" | ||
| # Build and push each tag to GHCR | ||
| # Jib automatically handles multi-platform builds (amd64, arm64) | ||
| for TAG in "${TAG_ARRAY[@]}"; do | ||
| echo "Building and pushing ghcr.io/${{ steps.repo.outputs.owner_lc }}/solr-mcp:$TAG" | ||
| ./gradlew jib \ | ||
| -Djib.to.image=ghcr.io/${{ steps.repo.outputs.owner_lc }}/solr-mcp:$TAG \ | ||
| -Djib.to.auth.username=${{ github.actor }} \ | ||
| -Djib.to.auth.password=${{ secrets.GITHUB_TOKEN }} | ||
| done | ||
| # Build and publish images to Docker Hub | ||
| # Only runs if Docker Hub secrets are configured | ||
| # Gracefully skips if secrets are not available | ||
| - name: Build and publish to Docker Hub | ||
| if: secrets.DOCKERHUB_USERNAME != '' && secrets.DOCKERHUB_TOKEN != '' | ||
| run: | | ||
| TAGS="${{ steps.meta.outputs.tags }}" | ||
| IFS=',' read -ra TAG_ARRAY <<< "$TAGS" | ||
| # Build and push each tag to Docker Hub | ||
| for TAG in "${TAG_ARRAY[@]}"; do | ||
| echo "Building and pushing ${{ secrets.DOCKERHUB_USERNAME }}/solr-mcp:$TAG" | ||
| ./gradlew jib \ | ||
| -Djib.to.image=${{ secrets.DOCKERHUB_USERNAME }}/solr-mcp:$TAG \ | ||
| -Djib.to.auth.username=${{ secrets.DOCKERHUB_USERNAME }} \ | ||
| -Djib.to.auth.password=${{ secrets.DOCKERHUB_TOKEN }} | ||
| done | ||
| # Create a summary of published images | ||
| # Displayed in the GitHub Actions workflow summary page | ||
| # Makes it easy to see which images were published and their tags | ||
| - name: Summary | ||
| run: | | ||
| echo "### Docker Images Published :rocket:" >> $GITHUB_STEP_SUMMARY | ||
| echo "" >> $GITHUB_STEP_SUMMARY | ||
| echo "#### GitHub Container Registry" >> $GITHUB_STEP_SUMMARY | ||
| TAGS="${{ steps.meta.outputs.tags }}" | ||
| IFS=',' read -ra TAG_ARRAY <<< "$TAGS" | ||
| for TAG in "${TAG_ARRAY[@]}"; do | ||
| echo "- \`ghcr.io/${{ steps.repo.outputs.owner_lc }}/solr-mcp:$TAG\`" >> $GITHUB_STEP_SUMMARY | ||
| done | ||
| # Only show Docker Hub section if secrets are configured | ||
| if [[ "${{ secrets.DOCKERHUB_USERNAME }}" != "" ]]; then | ||
| echo "" >> $GITHUB_STEP_SUMMARY | ||
| echo "#### Docker Hub" >> $GITHUB_STEP_SUMMARY | ||
| for TAG in "${TAG_ARRAY[@]}"; do | ||
| echo "- \`${{ secrets.DOCKERHUB_USERNAME }}/solr-mcp:$TAG\`" >> $GITHUB_STEP_SUMMARY | ||
| done | ||
| fi | ||