name: Frontend Release (reusable) # Pipeline di release per frontend Angular containerizzati con nginx. # Speculare a maven-release.yml ma per il mondo FE: # - versionamento su package.json (source of truth), flusso -SNAPSHOT come maven # - UNA sola immagine env-agnostic (i puntamenti per-ambiente vivono nelle # env var del docker-compose, applicate a runtime da nginx via envsubst) # - push su registry artifacts.biters.it:8443/biters/: # - tag + release Gitea, bump SNAPSHOT, rebase develop, update compose repos # # Requisiti runner: deve avere Docker (buildx) disponibile + jq/curl/git. on: workflow_call: inputs: compose-repos: description: "Repo docker-compose da aggiornare, separati da virgola (es. Biters/bitwork). Vuoto = skip." required: false type: string default: "" docker-registry: description: "Registry Docker." required: false type: string default: "artifacts.biters.it:8443" build-config: description: "Configurazione Angular da buildare (deve essere env-agnostic)." required: false type: string default: "prod" jobs: release: runs-on: ubuntu-latest env: MAVEN_USERNAME: ${{ secrets.MAVEN_USERNAME }} MAVEN_PASSWORD: ${{ secrets.MAVEN_PASSWORD }} GITEA_TOKEN: ${{ secrets.REPO_ACCESS_TOKEN }} REGISTRY: ${{ inputs.docker-registry }} BUILD_CONFIG: ${{ inputs.build-config }} steps: # ── Bootstrap ────────────────────────────────────────────── - uses: actions/checkout@v6 with: fetch-depth: 0 - name: Verifica tooling e configurazione run: | missing=0 for v in MAVEN_USERNAME MAVEN_PASSWORD GITEA_TOKEN; do eval "val=\${$v}" if [ -z "$val" ]; then echo "MANCANTE: $v"; missing=1; else echo "OK: $v"; fi done [ "$missing" -eq 0 ] || { echo "Imposta le Secrets mancanti a livello org."; exit 1; } # Tool richiesti sul runner command -v docker >/dev/null 2>&1 || { echo "ERRORE: docker non disponibile sul runner."; exit 1; } command -v jq >/dev/null 2>&1 || { echo "ERRORE: jq non disponibile sul runner."; exit 1; } docker buildx version >/dev/null 2>&1 || { echo "ERRORE: docker buildx non disponibile."; exit 1; } - name: Configura git run: | git config user.name "CI Release Bot" git config user.email "ci@biters.it" git remote set-url origin "https://biters.gitea:${GITEA_TOKEN}@git.biters.it/${{ github.repository }}.git" # ── Versione ─────────────────────────────────────────────── - name: Promuovi a release (rimuovi -SNAPSHOT) id: version run: | CURRENT=$(jq -r '.version' package.json) RELEASE_VERSION="${CURRENT%-SNAPSHOT}" PROJECT_NAME=$(jq -r '.name' package.json) # Scrive la versione di release nel package.json jq --arg v "$RELEASE_VERSION" '.version=$v' package.json > package.json.tmp mv package.json.tmp package.json MAJOR=$(echo "$RELEASE_VERSION" | cut -d. -f1) MINOR=$(echo "$RELEASE_VERSION" | cut -d. -f2) PATCH=$(echo "$RELEASE_VERSION" | cut -d. -f3) NEXT_VERSION="$MAJOR.$MINOR.$((PATCH + 1))-SNAPSHOT" echo "RELEASE_VERSION=$RELEASE_VERSION" >> "$GITHUB_OUTPUT" echo "PROJECT_NAME=$PROJECT_NAME" >> "$GITHUB_OUTPUT" echo "NEXT_VERSION=$NEXT_VERSION" >> "$GITHUB_OUTPUT" echo "── Riepilogo ──" echo " project : $PROJECT_NAME" echo " release : $RELEASE_VERSION" echo " next : $NEXT_VERSION" # ── Check registry ───────────────────────────────────────── - name: Verifica che il tag immagine non esista già run: | VERSION="${{ steps.version.outputs.RELEASE_VERSION }}" NAME="${{ steps.version.outputs.PROJECT_NAME }}" HTTP_CODE=$(curl -s -o /dev/null -w "%{http_code}" \ -u "$MAVEN_USERNAME:$MAVEN_PASSWORD" \ -H "Accept: application/vnd.docker.distribution.manifest.v2+json" \ "https://${REGISTRY}/v2/biters/${NAME}/manifests/${VERSION}") if [ "$HTTP_CODE" = "200" ]; then echo "ERRORE: l'immagine biters/${NAME}:${VERSION} esiste già sul registry!" exit 1 fi echo "OK: tag ${VERSION} non presente (HTTP $HTTP_CODE)" # ── Build & Push ─────────────────────────────────────────── - name: Docker login run: echo "$MAVEN_PASSWORD" | docker login "$REGISTRY" -u "$MAVEN_USERNAME" --password-stdin - name: Build + Push immagine run: | VERSION="${{ steps.version.outputs.RELEASE_VERSION }}" NAME="${{ steps.version.outputs.PROJECT_NAME }}" IMAGE="${REGISTRY}/biters/${NAME}:${VERSION}" docker buildx build \ --build-arg VERSION="${VERSION}" \ --build-arg BUILD_CONFIG="${BUILD_CONFIG}" \ -t "${IMAGE}" \ --push \ . echo "Immagine pubblicata: ${IMAGE}" # ── Tag & Bump ───────────────────────────────────────────── - name: Commit release e tag run: | VERSION="${{ steps.version.outputs.RELEASE_VERSION }}" git add package.json git commit -m "release: ${VERSION} [skip ci]" git tag -a "${VERSION}" -m "Release ${VERSION}" - name: Avanza a prossima versione SNAPSHOT run: | NEXT="${{ steps.version.outputs.NEXT_VERSION }}" jq --arg v "$NEXT" '.version=$v' package.json > package.json.tmp mv package.json.tmp package.json git add package.json git commit -m "chore: avanza versione a ${NEXT} [skip ci]" - name: Push release + tag + versione successiva run: | VERSION="${{ steps.version.outputs.RELEASE_VERSION }}" git push origin HEAD "${VERSION}" # ── Gitea Release ────────────────────────────────────────── - name: Crea release su Gitea run: | VERSION="${{ steps.version.outputs.RELEASE_VERSION }}" NAME="${{ steps.version.outputs.PROJECT_NAME }}" DOCKER_IMAGE="${REGISTRY}/biters/${NAME}:${VERSION}" BODY="## Artifacts - **Docker**: \`${DOCKER_IMAGE}\`" curl -s -X POST \ -H "Authorization: token ${GITEA_TOKEN}" \ -H "Content-Type: application/json" \ "https://git.biters.it/api/v1/repos/${{ github.repository }}/releases" \ -d "$(jq -n \ --arg tag "$VERSION" \ --arg name "v${VERSION}" \ --arg body "$BODY" \ '{tag_name: $tag, name: $name, body: $body, draft: false, prerelease: false}')" # ── Rebase develop ───────────────────────────────────────── - name: Rebase develop su ${{ github.ref_name }} run: | if git ls-remote --exit-code --heads origin develop >/dev/null 2>&1; then git fetch origin develop git checkout develop git rebase origin/${{ github.ref_name }} git push origin develop --force-with-lease else echo "Branch develop assente: skip rebase." fi # ── Aggiorna docker-compose (opzionale, multi-repo) ──────── - name: Aggiorna docker-compose nei repo compose if: ${{ inputs.compose-repos != '' }} run: | VERSION="${{ steps.version.outputs.RELEASE_VERSION }}" PROJECT_NAME="${{ steps.version.outputs.PROJECT_NAME }}" ESCAPED_REGISTRY=$(echo "$REGISTRY" | sed 's/\./\\./g') echo "${{ inputs.compose-repos }}" | tr ',' '\n' | while IFS= read -r COMPOSE_REPO; do COMPOSE_REPO=$(echo "$COMPOSE_REPO" | xargs) [ -z "$COMPOSE_REPO" ] && continue REPO_DIR="/tmp/compose-$(echo "$COMPOSE_REPO" | tr '/' '-')" echo "" echo "════════════════════════════════════════" echo " Repo: ${COMPOSE_REPO}" echo "════════════════════════════════════════" git clone "https://biters.gitea:${GITEA_TOKEN}@git.biters.it/${COMPOSE_REPO}.git" "$REPO_DIR" cd "$REPO_DIR" git config user.name "CI Release Bot" git config user.email "ci@biters.it" find . -name 'docker-compose*.yml' -exec \ sed -i "s|\(${ESCAPED_REGISTRY}/biters/${PROJECT_NAME}:\)[^ \"']*|\1${VERSION}|g" {} + if git diff --quiet; then echo " Nessuna modifica necessaria" else git add -A git commit -m "chore(${PROJECT_NAME}): aggiorna immagine a ${VERSION}" git push origin HEAD echo " Docker-compose aggiornati a ${VERSION}" fi cd "$GITHUB_WORKSPACE" done