Files
pipu-music/.gitea/workflows/release.yml
T
mrleo1nidandClaude Opus 5.5 1633b28c1a
ci / contract (сгенерированный код совпадает с openapi.yaml) (push) Successful in 47s
ci / api (push) Successful in 53s
ci / recommender (push) Successful in 37s
ci / ts (packages + web) (push) Successful in 38s
ci / mobile (Metro-бандл Android) (push) Successful in 52s
docs(deploy): add install guide for a domain with HTTPS
- docs/install-guide.md: step-by-step server setup (DNS, Docker, install.sh,
  .env, launch, checks), web and Android client setup, own reverse proxy
  variant, updates, backups and troubleshooting
- deploy/compose.tls.yaml + Caddyfile: optional Caddy with automatic
  Let's Encrypt in front of nginx (enabled via COMPOSE_FILE in .env)
- nginx: honour X-Forwarded-Proto/For from private networks
- .env.example: DOMAIN, ACME_EMAIL, COMPOSE_FILE, bootstrap admin vars
- install.sh: create caddy data dirs; release.yml: ship TLS files as assets
- deployment.md, docs index and README link to the guide

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-20 00:03:26 +03:00

167 lines
7.5 KiB
YAML
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Релиз по тегу vMAJOR.MINOR.PATCH[-rc.N] (docs/ci-cd.md):
# проверки → Docker-образы в Gitea Container Registry → подписанный APK → Gitea Release с ассетами.
#
# Переменные репозитория (Settings → Actions → Variables):
# REGISTRY — хост реестра, например git.home.lan (по умолчанию — хост сервера Gitea)
# Секреты (Settings → Actions → Secrets):
# REGISTRY_USER, REGISTRY_TOKEN — push образов (scope: write:package)
# RELEASE_TOKEN — создание релиза и загрузка ассетов (scope: write:repository)
# ANDROID_KEYSTORE_BASE64, ANDROID_KEYSTORE_PASSWORD, ANDROID_KEY_ALIAS, ANDROID_KEY_PASSWORD — подпись APK
name: release
on:
push:
tags: ["v*.*.*"]
env:
GO_VERSION: "1.24"
NODE_VERSION: "22"
jobs:
verify:
runs-on: ubuntu-latest
outputs:
version: ${{ steps.v.outputs.PIPU_VERSION }}
version_code: ${{ steps.v.outputs.PIPU_VERSION_CODE }}
prerelease: ${{ steps.v.outputs.PIPU_PRERELEASE }}
steps:
- uses: actions/checkout@v4
- id: v
run: node scripts/version.mjs "${GITHUB_REF_NAME}" | tee -a "$GITHUB_OUTPUT"
- uses: actions/setup-go@v5
with: { go-version: "${{ env.GO_VERSION }}", cache-dependency-path: services/api/go.sum }
- uses: astral-sh/setup-uv@v6
with: { version: "0.10.2" }
- uses: pnpm/action-setup@v4
- uses: actions/setup-node@v4
with: { node-version: "${{ env.NODE_VERSION }}", cache: pnpm }
- run: pnpm install --frozen-lockfile
- name: Go
working-directory: services/api
run: go vet ./... && go test ./...
- name: Python
working-directory: services/recommender
run: uv sync --frozen && uv run ruff check . && uv run mypy pipu_rec && uv run pytest -q
- name: TypeScript
run: pnpm i18n:check && pnpm test:scripts && pnpm typecheck && pnpm test
images:
needs: verify
runs-on: ubuntu-latest
strategy:
fail-fast: true
matrix:
include:
- { name: api, dockerfile: services/api/Dockerfile, target: api }
- { name: storage-agent, dockerfile: services/api/Dockerfile, target: storage-agent }
- { name: recommender, dockerfile: services/recommender/Dockerfile, target: "" }
- { name: web, dockerfile: apps/web/Dockerfile, target: "" }
steps:
- uses: actions/checkout@v4
- name: Имя образа
id: img
run: |
registry="${{ vars.REGISTRY }}"
[ -n "$registry" ] || registry="$(echo '${{ github.server_url }}' | sed -E 's#^https?://##')"
owner="$(echo '${{ github.repository_owner }}' | tr '[:upper:]' '[:lower:]')"
echo "registry=$registry" >> "$GITHUB_OUTPUT"
echo "image=$registry/$owner/pipu-music-${{ matrix.name }}" >> "$GITHUB_OUTPUT"
- uses: docker/setup-buildx-action@v3
- uses: docker/login-action@v3
with:
registry: ${{ steps.img.outputs.registry }}
username: ${{ secrets.REGISTRY_USER }}
password: ${{ secrets.REGISTRY_TOKEN }}
- uses: docker/build-push-action@v6
with:
context: .
file: ${{ matrix.dockerfile }}
target: ${{ matrix.target }}
push: true
build-args: VERSION=${{ needs.verify.outputs.version }}
tags: |
${{ steps.img.outputs.image }}:${{ needs.verify.outputs.version }}
${{ needs.verify.outputs.prerelease == 'false' && format('{0}:latest', steps.img.outputs.image) || '' }}
android-release:
name: android + release
needs: [verify, images]
runs-on: ubuntu-latest
env:
PIPU_VERSION: ${{ needs.verify.outputs.version }}
PIPU_VERSION_CODE: ${{ needs.verify.outputs.version_code }}
steps:
- uses: actions/checkout@v4
with: { fetch-depth: 0 }
- uses: actions/setup-java@v4
with: { distribution: temurin, java-version: "17" }
- uses: android-actions/setup-android@v3
- uses: pnpm/action-setup@v4
- uses: actions/setup-node@v4
with: { node-version: "${{ env.NODE_VERSION }}", cache: pnpm }
- run: pnpm install --frozen-lockfile
- name: Сборка APK
working-directory: apps/mobile
run: |
npx expo prebuild --platform android --clean --no-install
cd android && ./gradlew --no-daemon assembleRelease
- name: Подпись APK
env:
KEYSTORE_B64: ${{ secrets.ANDROID_KEYSTORE_BASE64 }}
KEYSTORE_PASSWORD: ${{ secrets.ANDROID_KEYSTORE_PASSWORD }}
KEY_ALIAS: ${{ secrets.ANDROID_KEY_ALIAS }}
KEY_PASSWORD: ${{ secrets.ANDROID_KEY_PASSWORD }}
run: |
set -euo pipefail
src=apps/mobile/android/app/build/outputs/apk/release/app-release.apk
out="pipu-music-${PIPU_VERSION}.apk"
bt="$(ls -d "$ANDROID_HOME"/build-tools/* | sort -V | tail -1)"
if [ -n "${KEYSTORE_B64}" ]; then
echo "$KEYSTORE_B64" | base64 -d > release.keystore
"$bt/apksigner" sign --ks release.keystore --ks-pass env:KEYSTORE_PASSWORD \
--ks-key-alias "$KEY_ALIAS" --key-pass env:KEY_PASSWORD --out "$out" "$src"
rm release.keystore
else
echo "::warning::ANDROID_KEYSTORE_BASE64 не задан — APK подписан отладочным ключом и не обновится поверх релизного"
cp "$src" "$out"
fi
"$bt/apksigner" verify --print-certs "$out" | head -3
sha256sum "$out" | cut -d' ' -f1 > "$out.sha256"
echo "APK=$out" >> "$GITHUB_ENV"
- name: Changelog
run: |
prev="$(git describe --tags --abbrev=0 "${GITHUB_REF_NAME}^" 2>/dev/null || true)"
range="${prev:+$prev..}${GITHUB_REF_NAME}"
{
echo "## Pipu Music ${PIPU_VERSION}"
echo
for t in feat fix perf refactor docs ci chore; do
lines="$(git log --no-merges --format='%s' "$range" | grep -E "^${t}(\(|:|!)" || true)"
[ -n "$lines" ] || continue
case $t in feat) h="Новое";; fix) h="Исправления";; perf) h="Производительность";; *) h="$t";; esac
echo "### $h"; echo "$lines" | sed 's/^/- /'; echo
done
} > CHANGELOG_RELEASE.md
cat CHANGELOG_RELEASE.md
- name: Gitea Release
env:
TOKEN: ${{ secrets.RELEASE_TOKEN }}
API: ${{ github.server_url }}/api/v1/repos/${{ github.repository }}
PRERELEASE: ${{ needs.verify.outputs.prerelease }}
run: |
set -euo pipefail
body="$(jq -n --arg tag "$GITHUB_REF_NAME" --arg name "Pipu Music $PIPU_VERSION" \
--rawfile notes CHANGELOG_RELEASE.md --argjson pre "$PRERELEASE" \
'{tag_name:$tag, name:$name, body:$notes, prerelease:$pre, draft:false}')"
id="$(curl -fsS -X POST -H "Authorization: token $TOKEN" -H 'Content-Type: application/json' \
-d "$body" "$API/releases" | jq -r .id)"
for f in "$APK" "$APK.sha256" deploy/compose.yaml deploy/compose.tls.yaml deploy/Caddyfile deploy/.env.example deploy/install.sh deploy/update.sh; do
curl -fsS -X POST -H "Authorization: token $TOKEN" \
-F "attachment=@$f" "$API/releases/$id/assets?name=$(basename "$f")" > /dev/null
echo "uploaded $(basename "$f")"
done