diff --git a/.github/workflows/build-docker.yml b/.github/workflows/build-docker.yml new file mode 100644 index 0000000..6cfe982 --- /dev/null +++ b/.github/workflows/build-docker.yml @@ -0,0 +1,61 @@ +name: container-images + +on: + push: + branches: [ "main" ] + tags: [ "v*" ] + +jobs: + build-container-image: + runs-on: ubuntu-latest + permissions: + contents: read + packages: write + steps: + - uses: actions/checkout@v4 + with: + fetch-depth: 0 + - uses: docker/setup-qemu-action@v3 + - uses: docker/setup-buildx-action@v3 + + - name: Set ALL_TAGS + env: + REPOSITORY: '${{ github.repository }}' + run: | + # tag main if main branch + if [[ "${{ github.ref_name }}" == "main" ]]; then + image_tags=("main") + # tag with tag name if tag + elif [[ "${{ github.ref }}" == refs/tags/v* ]]; then + image_tags=("${{ github.ref_name }}") + # tag with latest if tag is a new major, minor or patch version + if [[ "${{ github.ref_name }}" =~ ^v(0|[1-9][0-9]*)\.(0|[1-9][0-9]*)\.(0|[1-9][0-9]*)$ ]]; then + image_tags+=("latest") + fi + fi + + lc_repo=${REPOSITORY,,} + + image_paths=() + for tag in ${image_tags[@]}; do + image_paths+=("ghcr.io/$lc_repo:$tag") + done + + # join with ',' and then skip first character + ALL_TAGS=$(printf ',%s' "${image_paths[@]}") + echo "ALL_TAGS=${ALL_TAGS:1}" >>$GITHUB_ENV + + - name: Login to ghcr.io + uses: docker/login-action@v3 + with: + registry: ghcr.io + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} + + - name: Build and push default image + uses: docker/build-push-action@v5 + with: + context: . + platforms: linux/amd64,linux/arm64 + push: true + tags: ${{ env.ALL_TAGS }} diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 0000000..c9cbba1 --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,35 @@ +name: Release + +on: + push: + tags: + - 'v*' + +jobs: + release: + runs-on: ubuntu-latest + permissions: + contents: write + steps: + - name: Checkout code + uses: actions/checkout@v6 + with: + fetch-depth: 0 + + - name: Check if stable release + id: check + run: | + # align with build-docker.yml: stable only for strict semver tags + if [[ "${{ github.ref_name }}" =~ ^v(0|[1-9][0-9]*)\.(0|[1-9][0-9]*)\.(0|[1-9][0-9]*)$ ]]; then + echo "stable=true" >> "$GITHUB_OUTPUT" + else + echo "stable=false" >> "$GITHUB_OUTPUT" + fi + + - name: Create release + uses: softprops/action-gh-release@v2 + with: + generate_release_notes: true + draft: false + prerelease: ${{ steps.check.outputs.stable != 'true' }} + make_latest: ${{ steps.check.outputs.stable == 'true' }} diff --git a/README.md b/README.md index b51692b..ce0eeef 100644 --- a/README.md +++ b/README.md @@ -64,6 +64,14 @@ todo-mcp purge ## Docker +A pre-built image is available from GitHub Container Registry: + +```sh +docker run --rm -v todo-mcp-data:/data -e TODO_DB=/data/todos.db ghcr.io/janezicmatej/todo-mcp --help +``` + +Or build locally: + ```sh docker build -t local/todo-mcp . docker run --rm -v todo-mcp-data:/data -e TODO_DB=/data/todos.db local/todo-mcp --help @@ -88,8 +96,6 @@ Data is persisted in the `todo-mcp-data` volume. See [Usage](#usage) for more co ### Docker -Build the image first (see [Docker](#docker)), then add to your Claude MCP config: - ```json { "mcpServers": { @@ -99,7 +105,7 @@ Build the image first (see [Docker](#docker)), then add to your Claude MCP confi "run", "-i", "--rm", "-v", "todo-mcp-data:/data", "-e", "TODO_DB=/data/todos.db", - "local/todo-mcp", "mcp-serve" + "ghcr.io/janezicmatej/todo-mcp", "mcp-serve" ] } }