diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index eca8c4d..d5d44b2 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -17,14 +17,14 @@ jobs: uses: actions/checkout@v4.2.2 with: fetch-depth: 0 - + - name: Set up Go uses: actions/setup-go@v5 with: go-version: '1.24' check-latest: true cache: true - + - name: Check formatting run: | if [ "$(gofmt -s -l . | wc -l)" -gt 0 ]; then @@ -33,7 +33,7 @@ jobs: echo "Please run 'go fmt ./...' to fix formatting issues." exit 1 fi - + - name: Run go vet run: go vet ./... @@ -46,20 +46,20 @@ jobs: uses: actions/checkout@v4.2.2 with: fetch-depth: 0 - + - name: Set up Go uses: actions/setup-go@v5 with: go-version: '1.24' check-latest: true cache: true - + - name: Lint uses: golangci/golangci-lint-action@v8 with: version: latest args: --timeout=5m - + test: name: Test runs-on: ubuntu-latest @@ -69,27 +69,27 @@ jobs: uses: actions/checkout@v4.2.2 with: fetch-depth: 0 - + - name: Set up Go uses: actions/setup-go@v5 with: go-version: '1.24' check-latest: true cache: true - + - name: Install dependencies run: go mod download - + - name: Run tests with coverage run: go test -race -coverprofile=coverage.txt -covermode=atomic ./... - + - name: Upload coverage to Codecov uses: codecov/codecov-action@v5 with: file: ./coverage.txt fail_ci_if_error: false continue-on-error: true - + - name: Archive code coverage results uses: actions/upload-artifact@v4 with: @@ -106,25 +106,67 @@ jobs: uses: actions/checkout@v4.2.2 with: fetch-depth: 0 - + - name: Set up Go uses: actions/setup-go@v5 with: go-version: '1.24' check-latest: true cache: true - - - name: Build binary + + - name: Build Linux binary run: | go build -o aks-mcp ./cmd/aks-mcp - - - name: Build Docker image - run: docker build -t aks-mcp:test . - - - name: Check Docker image + + - name: Build Windows binary + run: | + GOOS=windows GOARCH=amd64 go build -trimpath -tags withoutebpf -o aks-mcp.exe ./cmd/aks-mcp + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v3 + + - name: Build Linux Docker image + uses: docker/build-push-action@v6 + with: + push: false + platforms: linux/amd64 + tags: aks-mcp:linux-test + file: ./Dockerfile + load: true + + - name: Validate Linux Docker image run: | - docker images aks-mcp:test - docker run --rm aks-mcp:test --help || true + docker images aks-mcp:linux-test + docker run --rm aks-mcp:linux-test --help || true + + build-windows: + name: Build Windows + runs-on: windows-latest + needs: [lint, test] + steps: + - name: Checkout code + uses: actions/checkout@v4.2.2 + with: + fetch-depth: 0 + + - name: Set up Go + uses: actions/setup-go@v5 + with: + go-version: '1.24' + check-latest: true + cache: true + + - name: Build Windows binary + run: | + go build -trimpath -tags withoutebpf -o aks-mcp.exe ./cmd/aks-mcp + + - name: Build Windows Docker image + run: docker build --platform windows/amd64 -f Dockerfile.windows -t aks-mcp:windows-test . + + - name: Validate Windows Docker image + run: | + docker images aks-mcp:windows-test + docker run --rm aks-mcp:windows-test --help || true security: name: Security Scan @@ -134,8 +176,8 @@ jobs: uses: actions/checkout@v4.2.2 with: fetch-depth: 0 - + - name: Run Gosec Security Scanner uses: securego/gosec@master with: - args: ./... \ No newline at end of file + args: ./... diff --git a/.github/workflows/go-ossf-slsa3-publish.yml b/.github/workflows/go-ossf-slsa3-publish.yml index ab01d35..913ab59 100644 --- a/.github/workflows/go-ossf-slsa3-publish.yml +++ b/.github/workflows/go-ossf-slsa3-publish.yml @@ -75,7 +75,7 @@ jobs: needs: args outputs: image: ${{ steps.image.outputs.image }} - digest: ${{ steps.build.outputs.digest }} + digest: ${{ steps.image.outputs.digest }} runs-on: ubuntu-latest steps: - name: Checkout the repository @@ -97,18 +97,21 @@ jobs: with: images: ${{ env.IMAGE_REGISTRY }}/${{ env.IMAGE_NAME }} - - name: Build and push Docker image + - name: Build and push Linux Docker images uses: docker/build-push-action@263435318d21b8e681c14492fe198d362a7d2c83 # v6.18.0 - id: build + id: build-linux with: push: true + platforms: linux/amd64,linux/arm64 tags: ${{ steps.meta.outputs.tags }} labels: ${{ steps.meta.outputs.labels }} + file: ./Dockerfile build-args: | VERSION=${{ needs.args.outputs.version }} GIT_COMMIT=${{ needs.args.outputs.commit }} BUILD_DATE=${{ needs.args.outputs.commit-date }} GIT_TREE_STATE=${{ needs.args.outputs.tree-state }} + - name: Output image id: image run: | @@ -116,6 +119,45 @@ jobs: # available to the inputs of a reusable workflow call. image_name=$(echo "${IMAGE_REGISTRY}/${IMAGE_NAME}"| tr '[:upper:]' '[:lower:]') echo "image=$image_name" >> "$GITHUB_OUTPUT" + # Use the Linux build digest for provenance (primary platform) + echo "digest=${{ steps.build-linux.outputs.digest }}" >> "$GITHUB_OUTPUT" + + build-windows-image: + permissions: + contents: read + packages: write + needs: args + runs-on: windows-latest + steps: + - name: Checkout the repository + uses: actions/checkout@85e6279cec87321a52edac9c87bce653a07cf6c2 # v2.3.4 + + - name: Authenticate Docker + uses: docker/login-action@74a5d142397b4f367a81961eba4e8cd7edddf772 # v3.4.0 + with: + registry: ${{ env.IMAGE_REGISTRY }} + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} + + - name: Extract metadata (tags, labels) for Docker + id: meta + uses: docker/metadata-action@902fa8ec7d6ecbf8d84d538b9b233a880e428804 # v5.7.0 + with: + images: ${{ env.IMAGE_REGISTRY }}/${{ env.IMAGE_NAME }} + + - name: Build and push Windows Docker images + uses: docker/build-push-action@263435318d21b8e681c14492fe198d362a7d2c83 # v6.18.0 + with: + push: true + platforms: windows/amd64 + tags: ${{ steps.meta.outputs.tags }} + labels: ${{ steps.meta.outputs.labels }} + file: ./Dockerfile.windows + build-args: | + VERSION=${{ needs.args.outputs.version }} + GIT_COMMIT=${{ needs.args.outputs.commit }} + BUILD_DATE=${{ needs.args.outputs.commit-date }} + GIT_TREE_STATE=${{ needs.args.outputs.tree-state }} # This step calls the container workflow to generate provenance and push it to # the container registry. provenance: diff --git a/Dockerfile b/Dockerfile index 15b588d..e6fe705 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,9 +1,13 @@ +# Linux Dockerfile for aks-mcp # Build stage FROM golang:1.24-alpine AS builder +ARG TARGETOS=linux +ARG TARGETARCH ARG VERSION ARG GIT_COMMIT ARG BUILD_DATE ARG GIT_TREE_STATE + # Set working directory WORKDIR /app @@ -16,8 +20,8 @@ RUN go mod download # Copy source code COPY . . -# Build the application -RUN CGO_ENABLED=0 GOOS=linux go build -o aks-mcp ./cmd/aks-mcp +# Build the application for target platform +RUN CGO_ENABLED=0 GOOS=${TARGETOS} GOARCH=${TARGETARCH} go build -o aks-mcp ./cmd/aks-mcp # Runtime stage FROM alpine:3.22 diff --git a/Dockerfile.windows b/Dockerfile.windows new file mode 100644 index 0000000..c2342e6 --- /dev/null +++ b/Dockerfile.windows @@ -0,0 +1,52 @@ +# Windows Dockerfile for aks-mcp +# Build stage +FROM golang:1.24-windowsservercore-ltsc2022 AS builder +ARG TARGETOS=windows +ARG TARGETARCH=amd64 +ARG VERSION +ARG GIT_COMMIT +ARG BUILD_DATE +ARG GIT_TREE_STATE + +# Set working directory +WORKDIR "C:\\app" + +# Copy go mod and sum files +COPY go.mod go.sum ./ + +# Download dependencies +RUN go mod download + +# Copy source code +COPY . . + +# Build the application for Windows +RUN go build -trimpath -tags withoutebpf -o aks-mcp.exe ./cmd/aks-mcp + +# Runtime stage +FROM mcr.microsoft.com/windows/servercore:ltsc2022 + +# Set working directory +WORKDIR "C:\\app" + +# Use cmd shell +SHELL ["cmd.exe", "/S", "/C"] + +# Download and install Chocolatey using cmd and PowerShell inline +RUN @"%SystemRoot%\System32\WindowsPowerShell\v1.0\powershell.exe" -NoProfile -InputFormat None -ExecutionPolicy Bypass -Command "[System.Net.ServicePointManager]::SecurityProtocol = 3072; iex ((New-Object System.Net.WebClient).DownloadString('https://community.chocolatey.org/install.ps1'))" && SET "PATH=%PATH%;%ALLUSERSPROFILE%\chocolatey\bin" + +# Install Azure CLI using Chocolatey +RUN choco install azure-cli -y + +# Copy binary from builder +COPY --from=builder "C:\\app\\aks-mcp.exe" "C:\\app\\aks-mcp.exe" + +# Expose the default port for sse/streamable-http transports +EXPOSE 8000 + +# Set environment variables +ENV PATH="C:\\app;${PATH}" + +# Command to run +ENTRYPOINT ["C:\\app\\aks-mcp.exe"] +CMD ["--transport", "streamable-http", "--host", "0.0.0.0"] \ No newline at end of file