Publish to MCR #15
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: Publish to MCR | |
| on: | |
| # Manual trigger for testing and ad-hoc releases | |
| workflow_dispatch: | |
| inputs: | |
| tag: | |
| description: "Git tag (e.g., v1.2.3)" | |
| required: true | |
| ghcr_image: | |
| description: "GHCR source image (optional, defaults to ghcr.io/azure/aks-mcp:<tag>)" | |
| required: false | |
| # Automatic trigger after SLSA releaser completes | |
| workflow_run: | |
| workflows: ["SLSA releaser"] | |
| types: [completed] | |
| permissions: | |
| contents: read | |
| packages: read | |
| env: | |
| GHCR_REGISTRY: ghcr.io | |
| GHCR_IMAGE_NAME: azure/aks-mcp | |
| jobs: | |
| publish-to-mcr: | |
| # Only run on successful workflow_run or manual dispatch | |
| if: ${{ github.event_name == 'workflow_dispatch' || github.event.workflow_run.conclusion == 'success' }} | |
| runs-on: | |
| labels: ["self-hosted", "1ES.Pool=1es-aks-mcp-agent-pool-ubuntu"] | |
| environment: publish-mcr | |
| outputs: | |
| version: ${{ steps.version.outputs.version }} | |
| mcr_image: ${{ steps.push.outputs.mcr_image }} | |
| image_id: ${{ steps.verify.outputs.image_id }} | |
| steps: | |
| - name: Determine version and source image | |
| id: version | |
| run: | | |
| if [ "${{ github.event_name }}" = "workflow_dispatch" ]; then | |
| TAG="${{ github.event.inputs.tag }}" | |
| GHCR_IMAGE="${{ github.event.inputs.ghcr_image }}" | |
| else | |
| # Extract tag from workflow_run ref (refs/tags/v1.2.3 -> v1.2.3) | |
| TAG="${{ github.event.workflow_run.head_branch }}" | |
| if [[ ! "$TAG" =~ ^v[0-9]+\.[0-9]+\.[0-9]+ ]]; then | |
| echo "Not a version tag, skipping MCR publish" | |
| exit 0 | |
| fi | |
| fi | |
| # Use provided GHCR image or construct default | |
| if [ -z "$GHCR_IMAGE" ]; then | |
| GHCR_IMAGE="${{ env.GHCR_REGISTRY }}/${{ env.GHCR_IMAGE_NAME }}:${TAG}" | |
| fi | |
| # Keep the version with 'v' prefix for MCR | |
| VERSION="${TAG}" | |
| echo "tag=${TAG}" >> "$GITHUB_OUTPUT" | |
| echo "version=${VERSION}" >> "$GITHUB_OUTPUT" | |
| echo "ghcr_image=${GHCR_IMAGE}" >> "$GITHUB_OUTPUT" | |
| echo "Git Tag: ${TAG}" | |
| echo "MCR Version: ${VERSION}" | |
| echo "Source GHCR Image: ${GHCR_IMAGE}" | |
| echo "Note: MCR version keeps 'v' prefix to match GHCR" | |
| - name: Authenticate to Azure | |
| run: | | |
| az login --identity | |
| az account show | |
| - name: Authenticate to MCR | |
| id: mcr-auth | |
| run: | | |
| MCR_REGISTRY=$(echo "${{ secrets.AKS_MCP_MCR_REGISTRY }}" | tr '[:upper:]' '[:lower:]') | |
| az acr login -n ${{ secrets.AKS_MCP_MCR_REGISTRY }} | |
| echo "registry=${MCR_REGISTRY}" >> "$GITHUB_OUTPUT" | |
| - name: Authenticate to GHCR | |
| run: | | |
| echo "${{ secrets.GITHUB_TOKEN }}" | docker login ${{ env.GHCR_REGISTRY }} -u ${{ github.actor }} --password-stdin | |
| - name: Pull image from GHCR | |
| id: pull | |
| run: | | |
| GHCR_IMAGE="${{ steps.version.outputs.ghcr_image }}" | |
| echo "Pulling image: ${GHCR_IMAGE}" | |
| docker pull ${GHCR_IMAGE} | |
| # Get the image ID (content hash) from GHCR | |
| GHCR_IMAGE_ID=$(docker inspect ${GHCR_IMAGE} --format='{{.Id}}') | |
| echo "ghcr_image_id=${GHCR_IMAGE_ID}" >> "$GITHUB_OUTPUT" | |
| echo "GHCR Image ID: ${GHCR_IMAGE_ID}" | |
| - name: Tag and push to MCR | |
| id: push | |
| run: | | |
| GHCR_IMAGE="${{ steps.version.outputs.ghcr_image }}" | |
| VERSION="${{ steps.version.outputs.version }}" | |
| MCR_REGISTRY="${{ steps.mcr-auth.outputs.registry }}" | |
| MCR_INTERNAL_IMAGE="${MCR_REGISTRY}.azurecr.io/public/aks/aks-mcp" | |
| MCR_PUBLIC_IMAGE="mcr.microsoft.com/aks/aks-mcp" | |
| # Tag and push (suppress output to avoid exposing internal registry) | |
| docker tag ${GHCR_IMAGE} ${MCR_INTERNAL_IMAGE}:${VERSION} | |
| docker tag ${GHCR_IMAGE} ${MCR_INTERNAL_IMAGE}:latest | |
| docker push ${MCR_INTERNAL_IMAGE}:${VERSION} > /dev/null 2>&1 | |
| docker push ${MCR_INTERNAL_IMAGE}:latest > /dev/null 2>&1 | |
| # Output the public MCR image for display (not the internal registry) | |
| echo "mcr_image=${MCR_PUBLIC_IMAGE}:${VERSION}" >> "$GITHUB_OUTPUT" | |
| echo "mcr_internal_image=${MCR_INTERNAL_IMAGE}:${VERSION}" >> "$GITHUB_OUTPUT" | |
| echo "Successfully pushed to mcr.microsoft.com/aks/aks-mcp:${VERSION}" | |
| - name: Verify image consistency | |
| id: verify | |
| run: | | |
| GHCR_IMAGE="${{ steps.version.outputs.ghcr_image }}" | |
| MCR_INTERNAL_IMAGE="${{ steps.push.outputs.mcr_internal_image }}" | |
| MCR_PUBLIC_IMAGE="${{ steps.push.outputs.mcr_image }}" | |
| # Pull and inspect (suppress output to avoid exposing internal registry) | |
| docker pull ${MCR_INTERNAL_IMAGE} > /dev/null 2>&1 | |
| MCR_IMAGE_ID=$(docker inspect ${MCR_INTERNAL_IMAGE} --format='{{.Id}}') | |
| echo "Source: ${GHCR_IMAGE}" | |
| echo "Published: ${MCR_PUBLIC_IMAGE}" | |
| echo "Image ID: ${MCR_IMAGE_ID}" | |
| # Get and compare layer information (more reliable than Image ID) | |
| GHCR_LAYERS=$(docker inspect ${GHCR_IMAGE} --format='{{range .RootFS.Layers}}{{println .}}{{end}}' | sort) | |
| MCR_LAYERS=$(docker inspect ${MCR_INTERNAL_IMAGE} --format='{{range .RootFS.Layers}}{{println .}}{{end}}' | sort) | |
| echo "" | |
| echo "=== Layer Verification ===" | |
| GHCR_LAYER_COUNT=$(echo "${GHCR_LAYERS}" | wc -l) | |
| MCR_LAYER_COUNT=$(echo "${MCR_LAYERS}" | wc -l) | |
| echo "GHCR Layer Count: ${GHCR_LAYER_COUNT}" | |
| echo "MCR Layer Count: ${MCR_LAYER_COUNT}" | |
| if [ "${GHCR_LAYERS}" = "${MCR_LAYERS}" ]; then | |
| echo "✅ Image verification PASSED - All layers are identical" | |
| echo "image_id=${MCR_IMAGE_ID}" >> "$GITHUB_OUTPUT" | |
| else | |
| echo "❌ Image verification FAILED - Layers differ!" | |
| echo "" | |
| echo "GHCR Layers:" | |
| echo "${GHCR_LAYERS}" | |
| echo "" | |
| echo "MCR Layers:" | |
| echo "${MCR_LAYERS}" | |
| exit 1 | |
| fi | |
| # Verification complete | |
| echo "" | |
| echo "✅ Image layers verified successfully" | |
| - name: Summary | |
| run: | | |
| echo "## MCR Publishing Summary" >> $GITHUB_STEP_SUMMARY | |
| echo "" >> $GITHUB_STEP_SUMMARY | |
| echo "✅ Successfully published to MCR" >> $GITHUB_STEP_SUMMARY | |
| echo "" >> $GITHUB_STEP_SUMMARY | |
| echo "- **Git Tag**: ${{ steps.version.outputs.tag }}" >> $GITHUB_STEP_SUMMARY | |
| echo "- **MCR Version**: ${{ steps.version.outputs.version }}" >> $GITHUB_STEP_SUMMARY | |
| echo "- **Source Image**: ${{ steps.version.outputs.ghcr_image }}" >> $GITHUB_STEP_SUMMARY | |
| echo "- **MCR Image**: ${{ steps.push.outputs.mcr_image }}" >> $GITHUB_STEP_SUMMARY | |
| echo "- **Image ID**: ${{ steps.verify.outputs.image_id }}" >> $GITHUB_STEP_SUMMARY | |
| echo "" >> $GITHUB_STEP_SUMMARY | |
| echo "### Verification" >> $GITHUB_STEP_SUMMARY | |
| echo "\`\`\`bash" >> $GITHUB_STEP_SUMMARY | |
| echo "docker pull ${{ steps.push.outputs.mcr_image }}" >> $GITHUB_STEP_SUMMARY | |
| echo "\`\`\`" >> $GITHUB_STEP_SUMMARY |