Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
146 changes: 146 additions & 0 deletions .github/actions/build-and-push-container-image-test/action.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,146 @@
---
# This local action builds an image and pushes it to private ECR for testing
name: "Build and push image (Test)"
author: "MCP Proxy for AWS"
description: "Builds an image and pushes it to private ECR for testing"

inputs:
image:
description: 'The image'
type: string
required: true
version:
default: ''
description: 'The version to associate to the image'
type: string
required: false
ecr-role-to-assume:
description: 'The ECR role to use to push the image'
type: string
required: true
ecr-repository:
description: 'The ECR repository name'
type: string
required: true
ecr-aws-region:
default: 'us-east-1'
description: 'The region to login'
type: string
required: false

outputs:
version:
description: 'The version uploaded'
value: ${{ steps.get-version.outputs.version }}

runs:
using: "composite"
steps:
- name: Setup AWS Credentials
id: setup-aws-credentials
uses: aws-actions/configure-aws-credentials@ececac1a45f3b08a01d2dd070d28d111c5fe6722 # v4.1.0
with:
role-to-assume: ${{ inputs.ecr-role-to-assume }}
aws-region: ${{ inputs.ecr-aws-region }}
role-duration-seconds: 7200
role-session-name: GitHubActions${{ github.run_id }}
mask-aws-account-id: true

- name: Login to Amazon ECR
id: login-ecr
uses: aws-actions/amazon-ecr-login@062b18b96a7aff071d4dc91bc00c4c1a7945b076 # v2.0.1

- name: Docker meta
id: meta
uses: docker/metadata-action@902fa8ec7d6ecbf8d84d538b9b233a880e428804 # v5.7.0
with:
images: |
${{ steps.login-ecr.outputs.registry }}/${{ inputs.ecr-repository }}
# Disable all but the raw and sha
tags: |
type=schedule,enable=false
type=semver,pattern={{raw}},enable=false
type=pep440,pattern={{raw}},enable=false
type=match,pattern=(.*),group=1,enable=false
type=edge,enable=false
type=ref,event=branch,enable=false
type=ref,event=tag,enable=false
type=ref,event=pr,enable=false
type=sha,format=long,enable=true
type=raw,value=latest,enable=true
type=raw,value=${{ inputs.version || github.sha }},enable=${{ (inputs.version && true) || 'false' }}
labels: |
maintainer=MCP Proxy for AWS
org.opencontainers.image.description=MCP Proxy for AWS (Test Build)
org.opencontainers.image.source=https://github.com/${{ github.repository }}
org.opencontainers.image.title=${{ inputs.image }}
org.opencontainers.image.url=https://github.com/${{ github.repository }}
org.opencontainers.image.version=${{ inputs.version || github.sha }}
org.opencontainers.image.vendor=Amazon Web Services, Inc.

- name: Set up QEMU
id: setup-qemu
uses: docker/setup-qemu-action@29109295f81e9208d7d86ff1c6c12d2833863392 # v3.6.0

- name: Set up Docker Buildx
id: setup-buildx
uses: docker/setup-buildx-action@b5ca514318bd6ebac0fb2aedd5d36ec1b5c232a2 # v3.10.0
with:
buildkitd-flags: --debug

- name: Build and push by digest
id: build
uses: docker/build-push-action@14487ce63c7a62a4a324b0bfb37086795e31c6c1 # v6.16.0
with:
platforms: 'linux/amd64,linux/arm64'
labels: ${{ steps.meta.outputs.labels }}
tags: ${{ steps.login-ecr.outputs.registry }}/${{ inputs.ecr-repository }}
context: .
file: ./Dockerfile
push: true
outputs: type=image,push-by-digest=true,name-canonical=true,push=true
cache-from: type=gha
cache-to: type=gha,mode=max

- name: Export digest
run: |
mkdir -p ${{ runner.temp }}/digests/${{ inputs.image }}
digest="${{ steps.build.outputs.digest }}"
touch "${{ runner.temp }}/digests/${{ inputs.image }}/${digest#sha256:}"
shell: bash

