name: https://github.com/AIIrondev/legendary-octo-garbanzo on: push: tags: - "v*" workflow_dispatch: inputs: bump: description: "Version bump type (major stays fixed from latest release)" required: false default: "patch" type: choice options: - patch - minor permissions: contents: write packages: write env: FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: "true" jobs: release-docker: runs-on: ubuntu-latest steps: - name: Checkout uses: actions/checkout@v4 - name: Set metadata id: meta env: GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} REPO: ${{ github.repository }} EVENT_NAME: ${{ github.event_name }} REF_NAME: ${{ github.ref_name }} BUMP_TYPE: ${{ github.event.inputs.bump || 'patch' }} run: | if [ "$EVENT_NAME" = "push" ] && [ -n "$REF_NAME" ]; then TAG="$REF_NAME" else TAG="$(python3 - <<'PY' import json import os import re import urllib.request repo = os.environ["REPO"] token = os.environ.get("GH_TOKEN", "") bump = os.environ.get("BUMP_TYPE", "patch").strip().lower() req = urllib.request.Request( f"https://api.github.com/repos/{repo}/releases/latest", headers={ "Authorization": f"Bearer {token}", "Accept": "application/vnd.github+json", "User-Agent": "legendary-octo-garbanzo-release-workflow", }, ) latest_tag = "v3.0.0" try: with urllib.request.urlopen(req, timeout=20) as resp: data = json.loads(resp.read().decode("utf-8")) latest_tag = (data.get("tag_name") or latest_tag).strip() except Exception: pass m = re.match(r"^v(\d+)\.(\d+)\.(\d+)$", latest_tag) if not m: major, minor, patch = 3, 0, 0 else: major, minor, patch = map(int, m.groups()) # Keep major fixed from latest release; only bump minor/patch. if bump == "minor": minor += 1 patch = 0 else: patch += 1 print(f"v{major}.{minor}.{patch}") PY )" fi if ! echo "$TAG" | grep -Eq '^v[0-9]+\.[0-9]+\.[0-9]+$'; then echo "Error: tag '$TAG' is not valid semver (vX.Y.Z)" exit 1 fi git fetch --tags --force LATEST_TAG="$(git tag -l 'v*' | grep -E '^v[0-9]+\.[0-9]+\.[0-9]+$' | sort -V | tail -n1)" if [ -z "$LATEST_TAG" ]; then LATEST_TAG="v3.0.0" fi TAG_MAJOR="${TAG#v}" TAG_MAJOR="${TAG_MAJOR%%.*}" LATEST_MAJOR="$(echo "$LATEST_TAG" | grep -Eo '^v[0-9]+' | tr -d 'v')" if [ -z "$LATEST_MAJOR" ]; then LATEST_MAJOR="3" fi if [ "$TAG_MAJOR" != "$LATEST_MAJOR" ]; then echo "Error: major version must stay v$LATEST_MAJOR.x.x (got $TAG)" exit 1 fi while git rev-parse -q --verify "refs/tags/$TAG" >/dev/null; do BASE="${TAG%.*}" PATCH="${TAG##*.}" PATCH="$((PATCH + 1))" TAG="$BASE.$PATCH" done IMAGE="ghcr.io/aiirondev/legendary-octo-garbanzo:${TAG}" echo "tag=$TAG" >> "$GITHUB_OUTPUT" echo "image=$IMAGE" >> "$GITHUB_OUTPUT" - name: Create and push tag for manual releases if: github.event_name == 'workflow_dispatch' run: | TAG="${{ steps.meta.outputs.tag }}" git config user.name "github-actions[bot]" git config user.email "github-actions[bot]@users.noreply.github.com" git tag "$TAG" git push origin "$TAG" - name: Set up Docker Buildx uses: docker/setup-buildx-action@v3 - name: Login to GHCR uses: docker/login-action@v3 with: registry: ghcr.io username: ${{ github.actor }} password: ${{ secrets.GITHUB_TOKEN }} - name: Build and push release image uses: docker/build-push-action@v6 with: context: . file: ./Dockerfile push: true tags: | ${{ steps.meta.outputs.image }} ghcr.io/aiirondev/legendary-octo-garbanzo:latest - name: Build and push development image uses: docker/build-push-action@v6 with: context: . file: ./Dockerfile push: true tags: | ghcr.io/aiirondev/legendary-octo-garbanzo:development - name: Build local image tar for offline deploy run: | docker pull "${{ steps.meta.outputs.image }}" docker save "${{ steps.meta.outputs.image }}" | gzip > "inventarsystem-image-${{ steps.meta.outputs.tag }}.tar.gz" - name: Build local development image tar for offline deploy run: | docker pull ghcr.io/aiirondev/legendary-octo-garbanzo:development || true docker save ghcr.io/aiirondev/legendary-octo-garbanzo:development | gzip > "inventarsystem-image-development.tar.gz" || true - name: Create release-only docker bundle run: | mkdir -p release-bundle cat > release-bundle/docker-compose.yml < release-bundle/DEVELOPMENT.md <<'EOF' This bundle contains an optional development image tar: inventarsystem-image-development.tar.gz To install the development build on a target host, extract the bundle and run: ./update.sh development EOF chmod +x release-bundle/start.sh release-bundle/stop.sh release-bundle/restart.sh release-bundle/backup.sh release-bundle/update.sh release-bundle/manage-tenant.sh release-bundle/run-tenant-cmd.sh tar -czf inventarsystem-docker-bundle.tar.gz -C release-bundle . - name: Create or update GitHub Release uses: softprops/action-gh-release@v2 with: tag_name: ${{ steps.meta.outputs.tag }} files: | inventarsystem-docker-bundle.tar.gz inventarsystem-image-${{ steps.meta.outputs.tag }}.tar.gz inventarsystem-image-development.tar.gz fail_on_unmatched_files: false generate_release_notes: true