diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml new file mode 100644 index 0000000..9dfd7c8 --- /dev/null +++ b/.github/workflows/publish.yml @@ -0,0 +1,50 @@ +name: publish +run-name: Publish ${{ github.ref_name }} + +on: + release: + types: [published] + +jobs: + mapache-py: + runs-on: ubuntu-latest + defaults: + run: + working-directory: mapache-py + steps: + - uses: actions/checkout@v4 + + - uses: actions/setup-python@v5 + with: + python-version: "3.13" + + - name: Install build tools + run: pip install build twine + + - name: Build + run: python -m build + + - name: Publish to PyPI + run: twine upload dist/* + env: + TWINE_USERNAME: __token__ + TWINE_PASSWORD: ${{ secrets.PYPI_API_TOKEN }} + + mapache-go: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - uses: actions/setup-go@v5 + with: + go-version: "1.26" + + - name: Create Go module tag + run: | + VERSION="${GITHUB_REF_NAME}" + GO_TAG="mapache-go/${VERSION}" + git tag "$GO_TAG" + git push origin "$GO_TAG" + + - name: Warm Go module proxy + run: GOPROXY=proxy.golang.org go list -m "github.com/gaucho-racing/mapache/mapache-go@${GITHUB_REF_NAME}" diff --git a/scripts/release.sh b/scripts/release.sh new file mode 100755 index 0000000..d9202e5 --- /dev/null +++ b/scripts/release.sh @@ -0,0 +1,101 @@ +#!/usr/bin/env bash +set -euo pipefail + +if ! command -v gh &> /dev/null; then + echo "Error: gh CLI is required (https://cli.github.com)" + exit 1 +fi + +BRANCH=$(git rev-parse --abbrev-ref HEAD) +if [[ "$BRANCH" != "main" ]]; then + echo "Error: must be on main branch (currently on $BRANCH)" + exit 1 +fi + +git fetch origin main --tags --quiet +LOCAL=$(git rev-parse HEAD) +REMOTE=$(git rev-parse origin/main) +if [[ "$LOCAL" != "$REMOTE" ]]; then + echo "Error: local main is not up to date with origin/main" + echo " local: $LOCAL" + echo " remote: $REMOTE" + echo "Run 'git pull' first." + exit 1 +fi + +PREV_TAG=$(gh release list --limit 1 --json tagName --jq '.[0].tagName' 2>/dev/null || true) + +echo "" +if [[ -n "$PREV_TAG" ]]; then + echo "Current release: $PREV_TAG" +else + echo "Current release: (none)" +fi +echo "" +read -rp "Enter new version: " INPUT + +if [[ -z "$INPUT" ]]; then + echo "Error: version cannot be empty" + exit 1 +fi + +INPUT="${INPUT#v}" +if [[ ! "$INPUT" =~ ^[0-9]+\.[0-9]+\.[0-9]+$ ]]; then + echo "Error: version must be a valid semver (e.g. 1.5.0)" + exit 1 +fi +VERSION="v${INPUT}" + +if git tag -l "$VERSION" | grep -q "^${VERSION}$"; then + echo "Error: tag $VERSION already exists" + exit 1 +fi + +SEMVER="${VERSION#v}" +SERVICES=("auth" "gr26" "vehicle") +CONFIG_FILES=() +for svc in "${SERVICES[@]}"; do + CONFIG_FILES+=("${svc}/config/config.go") +done + +echo "" +echo "=== Release Summary ===" +echo " Version: $VERSION" +echo " Commit: $(git rev-parse --short HEAD)" +echo " Branch: main" +echo "" +echo " Files to update:" +for f in "${CONFIG_FILES[@]}"; do + echo " $f" +done +echo " mapache-py/pyproject.toml" +echo "" +echo " Docker images that will be tagged:" +for svc in "${SERVICES[@]}"; do + echo " ghcr.io/gaucho-racing/mapache/${svc}:${VERSION}" +done +echo "" +read -rp "Proceed? (y/N) " CONFIRM +if [[ "$CONFIRM" != "y" && "$CONFIRM" != "Y" ]]; then + echo "Aborted." + exit 0 +fi + +REPO_ROOT=$(git rev-parse --show-toplevel) +for f in "${CONFIG_FILES[@]}"; do + sed -i '' "s/Version:.*\".*\"/Version: \"${SEMVER}\"/" "${REPO_ROOT}/${f}" +done +sed -i '' "s/^version = \".*\"/version = \"${SEMVER}\"/" "${REPO_ROOT}/mapache-py/pyproject.toml" + +git add "${CONFIG_FILES[@]}" mapache-py/pyproject.toml +git commit -m "release: ${VERSION}" +git push origin main + +gh release create "$VERSION" \ + --target main \ + --title "$VERSION" \ + --generate-notes + +echo "" +echo "Release $VERSION created successfully." +echo "CI workflows will tag Docker images once builds complete."