- name: Upload digest
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
with:
name: digests-${{ inputs.image }}
path: ${{ runner.temp }}/digests/${{ inputs.image }}/*
if-no-files-found: error
retention-days: 1

- name: Create manifest list and push
working-directory: ${{ runner.temp }}/digests/${{ inputs.image }}
env:
IMAGE: ${{ inputs.image }}
REGISTRY: ${{ steps.login-ecr.outputs.registry }}
REPOSITORY: ${{ inputs.ecr-repository }}
run: |
echo "DOCKER_METADATA_OUTPUT_JSON=$DOCKER_METADATA_OUTPUT_JSON"
docker buildx imagetools create $(jq -cr '.tags | map("-t " + .) | join(" ")' <<< "$DOCKER_METADATA_OUTPUT_JSON") \
$(printf ''$REGISTRY'/'$REPOSITORY'@sha256:%s ' *)
shell: bash

- name: Inspect image
env:
IMAGE: ${{ inputs.image }}
REGISTRY: ${{ steps.login-ecr.outputs.registry }}
REPOSITORY: ${{ inputs.ecr-repository }}
VERSION: ${{ steps.meta.outputs.version }}
run: |
docker buildx imagetools inspect $REGISTRY/$REPOSITORY:$VERSION
shell: bash

- name: Get version
id: get-version
run: |
echo version="${{ steps.meta.outputs.version }}" >>"$GITHUB_OUTPUT"
shell: bash
147 changes: 147 additions & 0 deletions .github/actions/build-and-push-container-image/action.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,147 @@
---
# This local action builds an image and pushes it to registries
name: "Build and push image"
author: "MCP Proxy for AWS"
description: "Builds an image and pushes it to registries"

inputs:
image:
description: 'The image'
type: string
required: true
version:
default: ''
description: 'The version to associate to the image'
type: string
required: false
public-ecr-role-to-assume:
description: 'The public ECR role to use to push the image'
type: string
required: true
public-ecr-registry-alias:
description: 'The registry alias'
type: string
required: true
public-ecr-aws-region:
default: 'us-east-1'
description: 'The region to login'
type: string
required: false

outputs:
version:
description: 'The version uploaded'
value: ${{ steps.get-version.outputs.version }}

runs:
using: "composite"
steps:
- name: Docker meta
id: meta
uses: docker/metadata-action@902fa8ec7d6ecbf8d84d538b9b233a880e428804 # v5.7.0
with:
images: |
public.ecr.aws/${{ inputs.public-ecr-registry-alias }}/${{ github.repository_owner }}/${{ inputs.image }}
# Disable all but the raw and sha
tags: |
type=schedule,enable=false
type=semver,pattern={{raw}},enable=false
type=pep440,pattern={{raw}},enable=false
type=match,pattern=(.*),group=1,enable=false
type=edge,enable=false
type=ref,event=branch,enable=false
type=ref,event=tag,enable=false
type=ref,event=pr,enable=false
type=sha,format=long,enable=true
type=raw,value=latest,enable=true
type=raw,value=${{ inputs.version || github.sha }},enable=${{ (inputs.version && true) || 'false' }}
labels: |
maintainer=MCP Proxy for AWS
org.opencontainers.image.description=MCP Proxy for AWS
org.opencontainers.image.source=https://github.com/${{ github.repository_owner }}/${{ inputs.image }}
org.opencontainers.image.title=aws.${{ inputs.image }}
org.opencontainers.image.url=https://github.com/${{ github.repository_owner }}/${{ inputs.image }}
org.opencontainers.image.version=${{ inputs.version || github.sha }}
org.opencontainers.image.vendor=Amazon Web Services, Inc.

- name: Setup AWS Credentials
id: setup-aws-credentials
uses: aws-actions/configure-aws-credentials@ececac1a45f3b08a01d2dd070d28d111c5fe6722 # v4.1.0
with:
role-to-assume: ${{ inputs.public-ecr-role-to-assume }}
aws-region: ${{ inputs.public-ecr-aws-region }}
role-duration-seconds: 7200
role-session-name: GitHubActions${{ github.run_id }}
mask-aws-account-id: true

- name: Login to Public ECR
uses: docker/login-action@74a5d142397b4f367a81961eba4e8cd7edddf772 # v3.4.0
with:
registry: public.ecr.aws

- name: Set up QEMU
id: setup-qemu
uses: docker/setup-qemu-action@29109295f81e9208d7d86ff1c6c12d2833863392 # v3.6.0

- name: Set up Docker Buildx
id: setup-buildx
uses: docker/setup-buildx-action@b5ca514318bd6ebac0fb2aedd5d36ec1b5c232a2 # v3.10.0
with:
buildkitd-flags: --debug

- name: Build and push by digest
id: build
uses: docker/build-push-action@14487ce63c7a62a4a324b0bfb37086795e31c6c1 # v6.16.0
with:
platforms: 'linux/amd64,linux/arm64'
labels: ${{ steps.meta.outputs.labels }}
tags: public.ecr.aws/${{ inputs.public-ecr-registry-alias }}/${{ github.repository_owner }}/${{ inputs.image }}
context: .
file: ./Dockerfile
push: true
outputs: type=image,push-by-digest=true,name-canonical=true,push=true
cache-from: type=gha
cache-to: type=gha,mode=max

- name: Export digest
run: |
mkdir -p ${{ runner.temp }}/digests/${{ inputs.image }}
digest="${{ steps.build.outputs.digest }}"
touch "${{ runner.temp }}/digests/${{ inputs.image }}/${digest#sha256:}"
shell: bash

- name: Upload digest
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
with:
name: digests-${{ inputs.image }}
path: ${{ runner.temp }}/digests/${{ inputs.image }}/*
if-no-files-found: error
retention-days: 1

- name: Create manifest list and push
working-directory: ${{ runner.temp }}/digests/${{ inputs.image }}
env:
IMAGE: ${{ inputs.image }}
ALIAS: ${{ inputs.public-ecr-registry-alias }}
OWNER: ${{ github.repository_owner }}
run: |
echo "DOCKER_METADATA_OUTPUT_JSON=$DOCKER_METADATA_OUTPUT_JSON"
docker buildx imagetools create $(jq -cr '.tags | map("-t " + .) | join(" ")' <<< "$DOCKER_METADATA_OUTPUT_JSON") \
$(printf 'public.ecr.aws/'$ALIAS'/'$OWNER'/'$IMAGE'@sha256:%s ' *)
shell: bash

- name: Inspect image
env:
IMAGE: ${{ inputs.image }}
ALIAS: ${{ inputs.public-ecr-registry-alias }}
OWNER: ${{ github.repository_owner }}
VERSION: ${{ steps.meta.outputs.version }}
run: |
docker buildx imagetools inspect public.ecr.aws/$ALIAS/$OWNER/$IMAGE:$VERSION
shell: bash

- name: Get version
id: get-version
run: |
echo version="${{ steps.meta.outputs.version }}" >>"$GITHUB_OUTPUT"
shell: bash
46 changes: 43 additions & 3 deletions .github/workflows/pypi-publish-on-release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -59,15 +59,55 @@ jobs:
url: https://pypi.org/p/mcp-proxy-for-aws
permissions:
id-token: write
contents: read
steps:
- name: Checkout code
uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
with:
persist-credentials: false

- name: Download distribution packages
uses: actions/download-artifact@v5
uses: actions/download-artifact@v4
with:
name: python-package-distributions
path: dist/

- name: Set up uv
uses: astral-sh/setup-uv@v4
uses: astral-sh/setup-uv@ed21f2f24f8dd64503750218de024bcf64c7250a # v7.1.5

- name: Get version from package
id: get-package-version
run: |
set -euo pipefail

# Get version from uv
VERSION="$(uv tree 2>/dev/null | grep mcp-proxy-for-aws | sed -e 's/^.*[[:space:]]v\(.*\)/\1/g' | head -1)"

if [[ -z "$VERSION" ]]; then
echo "::error::Failed to extract version from package" >&2
exit 1
fi

# Validate version format
if [[ ! "$VERSION" =~ ^[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
echo "::error::Invalid version format: $VERSION" >&2
exit 1
fi

echo "version=$VERSION" >> $GITHUB_OUTPUT
echo "::debug::Package version: $VERSION"

- name: Publish to PyPI
run: uv publish
uses: pypa/gh-action-pypi-publish@ed0c53931b1dc9bd32cbe73a98c7f6766f8a527e # v1.13.0
with:
print-hash: true

- name: Build and Publish Container
id: build-and-publish
uses: ./.github/actions/build-and-push-container-image
with:
image: mcp-proxy-for-aws
version: ${{ steps.get-package-version.outputs.version }}
public-ecr-role-to-assume: ${{ secrets.AWS_ROLE_TO_ASSUME }}
public-ecr-registry-alias: awslabs-mcp
public-ecr-aws-region: us-east-1
Loading
Loading