14c4192306
Co-authored-by: Copilot <copilot@github.com>
254 lines
8.4 KiB
YAML
254 lines
8.4 KiB
YAML
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 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: Create release-only docker bundle
|
|
run: |
|
|
mkdir -p release-bundle
|
|
cat > release-bundle/docker-compose.yml <<EOF
|
|
services:
|
|
app:
|
|
image: ${INVENTAR_APP_IMAGE:-ghcr.io/aiirondev/legendary-octo-garbanzo:${{ steps.meta.outputs.tag }}}
|
|
container_name: inventarsystem-app
|
|
restart: unless-stopped
|
|
ports:
|
|
- "${INVENTAR_HTTP_PORT:-10000}:8000"
|
|
depends_on:
|
|
- mongodb
|
|
- redis
|
|
environment:
|
|
INVENTAR_MONGODB_HOST: mongodb
|
|
INVENTAR_MONGODB_PORT: "27017"
|
|
INVENTAR_MONGODB_DB: Inventarsystem
|
|
INVENTAR_BACKUP_FOLDER: /data/backups
|
|
INVENTAR_LOGS_FOLDER: /data/logs
|
|
expose:
|
|
- "8000"
|
|
volumes:
|
|
- ./config.json:/app/config.json:ro
|
|
- app_uploads:/app/Web/uploads
|
|
- app_thumbnails:/app/Web/thumbnails
|
|
- app_previews:/app/Web/previews
|
|
- app_qrcodes:/app/Web/QRCodes
|
|
- app_backups:/data/backups
|
|
- app_logs:/data/logs
|
|
|
|
mongodb:
|
|
image: mongo:7.0
|
|
container_name: inventarsystem-mongodb
|
|
restart: unless-stopped
|
|
volumes:
|
|
- mongodb_data:/data/db
|
|
healthcheck:
|
|
test: ["CMD", "mongosh", "--quiet", "--eval", "db.adminCommand('ping').ok"]
|
|
interval: 10s
|
|
timeout: 5s
|
|
retries: 10
|
|
|
|
redis:
|
|
image: redis:7-alpine
|
|
container_name: inventarsystem-redis
|
|
restart: unless-stopped
|
|
command: redis-server --appendonly yes --maxmemory 512mb --maxmemory-policy allkeys-lru
|
|
ports:
|
|
- "6379:6379"
|
|
volumes:
|
|
- redis_data:/data
|
|
healthcheck:
|
|
test: ["CMD", "redis-cli", "ping"]
|
|
interval: 10s
|
|
timeout: 5s
|
|
retries: 5
|
|
|
|
volumes:
|
|
mongodb_data:
|
|
app_uploads:
|
|
app_thumbnails:
|
|
app_previews:
|
|
app_qrcodes:
|
|
app_backups:
|
|
app_logs:
|
|
redis_data:
|
|
EOF
|
|
|
|
cp start.sh release-bundle/start.sh
|
|
cp stop.sh release-bundle/stop.sh
|
|
cp restart.sh release-bundle/restart.sh
|
|
cp backup.sh release-bundle/backup.sh
|
|
cp config.json release-bundle/config.json
|
|
cp update.sh release-bundle/update.sh
|
|
cp init-admin.sh release-bundle/init-admin.sh
|
|
|
|
# Multitenant scripts & docs
|
|
cp docker-compose-multitenant.yml release-bundle/docker-compose-multitenant.yml
|
|
cp manage-tenant.sh release-bundle/manage-tenant.sh
|
|
cp run-tenant-cmd.sh release-bundle/run-tenant-cmd.sh
|
|
cp MULTITENANT_DEPLOYMENT.md release-bundle/MULTITENANT_DEPLOYMENT.md
|
|
cp MULTITENANT_PYTHON_API.md release-bundle/MULTITENANT_PYTHON_API.md
|
|
|
|
chmod +x release-bundle/start.sh release-bundle/stop.sh release-bundle/restart.sh release-bundle/backup.sh release-bundle/update.sh release-bundle/init-admin.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
|
|
fail_on_unmatched_files: true
|
|
generate_release_notes: true
|