CI Updates (#536)
* Update the major tag of a version as well when publishing to Docker Useful for the asset store releases * feat: trigger publish workflows automatically after version bump and release creation It should work in theory, and correctly release to Docker and pypi via tags. * feat: consolidate release workflows into single pipeline with reusable actions Refactored version bump, Docker publish, and PyPI publish workflows into a unified release pipeline that runs sequentially. Created reusable composite actions for Docker and PyPI publishing to eliminate duplication. Changes: - Rename bump-version.yml to release.yml with three jobs: bump, publish_docker, publish_pypi - Create .github/actions/publish-docker/action.yml with configurable inputs for image, version, branchmain
parent
85198a07ea
commit
41664178aa
|
|
@ -0,0 +1,111 @@
|
||||||
|
name: Publish Docker image
|
||||||
|
description: Build and push the Docker image to Docker Hub
|
||||||
|
inputs:
|
||||||
|
docker_username:
|
||||||
|
required: true
|
||||||
|
description: Docker Hub username
|
||||||
|
docker_password:
|
||||||
|
required: true
|
||||||
|
description: Docker Hub password
|
||||||
|
image:
|
||||||
|
required: true
|
||||||
|
description: Docker image name (e.g. user/repo)
|
||||||
|
version:
|
||||||
|
required: false
|
||||||
|
default: ""
|
||||||
|
description: Optional version string (e.g. 1.2.3). If provided, tags are computed from this version instead of the GitHub ref.
|
||||||
|
include_branch_tags:
|
||||||
|
required: false
|
||||||
|
default: "true"
|
||||||
|
description: Whether to also publish a branch tag when running on a branch ref (e.g. manual runs).
|
||||||
|
context:
|
||||||
|
required: false
|
||||||
|
default: .
|
||||||
|
description: Docker build context
|
||||||
|
dockerfile:
|
||||||
|
required: false
|
||||||
|
default: Server/Dockerfile
|
||||||
|
description: Path to Dockerfile
|
||||||
|
platforms:
|
||||||
|
required: false
|
||||||
|
default: linux/amd64
|
||||||
|
description: Target platforms
|
||||||
|
runs:
|
||||||
|
using: composite
|
||||||
|
steps:
|
||||||
|
- name: Log in to Docker Hub
|
||||||
|
uses: docker/login-action@v3
|
||||||
|
with:
|
||||||
|
username: ${{ inputs.docker_username }}
|
||||||
|
password: ${{ inputs.docker_password }}
|
||||||
|
|
||||||
|
- name: Extract metadata (tags, labels) for Docker
|
||||||
|
id: meta
|
||||||
|
uses: docker/metadata-action@v5
|
||||||
|
if: ${{ inputs.version == '' && inputs.include_branch_tags == 'true' }}
|
||||||
|
with:
|
||||||
|
images: ${{ inputs.image }}
|
||||||
|
tags: |
|
||||||
|
type=semver,pattern={{version}}
|
||||||
|
type=semver,pattern={{major}}.{{minor}}
|
||||||
|
type=semver,pattern={{major}}
|
||||||
|
type=ref,event=branch
|
||||||
|
|
||||||
|
- name: Extract metadata (tags, labels) for Docker
|
||||||
|
id: meta_nobranch
|
||||||
|
uses: docker/metadata-action@v5
|
||||||
|
if: ${{ inputs.version == '' && inputs.include_branch_tags != 'true' }}
|
||||||
|
with:
|
||||||
|
images: ${{ inputs.image }}
|
||||||
|
tags: |
|
||||||
|
type=semver,pattern={{version}}
|
||||||
|
type=semver,pattern={{major}}.{{minor}}
|
||||||
|
type=semver,pattern={{major}}
|
||||||
|
|
||||||
|
- name: Compute Docker tags from version
|
||||||
|
id: version_tags
|
||||||
|
if: ${{ inputs.version != '' }}
|
||||||
|
shell: bash
|
||||||
|
run: |
|
||||||
|
set -euo pipefail
|
||||||
|
IFS='.' read -r MA MI PA <<< "${{ inputs.version }}"
|
||||||
|
echo "major=$MA" >> "$GITHUB_OUTPUT"
|
||||||
|
echo "minor=$MI" >> "$GITHUB_OUTPUT"
|
||||||
|
|
||||||
|
- name: Extract metadata (tags, labels) for Docker
|
||||||
|
id: meta_version
|
||||||
|
uses: docker/metadata-action@v5
|
||||||
|
if: ${{ inputs.version != '' && inputs.include_branch_tags == 'true' }}
|
||||||
|
with:
|
||||||
|
images: ${{ inputs.image }}
|
||||||
|
tags: |
|
||||||
|
type=raw,value=v${{ inputs.version }}
|
||||||
|
type=raw,value=v${{ steps.version_tags.outputs.major }}.${{ steps.version_tags.outputs.minor }}
|
||||||
|
type=raw,value=v${{ steps.version_tags.outputs.major }}
|
||||||
|
type=ref,event=branch
|
||||||
|
|
||||||
|
- name: Extract metadata (tags, labels) for Docker
|
||||||
|
id: meta_version_nobranch
|
||||||
|
uses: docker/metadata-action@v5
|
||||||
|
if: ${{ inputs.version != '' && inputs.include_branch_tags != 'true' }}
|
||||||
|
with:
|
||||||
|
images: ${{ inputs.image }}
|
||||||
|
tags: |
|
||||||
|
type=raw,value=v${{ inputs.version }}
|
||||||
|
type=raw,value=v${{ steps.version_tags.outputs.major }}.${{ steps.version_tags.outputs.minor }}
|
||||||
|
type=raw,value=v${{ steps.version_tags.outputs.major }}
|
||||||
|
|
||||||
|
- name: Set up Docker Buildx
|
||||||
|
uses: docker/setup-buildx-action@v3
|
||||||
|
|
||||||
|
- name: Build and push Docker image
|
||||||
|
uses: docker/build-push-action@v6
|
||||||
|
with:
|
||||||
|
context: ${{ inputs.context }}
|
||||||
|
file: ${{ inputs.dockerfile }}
|
||||||
|
platforms: ${{ inputs.platforms }}
|
||||||
|
push: true
|
||||||
|
tags: ${{ steps.meta.outputs.tags || steps.meta_nobranch.outputs.tags || steps.meta_version.outputs.tags || steps.meta_version_nobranch.outputs.tags }}
|
||||||
|
labels: ${{ steps.meta.outputs.labels || steps.meta_nobranch.outputs.labels || steps.meta_version.outputs.labels || steps.meta_version_nobranch.outputs.labels }}
|
||||||
|
cache-from: type=gha
|
||||||
|
cache-to: type=gha,mode=max
|
||||||
|
|
@ -0,0 +1,21 @@
|
||||||
|
name: Publish Python distribution to PyPI
|
||||||
|
description: Build and publish the Python package from Server/ to PyPI
|
||||||
|
runs:
|
||||||
|
using: composite
|
||||||
|
steps:
|
||||||
|
- name: Install uv
|
||||||
|
uses: astral-sh/setup-uv@v7
|
||||||
|
with:
|
||||||
|
version: "latest"
|
||||||
|
enable-cache: true
|
||||||
|
cache-dependency-glob: "Server/uv.lock"
|
||||||
|
|
||||||
|
- name: Build a binary wheel and a source tarball
|
||||||
|
shell: bash
|
||||||
|
run: uv build
|
||||||
|
working-directory: ./Server
|
||||||
|
|
||||||
|
- name: Publish distribution to PyPI
|
||||||
|
uses: pypa/gh-action-pypi-publish@release/v1
|
||||||
|
with:
|
||||||
|
packages-dir: Server/dist/
|
||||||
|
|
@ -1,47 +0,0 @@
|
||||||
name: Publish Docker image 🐳
|
|
||||||
|
|
||||||
on:
|
|
||||||
push:
|
|
||||||
tags:
|
|
||||||
- "*"
|
|
||||||
workflow_dispatch:
|
|
||||||
jobs:
|
|
||||||
push_to_registry:
|
|
||||||
name: Push Docker image to Docker Hub
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
|
|
||||||
steps:
|
|
||||||
- name: Check out the repo
|
|
||||||
uses: actions/checkout@v6
|
|
||||||
|
|
||||||
- name: Log in to Docker Hub
|
|
||||||
uses: docker/login-action@v3
|
|
||||||
with:
|
|
||||||
username: ${{ secrets.DOCKER_USERNAME }}
|
|
||||||
password: ${{ secrets.DOCKER_PASSWORD }}
|
|
||||||
|
|
||||||
- name: Extract metadata (tags, labels) for Docker
|
|
||||||
id: meta
|
|
||||||
uses: docker/metadata-action@v5
|
|
||||||
with:
|
|
||||||
images: ${{ secrets.DOCKER_USERNAME }}/mcp-for-unity-server
|
|
||||||
tags: |
|
|
||||||
type=semver,pattern={{version}}
|
|
||||||
type=semver,pattern={{major}}.{{minor}}
|
|
||||||
type=ref,event=branch
|
|
||||||
type=sha
|
|
||||||
|
|
||||||
- name: Set up Docker Buildx
|
|
||||||
uses: docker/setup-buildx-action@v3
|
|
||||||
|
|
||||||
- name: Build and push Docker image
|
|
||||||
uses: docker/build-push-action@v6
|
|
||||||
with:
|
|
||||||
context: .
|
|
||||||
file: Server/Dockerfile
|
|
||||||
platforms: linux/amd64
|
|
||||||
push: true
|
|
||||||
tags: ${{ steps.meta.outputs.tags }}
|
|
||||||
labels: ${{ steps.meta.outputs.labels }}
|
|
||||||
cache-from: type=gha
|
|
||||||
cache-to: type=gha,mode=max
|
|
||||||
|
|
@ -1,55 +0,0 @@
|
||||||
name: Publish Python 🐍 distribution 📦 to PyPI
|
|
||||||
|
|
||||||
on:
|
|
||||||
push:
|
|
||||||
tags:
|
|
||||||
- "*"
|
|
||||||
workflow_dispatch:
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
build:
|
|
||||||
name: Build distribution 📦
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
defaults:
|
|
||||||
run:
|
|
||||||
working-directory: ./Server
|
|
||||||
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v6
|
|
||||||
|
|
||||||
- name: Install uv
|
|
||||||
uses: astral-sh/setup-uv@v7
|
|
||||||
with:
|
|
||||||
version: "latest"
|
|
||||||
enable-cache: true
|
|
||||||
cache-dependency-glob: "Server/uv.lock"
|
|
||||||
|
|
||||||
- name: Build a binary wheel and a source tarball
|
|
||||||
run: uv build
|
|
||||||
|
|
||||||
- name: Store the distribution packages
|
|
||||||
uses: actions/upload-artifact@v6
|
|
||||||
with:
|
|
||||||
name: python-package-distributions
|
|
||||||
path: Server/dist/
|
|
||||||
|
|
||||||
publish-to-pypi:
|
|
||||||
name: >-
|
|
||||||
Publish Python 🐍 distribution 📦 to PyPI
|
|
||||||
needs:
|
|
||||||
- build
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
environment:
|
|
||||||
name: pypi
|
|
||||||
url: https://pypi.org/p/mcpforunityserver
|
|
||||||
permissions:
|
|
||||||
id-token: write
|
|
||||||
|
|
||||||
steps:
|
|
||||||
- name: Download all the dists
|
|
||||||
uses: actions/download-artifact@v7
|
|
||||||
with:
|
|
||||||
name: python-package-distributions
|
|
||||||
path: dist/
|
|
||||||
- name: Publish distribution 📦 to PyPI
|
|
||||||
uses: pypa/gh-action-pypi-publish@release/v1
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
name: Bump Version
|
name: Release
|
||||||
|
|
||||||
on:
|
on:
|
||||||
workflow_dispatch:
|
workflow_dispatch:
|
||||||
|
|
@ -15,13 +15,16 @@ on:
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
bump:
|
bump:
|
||||||
name: "Bump version and tag"
|
name: Bump version, tag, and create release
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
permissions:
|
permissions:
|
||||||
contents: write
|
contents: write
|
||||||
|
outputs:
|
||||||
|
new_version: ${{ steps.compute.outputs.new_version }}
|
||||||
|
tag: ${{ steps.tag.outputs.tag }}
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout repository
|
- name: Checkout repository
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v6
|
||||||
with:
|
with:
|
||||||
fetch-depth: 0
|
fetch-depth: 0
|
||||||
|
|
||||||
|
|
@ -56,6 +59,15 @@ jobs:
|
||||||
echo "new_version=$NEW_VERSION" >> "$GITHUB_OUTPUT"
|
echo "new_version=$NEW_VERSION" >> "$GITHUB_OUTPUT"
|
||||||
echo "current_version=$CURRENT_VERSION" >> "$GITHUB_OUTPUT"
|
echo "current_version=$CURRENT_VERSION" >> "$GITHUB_OUTPUT"
|
||||||
|
|
||||||
|
- name: Compute tag
|
||||||
|
id: tag
|
||||||
|
env:
|
||||||
|
NEW_VERSION: ${{ steps.compute.outputs.new_version }}
|
||||||
|
shell: bash
|
||||||
|
run: |
|
||||||
|
set -euo pipefail
|
||||||
|
echo "tag=v${NEW_VERSION}" >> "$GITHUB_OUTPUT"
|
||||||
|
|
||||||
- name: Update files to new version
|
- name: Update files to new version
|
||||||
env:
|
env:
|
||||||
NEW_VERSION: ${{ steps.compute.outputs.new_version }}
|
NEW_VERSION: ${{ steps.compute.outputs.new_version }}
|
||||||
|
|
@ -94,11 +106,10 @@ jobs:
|
||||||
|
|
||||||
- name: Create and push tag
|
- name: Create and push tag
|
||||||
env:
|
env:
|
||||||
NEW_VERSION: ${{ steps.compute.outputs.new_version }}
|
TAG: ${{ steps.tag.outputs.tag }}
|
||||||
shell: bash
|
shell: bash
|
||||||
run: |
|
run: |
|
||||||
set -euo pipefail
|
set -euo pipefail
|
||||||
TAG="v${NEW_VERSION}"
|
|
||||||
echo "Preparing to create tag $TAG"
|
echo "Preparing to create tag $TAG"
|
||||||
|
|
||||||
if git ls-remote --tags origin | grep -q "refs/tags/$TAG$"; then
|
if git ls-remote --tags origin | grep -q "refs/tags/$TAG$"; then
|
||||||
|
|
@ -106,19 +117,58 @@ jobs:
|
||||||
exit 0
|
exit 0
|
||||||
fi
|
fi
|
||||||
|
|
||||||
git tag -a "$TAG" -m "Version ${NEW_VERSION}"
|
git tag -a "$TAG" -m "Version ${TAG#v}"
|
||||||
git push origin "$TAG"
|
git push origin "$TAG"
|
||||||
|
|
||||||
- name: Create GitHub release
|
- name: Create GitHub release
|
||||||
env:
|
uses: softprops/action-gh-release@v2
|
||||||
NEW_VERSION: ${{ steps.compute.outputs.new_version }}
|
with:
|
||||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
tag_name: ${{ steps.tag.outputs.tag }}
|
||||||
shell: bash
|
name: ${{ steps.tag.outputs.tag }}
|
||||||
run: |
|
generate_release_notes: true
|
||||||
set -euo pipefail
|
|
||||||
TAG="v${NEW_VERSION}"
|
|
||||||
|
|
||||||
# Create release with auto-generated notes
|
publish_docker:
|
||||||
gh release create "$TAG" \
|
name: Publish Docker image
|
||||||
--title "v${NEW_VERSION}" \
|
needs:
|
||||||
--generate-notes
|
- bump
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
permissions:
|
||||||
|
contents: read
|
||||||
|
steps:
|
||||||
|
- name: Check out the repo
|
||||||
|
uses: actions/checkout@v6
|
||||||
|
with:
|
||||||
|
ref: ${{ needs.bump.outputs.tag }}
|
||||||
|
fetch-depth: 0
|
||||||
|
|
||||||
|
- name: Build and push Docker image
|
||||||
|
uses: ./.github/actions/publish-docker
|
||||||
|
with:
|
||||||
|
docker_username: ${{ secrets.DOCKER_USERNAME }}
|
||||||
|
docker_password: ${{ secrets.DOCKER_PASSWORD }}
|
||||||
|
image: ${{ secrets.DOCKER_USERNAME }}/mcp-for-unity-server
|
||||||
|
version: ${{ needs.bump.outputs.new_version }}
|
||||||
|
include_branch_tags: "false"
|
||||||
|
context: .
|
||||||
|
dockerfile: Server/Dockerfile
|
||||||
|
platforms: linux/amd64
|
||||||
|
|
||||||
|
publish_pypi:
|
||||||
|
name: Publish Python distribution to PyPI
|
||||||
|
needs:
|
||||||
|
- bump
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
environment:
|
||||||
|
name: pypi
|
||||||
|
url: https://pypi.org/p/mcpforunityserver
|
||||||
|
permissions:
|
||||||
|
contents: read
|
||||||
|
id-token: write
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v6
|
||||||
|
with:
|
||||||
|
ref: ${{ needs.bump.outputs.tag }}
|
||||||
|
fetch-depth: 0
|
||||||
|
|
||||||
|
- name: Build and publish
|
||||||
|
uses: ./.github/actions/publish-pypi
|
||||||
Loading…
Reference in New Issue