diff --git a/.gitea/workflows/auto-release-github.yml b/.gitea/workflows/auto-release-github.yml new file mode 100644 index 0000000..a0449eb --- /dev/null +++ b/.gitea/workflows/auto-release-github.yml @@ -0,0 +1,51 @@ +name: Auto Release + +on: + workflow_call: + +jobs: + auto-release: + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: https://github.com/actions/checkout@v6 + with: + fetch-depth: 0 + token: ${{ gitea.token }} + + - name: Generate changelog + id: changelog + run: | + CURRENT_TAG=${GITHUB_REF#refs/tags/} + PREV_TAG=$(git tag --sort=-version:refname | sed -n '2p') + + if [ -z "$PREV_TAG" ]; then + CHANGELOG=$(git log --pretty=format:"- %s (%h)" "$CURRENT_TAG") + else + CHANGELOG=$(git log --pretty=format:"- %s (%h)" "${PREV_TAG}..${CURRENT_TAG}") + fi + + echo "$CHANGELOG" > /tmp/changelog.txt + echo "current_tag=$CURRENT_TAG" >> $GITHUB_OUTPUT + + - name: Create release + env: + GITEA_TOKEN: ${{ gitea.token }} + SERVER_URL: ${{ gitea.server_url }} + REPOSITORY: ${{ gitea.repository }} + run: | + CURRENT_TAG=${{ steps.changelog.outputs.current_tag }} + APP_NAME=$(jq -r '.name' package.json) + CHANGELOG=$(cat /tmp/changelog.txt) + + curl -s -X POST \ + -H "Content-Type: application/json" \ + -H "Authorization: token $GITEA_TOKEN" \ + "$SERVER_URL/api/v1/repos/$REPOSITORY/releases" \ + -d "{ + \"tag_name\": \"$CURRENT_TAG\", + \"name\": \"$APP_NAME $CURRENT_TAG\", + \"body\": $(echo "$CHANGELOG" | jq -Rs .), + \"draft\": false, + \"prerelease\": false + }" diff --git a/.gitea/workflows/capacitor-android-github.yml b/.gitea/workflows/capacitor-android-github.yml new file mode 100644 index 0000000..5716566 --- /dev/null +++ b/.gitea/workflows/capacitor-android-github.yml @@ -0,0 +1,169 @@ +name: Capacitor Android + +on: + workflow_call: + inputs: + node-version: + type: string + default: '24.16.0' + java-version: + type: string + default: '21' + runner: + type: string + default: 'ubuntu-latest' + build-type: + description: 'debug | release' + type: string + default: 'debug' + output-format: + description: 'apk (sideload/test) | aab (Play Store)' + type: string + default: 'apk' + secrets: + NPM_TOKEN: + required: false + KEYSTORE_BASE64: + required: false + KEYSTORE_PASSWORD: + required: false + KEY_ALIAS: + required: false + KEY_PASSWORD: + required: false + GOOGLE_SERVICES_JSON: + required: false + +jobs: + android-build: + runs-on: ${{ inputs.runner }} + steps: + - name: Checkout + uses: https://github.com/actions/checkout@v6 + + - name: Setup Node.js + uses: https://github.com/actions/setup-node@v4 + with: + node-version: ${{ inputs.node-version || '24.16.0' }} + + - name: Setup Java + uses: https://github.com/actions/setup-java@v4 + with: + distribution: temurin + java-version: ${{ inputs.java-version || '17' }} + + - name: Setup Android SDK + uses: https://github.com/android-actions/setup-android@v4 + + - name: Cache npm + uses: https://github.com/actions/cache@v4 + with: + path: ~/.npm + key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }} + restore-keys: | + ${{ runner.os }}-node- + + - name: Cache Gradle + uses: https://github.com/actions/cache@v4 + with: + path: | + ~/.gradle/caches + ~/.gradle/wrapper + key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle*', '**/gradle-wrapper.properties') }} + restore-keys: | + ${{ runner.os }}-gradle- + + - name: Configure npm private registry + run: | + echo "@pzeta:registry=https://gitea.pzetatouch.it/api/packages/pzeta_touch/npm/" >> ~/.npmrc + echo "//gitea.pzetatouch.it/api/packages/pzeta_touch/npm/:_authToken=${{ secrets.NPM_TOKEN }}" >> ~/.npmrc + + - name: Read app info from package.json + id: app-info + run: | + echo "name=$(jq -r '.name' package.json)" >> $GITHUB_OUTPUT + echo "version=$(jq -r '.version' package.json)" >> $GITHUB_OUTPUT + + - name: Install dependencies + run: npm ci + + - name: Build web app + run: npm run build + + - name: Add Android platform + run: npx cap add android || true + + - name: Sync Capacitor + run: npx cap sync android + + - name: Setup google-services.json + if: secrets.GOOGLE_SERVICES_JSON != '' + run: echo '${{ secrets.GOOGLE_SERVICES_JSON }}' > android/app/google-services.json + + - name: Setup release keystore + if: inputs.build-type == 'release' + run: echo '${{ secrets.KEYSTORE_BASE64 }}' | base64 -d > android/app/keystore.jks + + - name: Build Android (APK) + if: inputs.output-format == 'apk' + working-directory: android + env: + KEYSTORE_PASSWORD: ${{ secrets.KEYSTORE_PASSWORD }} + KEY_ALIAS: ${{ secrets.KEY_ALIAS }} + KEY_PASSWORD: ${{ secrets.KEY_PASSWORD }} + run: | + if [ "${{ inputs.build-type }}" = "release" ]; then + ./gradlew assembleRelease + else + ./gradlew assembleDebug + fi + + - name: Rename APK + if: inputs.output-format == 'apk' + run: | + APP="${{ steps.app-info.outputs.name }}-${{ steps.app-info.outputs.version }}-${{ inputs.build-type }}" + APK_DIR="android/app/build/outputs/apk/${{ inputs.build-type }}" + mv "$APK_DIR"/app-${{ inputs.build-type }}.apk "$APK_DIR/${APP}.apk" 2>/dev/null || \ + mv "$APK_DIR"/app-${{ inputs.build-type }}-unsigned.apk "$APK_DIR/${APP}.apk" 2>/dev/null || \ + find "$APK_DIR" -name "*.apk" ! -name "${APP}.apk" -exec mv {} "$APK_DIR/${APP}.apk" \; + + - name: Build Android (AAB) + if: inputs.output-format == 'aab' + working-directory: android + env: + KEYSTORE_PASSWORD: ${{ secrets.KEYSTORE_PASSWORD }} + KEY_ALIAS: ${{ secrets.KEY_ALIAS }} + KEY_PASSWORD: ${{ secrets.KEY_PASSWORD }} + run: ./gradlew bundleRelease + + - name: Rename AAB + if: inputs.output-format == 'aab' + run: | + APP="${{ steps.app-info.outputs.name }}-${{ steps.app-info.outputs.version }}-release" + AAB_DIR="android/app/build/outputs/bundle/release" + find "$AAB_DIR" -name "*.aab" ! -name "${APP}.aab" -exec mv {} "$AAB_DIR/${APP}.aab" \; + + - name: Upload APK artifact + if: inputs.output-format == 'apk' + uses: https://github.com/actions/upload-artifact@v3 + with: + name: ${{ steps.app-info.outputs.name }}-${{ steps.app-info.outputs.version }}-${{ inputs.build-type }}-apk + path: android/app/build/outputs/apk/${{ inputs.build-type }}/${{ steps.app-info.outputs.name }}-${{ steps.app-info.outputs.version }}-${{ inputs.build-type }}.apk + retention-days: 14 + + - name: Upload AAB artifact + if: inputs.output-format == 'aab' + uses: https://github.com/actions/upload-artifact@v3 + with: + name: ${{ steps.app-info.outputs.name }}-${{ steps.app-info.outputs.version }}-release-aab + path: android/app/build/outputs/bundle/release/${{ steps.app-info.outputs.name }}-${{ steps.app-info.outputs.version }}-release.aab + retention-days: 14 + + - name: Upload Gradle build reports + if: always() + uses: https://github.com/actions/upload-artifact@v3 + with: + name: gradle-build-reports + path: android/build/reports/ + retention-days: 7 + if-no-files-found: ignore diff --git a/.gitea/workflows/dependency-check-github.yml b/.gitea/workflows/dependency-check-github.yml new file mode 100644 index 0000000..4b99575 --- /dev/null +++ b/.gitea/workflows/dependency-check-github.yml @@ -0,0 +1,68 @@ +name: Dependency Audit + +on: + workflow_call: + inputs: + node-version: + type: string + default: '24.16.0' + workflow_dispatch: + +jobs: + dependency-audit: + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: https://github.com/actions/checkout@v6 + + - name: Setup Node.js + uses: https://github.com/actions/setup-node@v4 + with: + node-version: ${{ inputs.node-version || '24.16.0' }} + + - name: Cache npm + uses: https://github.com/actions/cache@v4 + with: + path: ~/.npm + key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }} + restore-keys: | + ${{ runner.os }}-node- + + - name: Configure npm private registry + run: | + echo "@pzeta:registry=https://gitea.pzetatouch.it/api/packages/pzeta_touch/npm/" >> ~/.npmrc + echo "//gitea.pzetatouch.it/api/packages/pzeta_touch/npm/:_authToken=${{ secrets.NPM_TOKEN }}" >> ~/.npmrc + + - name: Install dependencies + run: npm ci + + - name: Security audit + id: audit + run: | + npm audit --audit-level=high --json > audit.json 2>/dev/null || true + VULNS=$(jq '(.metadata.vulnerabilities.high // 0) + (.metadata.vulnerabilities.critical // 0)' audit.json 2>/dev/null || echo "0") + echo "vulnerabilities=$VULNS" >> $GITHUB_OUTPUT + + - name: Open issue if vulnerabilities found + if: steps.audit.outputs.vulnerabilities != '0' + env: + GITEA_TOKEN: ${{ gitea.token }} + SERVER_URL: ${{ gitea.server_url }} + REPOSITORY: ${{ gitea.repository }} + run: | + VULNS="${{ steps.audit.outputs.vulnerabilities }}" + DATE=$(date '+%Y-%m-%d') + + VULN_LIST=$(jq -r '.vulnerabilities | to_entries[] | "- \(.key): \(.value.severity)"' audit.json 2>/dev/null | head -20 || echo "N/A") + + printf '## Security Audit — %s\n\n### Vulnerabilità (high/critical): %s\n\n```\n%s\n```\n' \ + "$DATE" "$VULNS" "$VULN_LIST" > /tmp/body.md + + curl -s -X POST \ + -H "Content-Type: application/json" \ + -H "Authorization: token $GITEA_TOKEN" \ + "$SERVER_URL/api/v1/repos/$REPOSITORY/issues" \ + -d "{ + \"title\": \"[$DATE] Security: $VULNS vulnerabilità high/critical\", + \"body\": $(jq -Rs . /tmp/body.md) + }" diff --git a/.gitea/workflows/dependency-outdated-github.yml b/.gitea/workflows/dependency-outdated-github.yml new file mode 100644 index 0000000..a95f1f6 --- /dev/null +++ b/.gitea/workflows/dependency-outdated-github.yml @@ -0,0 +1,68 @@ +name: Dependency Outdated + +on: + workflow_call: + inputs: + node-version: + type: string + default: '24.16.0' + workflow_dispatch: + +jobs: + dependency-outdated: + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: https://github.com/actions/checkout@v6 + + - name: Setup Node.js + uses: https://github.com/actions/setup-node@v4 + with: + node-version: ${{ inputs.node-version || '24.16.0' }} + + - name: Cache npm + uses: https://github.com/actions/cache@v4 + with: + path: ~/.npm + key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }} + restore-keys: | + ${{ runner.os }}-node- + + - name: Configure npm private registry + run: | + echo "@pzeta:registry=https://gitea.pzetatouch.it/api/packages/pzeta_touch/npm/" >> ~/.npmrc + echo "//gitea.pzetatouch.it/api/packages/pzeta_touch/npm/:_authToken=${{ secrets.NPM_TOKEN }}" >> ~/.npmrc + + - name: Install dependencies + run: npm ci + + - name: Check outdated packages + id: outdated + run: | + npm outdated --json > outdated.json 2>/dev/null || true + OUTDATED=$(jq 'keys | length' outdated.json 2>/dev/null || echo "0") + echo "count=$OUTDATED" >> $GITHUB_OUTPUT + + - name: Open issue if packages outdated + if: steps.outdated.outputs.count != '0' + env: + GITEA_TOKEN: ${{ gitea.token }} + SERVER_URL: ${{ gitea.server_url }} + REPOSITORY: ${{ gitea.repository }} + run: | + OUTDATED="${{ steps.outdated.outputs.count }}" + DATE=$(date '+%Y-%m-%d') + + OUTDATED_LIST=$(jq -r 'to_entries[] | "- \(.key): \(.value.current) → \(.value.latest)"' outdated.json 2>/dev/null | head -20 || echo "N/A") + + printf '## Dipendenze Obsolete — %s\n\n### Pacchetti da aggiornare: %s\n\n```\n%s\n```\n' \ + "$DATE" "$OUTDATED" "$OUTDATED_LIST" > /tmp/body.md + + curl -s -X POST \ + -H "Content-Type: application/json" \ + -H "Authorization: token $GITEA_TOKEN" \ + "$SERVER_URL/api/v1/repos/$REPOSITORY/issues" \ + -d "{ + \"title\": \"[$DATE] Dipendenze: $OUTDATED pacchetti obsoleti\", + \"body\": $(jq -Rs . /tmp/body.md) + }" diff --git a/.gitea/workflows/docker-release-github.yml b/.gitea/workflows/docker-release-github.yml new file mode 100644 index 0000000..9aa5546 --- /dev/null +++ b/.gitea/workflows/docker-release-github.yml @@ -0,0 +1,99 @@ +name: Docker Release + +on: + workflow_call: + inputs: + node-version: + type: string + default: '24.16.0' + npm-version: + type: string + default: '' + runner: + type: string + default: 'catthehacker-latest' + +jobs: + docker-release: + runs-on: ${{ inputs.runner }} + steps: + - name: Checkout + uses: https://github.com/actions/checkout@v6 + + - name: Setup Node.js + uses: https://github.com/actions/setup-node@v4 + with: + node-version: ${{ inputs.node-version || '24.16.0' }} + + - name: Upgrade npm + if: inputs.npm-version != '' + run: npm install -g npm@${{ inputs.npm-version }} + + - name: Cache npm + uses: https://github.com/actions/cache@v4 + with: + path: ~/.npm + key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }} + restore-keys: | + ${{ runner.os }}-node- + + - name: Configure npm private registry + run: | + echo "@pzeta:registry=https://gitea.pzetatouch.it/api/packages/pzeta_touch/npm/" >> ~/.npmrc + echo "//gitea.pzetatouch.it/api/packages/pzeta_touch/npm/:_authToken=${{ secrets.NPM_TOKEN }}" >> ~/.npmrc + + - name: Install dependencies + run: npm ci + + - name: Type check + run: npm run typecheck + + - name: Lint + run: npm run lint:check + + - name: Format check + run: npm run format:check + + - name: Build + run: npm run build + + - name: Test + run: npm run test + + - name: Login to container registry + uses: https://github.com/docker/login-action@v4 + with: + registry: gitea.pzetatouch.it + username: ${{ secrets.G_USER }} + password: ${{ secrets.NPM_TOKEN }} + + - name: Determine image tags + id: tags + run: | + RAW_NAME=$(jq -r '.name' package.json) + APP_NAME=$(echo "$RAW_NAME" | sed 's|^@[^/]*/||') + VERSION=$(jq -r '.version' package.json) + REGISTRY="gitea.pzetatouch.it/pzeta_touch" + echo "version_tag=${REGISTRY}/${APP_NAME}:${VERSION}" >> $GITHUB_OUTPUT + echo "latest_tag=${REGISTRY}/${APP_NAME}:latest" >> $GITHUB_OUTPUT + echo "version=${VERSION}" >> $GITHUB_OUTPUT + + - name: Build and push Docker image + uses: https://github.com/docker/build-push-action@v6 + with: + push: true + context: . + file: ./Dockerfile + tags: | + ${{ steps.tags.outputs.version_tag }} + ${{ steps.tags.outputs.latest_tag }} + labels: | + org.opencontainers.image.source=${{ gitea.server_url }}/${{ gitea.repository }} + org.opencontainers.image.revision=${{ gitea.sha }} + org.opencontainers.image.version=${{ steps.tags.outputs.version }} + build-args: | + NODE_VERSION=${{ vars.NODE_DOCKER_VERSION || '24.16.0-alpine3.22' }} + NGINX_VERSION=${{ vars.NGINX_DOCKER_VERSION || '1.30.2-alpine3.23' }} + NPM_VERSION=${{ vars.NPM_VERSION || '11.16.0' }} + secrets: | + npm_token=${{ secrets.NPM_TOKEN }} diff --git a/.gitea/workflows/npm-publish-github.yml b/.gitea/workflows/npm-publish-github.yml new file mode 100644 index 0000000..5210649 --- /dev/null +++ b/.gitea/workflows/npm-publish-github.yml @@ -0,0 +1,54 @@ +name: Publish npm Package + +on: + workflow_call: + inputs: + node-version: + type: string + default: '24.16.0' + +jobs: + npm-publish: + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: https://github.com/actions/checkout@v6 + + - name: Setup Node.js + uses: https://github.com/actions/setup-node@v4 + with: + node-version: ${{ inputs.node-version || '24.16.0' }} + + - name: Cache npm + uses: https://github.com/actions/cache@v4 + with: + path: ~/.npm + key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }} + restore-keys: | + ${{ runner.os }}-node- + + - name: Configure npm private registry + run: | + echo "@pzeta:registry=https://gitea.pzetatouch.it/api/packages/pzeta_touch/npm/" >> ~/.npmrc + echo "//gitea.pzetatouch.it/api/packages/pzeta_touch/npm/:_authToken=${{ secrets.NPM_TOKEN }}" >> ~/.npmrc + + - name: Install dependencies + run: npm ci + + - name: Lint + run: npm run lint:check + + - name: Type check + run: npm run typecheck + + - name: Format check + run: npm run format:check + + - name: Build + run: npm run build + + - name: Test + run: npm run test + + - name: Publish + run: npm publish diff --git a/.gitea/workflows/python-auto-release-github.yml b/.gitea/workflows/python-auto-release-github.yml new file mode 100644 index 0000000..766aeb0 --- /dev/null +++ b/.gitea/workflows/python-auto-release-github.yml @@ -0,0 +1,70 @@ +name: Python Auto Release + +on: + workflow_call: + inputs: + working-directory: + description: 'Directory di lavoro se il progetto non è in root' + type: string + default: '.' + +jobs: + python-auto-release: + runs-on: ubuntu-latest + defaults: + run: + working-directory: ${{ inputs.working-directory }} + steps: + - name: Checkout + uses: https://github.com/actions/checkout@v6 + with: + fetch-depth: 0 + token: ${{ gitea.token }} + + - name: Generate changelog + id: changelog + run: | + CURRENT_TAG=${GITHUB_REF#refs/tags/} + PREV_TAG=$(git tag --sort=-version:refname | sed -n '2p') + + if [ -z "$PREV_TAG" ]; then + CHANGELOG=$(git log --pretty=format:"- %s (%h)" "$CURRENT_TAG") + else + CHANGELOG=$(git log --pretty=format:"- %s (%h)" "${PREV_TAG}..${CURRENT_TAG}") + fi + + echo "$CHANGELOG" > /tmp/changelog.txt + echo "current_tag=$CURRENT_TAG" >> $GITHUB_OUTPUT + + - name: Read app name from pyproject.toml + id: app-info + run: | + APP_NAME=$(python3 -c " + import re, pathlib + content = pathlib.Path('pyproject.toml').read_text() + m = re.search(r'^name\s*=\s*[\"\'](.*?)[\"\']', content, re.MULTILINE) + print(m.group(1) if m else 'app') + " 2>/dev/null || echo 'app') + echo "name=$APP_NAME" >> $GITHUB_OUTPUT + + - name: Create release + env: + GITEA_TOKEN: ${{ gitea.token }} + SERVER_URL: ${{ gitea.server_url }} + REPOSITORY: ${{ gitea.repository }} + run: | + CURRENT_TAG=${{ steps.changelog.outputs.current_tag }} + APP_NAME=${{ steps.app-info.outputs.name }} + CHANGELOG=$(cat /tmp/changelog.txt) + + curl -s -X POST \ + -H "Content-Type: application/json" \ + -H "Authorization: token $GITEA_TOKEN" \ + "$SERVER_URL/api/v1/repos/$REPOSITORY/releases" \ + -d "{ + \"tag_name\": \"$CURRENT_TAG\", + \"name\": \"$APP_NAME $CURRENT_TAG\", + \"body\": $(echo "$CHANGELOG" | jq -Rs .), + \"draft\": false, + \"prerelease\": false + }" diff --git a/.gitea/workflows/python-dependency-check-github.yml b/.gitea/workflows/python-dependency-check-github.yml new file mode 100644 index 0000000..0b9cd40 --- /dev/null +++ b/.gitea/workflows/python-dependency-check-github.yml @@ -0,0 +1,120 @@ +name: Python Dependency Audit + +on: + workflow_call: + inputs: + python-version: + type: string + default: '3.11' + install-extras: + type: string + default: 'dev' + working-directory: + type: string + default: '.' + workflow_dispatch: + +jobs: + python-dependency-audit: + runs-on: ubuntu-latest + defaults: + run: + working-directory: ${{ inputs.working-directory }} + steps: + - name: Checkout + uses: https://github.com/actions/checkout@v6 + + - name: Setup Python + uses: https://github.com/actions/setup-python@v5.2.0 + with: + python-version: ${{ inputs.python-version || '3.11' }} + + - name: Cache pip + uses: https://github.com/actions/cache@v4 + with: + path: ~/.cache/pip + key: ${{ runner.os }}-pip-${{ inputs.python-version }}-${{ hashFiles('**/pyproject.toml', '**/requirements*.txt') }} + restore-keys: | + ${{ runner.os }}-pip-${{ inputs.python-version }}- + ${{ runner.os }}-pip- + + - name: Install dependencies (isolated venv) + run: | + # venv pulita: audita SOLO le dipendenze dichiarate dal repo, + # non l'ambiente globale del runner (che su runner ML/GPU è contaminato) + python -m venv .audit-venv + .audit-venv/bin/pip install --upgrade pip pip-audit + if [ -n "${{ inputs.install-extras }}" ]; then + .audit-venv/bin/pip install -e ".[${{ inputs.install-extras }}]" + elif [ -f requirements.txt ]; then + .audit-venv/bin/pip install -r requirements.txt + else + .audit-venv/bin/pip install -e "." + fi + + - name: Security audit (pip-audit) + id: audit + run: | + .audit-venv/bin/pip-audit --format=json --output=audit.json 2>/dev/null || true + VULNS=$(python3 -c " + import json, sys + try: + data = json.load(open('audit.json')) + deps = data.get('dependencies', []) + count = sum(len(d.get('vulns', [])) for d in deps) + print(count) + except Exception: + print(0) + ") + echo "vulnerabilities=$VULNS" >> $GITHUB_OUTPUT + + - name: Open or update issue if vulnerabilities found + if: steps.audit.outputs.vulnerabilities != '0' + env: + GITEA_TOKEN: ${{ gitea.token }} + SERVER_URL: ${{ gitea.server_url }} + REPOSITORY: ${{ gitea.repository }} + run: | + VULNS="${{ steps.audit.outputs.vulnerabilities }}" + DATE=$(date '+%Y-%m-%d') + TITLE_PREFIX="Security Python:" + + VULN_LIST=$(python3 -c " + import json + try: + data = json.load(open('audit.json')) + lines = [] + for dep in data.get('dependencies', []): + for v in dep.get('vulns', []): + lines.append(f\"- {dep['name']} {dep.get('version','?')}: {v.get('id','?')} ({v.get('description','')[:80]})\") + print('\n'.join(lines[:20])) + except Exception: + print('N/A') + ") + + printf '## Security Audit Python — %s\n\n### Vulnerabilità trovate: %s\n\n```\n%s\n```\n' \ + "$DATE" "$VULNS" "$VULN_LIST" > /tmp/body.md + + # Deduplica: se esiste già una issue aperta con lo stesso prefisso, + # aggiungi un commento invece di aprirne una nuova + EXISTING=$(curl -s \ + -H "Authorization: token $GITEA_TOKEN" \ + "$SERVER_URL/api/v1/repos/$REPOSITORY/issues?state=open&type=issues&limit=50" \ + | jq -r --arg p "$TITLE_PREFIX" '[.[] | select(.title | contains($p))] | (first // {}) | .number // empty') + + if [ -n "$EXISTING" ]; then + curl -s -X POST \ + -H "Content-Type: application/json" \ + -H "Authorization: token $GITEA_TOKEN" \ + "$SERVER_URL/api/v1/repos/$REPOSITORY/issues/$EXISTING/comments" \ + -d "{ \"body\": $(jq -Rs . /tmp/body.md) }" + else + curl -s -X POST \ + -H "Content-Type: application/json" \ + -H "Authorization: token $GITEA_TOKEN" \ + "$SERVER_URL/api/v1/repos/$REPOSITORY/issues" \ + -d "{ + \"title\": \"[$DATE] Security Python: $VULNS vulnerabilità rilevate\", + \"body\": $(jq -Rs . /tmp/body.md) + }" + fi diff --git a/.gitea/workflows/python-dependency-check.yml b/.gitea/workflows/python-dependency-check.yml index ed95123..97f0e74 100644 --- a/.gitea/workflows/python-dependency-check.yml +++ b/.gitea/workflows/python-dependency-check.yml @@ -38,21 +38,24 @@ jobs: ${{ runner.os }}-pip-${{ inputs.python-version }}- ${{ runner.os }}-pip- - - name: Install dependencies + - name: Install dependencies (isolated venv) run: | - python -m pip install --upgrade pip pip-audit + # venv pulita: audita SOLO le dipendenze dichiarate dal repo, + # non l'ambiente globale del runner (che su runner ML/GPU è contaminato) + python -m venv .audit-venv + .audit-venv/bin/pip install --upgrade pip pip-audit if [ -n "${{ inputs.install-extras }}" ]; then - pip install -e ".[${{ inputs.install-extras }}]" + .audit-venv/bin/pip install -e ".[${{ inputs.install-extras }}]" elif [ -f requirements.txt ]; then - pip install -r requirements.txt + .audit-venv/bin/pip install -r requirements.txt else - pip install -e "." + .audit-venv/bin/pip install -e "." fi - name: Security audit (pip-audit) id: audit run: | - pip-audit --format=json --output=audit.json 2>/dev/null || true + .audit-venv/bin/pip-audit --format=json --output=audit.json 2>/dev/null || true VULNS=$(python3 -c " import json, sys try: @@ -65,7 +68,7 @@ jobs: ") echo "vulnerabilities=$VULNS" >> $GITHUB_OUTPUT - - name: Open issue if vulnerabilities found + - name: Open or update issue if vulnerabilities found if: steps.audit.outputs.vulnerabilities != '0' env: GITEA_TOKEN: ${{ gitea.token }} @@ -74,6 +77,7 @@ jobs: run: | VULNS="${{ steps.audit.outputs.vulnerabilities }}" DATE=$(date '+%Y-%m-%d') + TITLE_PREFIX="Security Python:" VULN_LIST=$(python3 -c " import json @@ -91,11 +95,26 @@ jobs: printf '## Security Audit Python — %s\n\n### Vulnerabilità trovate: %s\n\n```\n%s\n```\n' \ "$DATE" "$VULNS" "$VULN_LIST" > /tmp/body.md - curl -s -X POST \ - -H "Content-Type: application/json" \ + # Deduplica: se esiste già una issue aperta con lo stesso prefisso, + # aggiungi un commento invece di aprirne una nuova + EXISTING=$(curl -s \ -H "Authorization: token $GITEA_TOKEN" \ - "$SERVER_URL/api/v1/repos/$REPOSITORY/issues" \ - -d "{ - \"title\": \"[$DATE] Security Python: $VULNS vulnerabilità rilevate\", - \"body\": $(jq -Rs . /tmp/body.md) - }" + "$SERVER_URL/api/v1/repos/$REPOSITORY/issues?state=open&type=issues&limit=50" \ + | jq -r --arg p "$TITLE_PREFIX" '[.[] | select(.title | contains($p))] | (first // {}) | .number // empty') + + if [ -n "$EXISTING" ]; then + curl -s -X POST \ + -H "Content-Type: application/json" \ + -H "Authorization: token $GITEA_TOKEN" \ + "$SERVER_URL/api/v1/repos/$REPOSITORY/issues/$EXISTING/comments" \ + -d "{ \"body\": $(jq -Rs . /tmp/body.md) }" + else + curl -s -X POST \ + -H "Content-Type: application/json" \ + -H "Authorization: token $GITEA_TOKEN" \ + "$SERVER_URL/api/v1/repos/$REPOSITORY/issues" \ + -d "{ + \"title\": \"[$DATE] Security Python: $VULNS vulnerabilità rilevate\", + \"body\": $(jq -Rs . /tmp/body.md) + }" + fi diff --git a/.gitea/workflows/python-dependency-outdated-github.yml b/.gitea/workflows/python-dependency-outdated-github.yml new file mode 100644 index 0000000..f5547b8 --- /dev/null +++ b/.gitea/workflows/python-dependency-outdated-github.yml @@ -0,0 +1,108 @@ +name: Python Dependency Outdated + +on: + workflow_call: + inputs: + python-version: + type: string + default: '3.11' + install-extras: + type: string + default: 'dev' + working-directory: + type: string + default: '.' + workflow_dispatch: + +jobs: + python-dependency-outdated: + runs-on: ubuntu-latest + defaults: + run: + working-directory: ${{ inputs.working-directory }} + steps: + - name: Checkout + uses: https://github.com/actions/checkout@v6 + + - name: Setup Python + uses: https://github.com/actions/setup-python@v5.2.0 + with: + python-version: ${{ inputs.python-version || '3.11' }} + + - name: Cache pip + uses: https://github.com/actions/cache@v4 + with: + path: ~/.cache/pip + key: ${{ runner.os }}-pip-${{ inputs.python-version }}-${{ hashFiles('**/pyproject.toml', '**/requirements*.txt') }} + restore-keys: | + ${{ runner.os }}-pip-${{ inputs.python-version }}- + ${{ runner.os }}-pip- + + - name: Install dependencies (isolated venv) + run: | + # venv pulita: elenca come obsolete SOLO le dipendenze dichiarate dal repo, + # non i pacchetti globali del runner (torch/cuda/nvidia su runner ML/GPU) + python -m venv .audit-venv + .audit-venv/bin/pip install --upgrade pip + if [ -n "${{ inputs.install-extras }}" ]; then + .audit-venv/bin/pip install -e ".[${{ inputs.install-extras }}]" + elif [ -f requirements.txt ]; then + .audit-venv/bin/pip install -r requirements.txt + else + .audit-venv/bin/pip install -e "." + fi + + - name: Check outdated packages + id: outdated + run: | + .audit-venv/bin/pip list --outdated --format=json > outdated.json 2>/dev/null || echo '[]' > outdated.json + COUNT=$(python3 -c "import json; print(len(json.load(open('outdated.json'))))") + echo "count=$COUNT" >> $GITHUB_OUTPUT + + - name: Open or update issue if packages outdated + if: steps.outdated.outputs.count != '0' + env: + GITEA_TOKEN: ${{ gitea.token }} + SERVER_URL: ${{ gitea.server_url }} + REPOSITORY: ${{ gitea.repository }} + run: | + COUNT="${{ steps.outdated.outputs.count }}" + DATE=$(date '+%Y-%m-%d') + TITLE_PREFIX="Dipendenze Python:" + + OUTDATED_LIST=$(python3 -c " + import json + try: + data = json.load(open('outdated.json')) + lines = [f\"- {p['name']}: {p['version']} → {p['latest_version']}\" for p in data[:20]] + print('\n'.join(lines)) + except Exception: + print('N/A') + ") + + printf '## Dipendenze Python Obsolete — %s\n\n### Pacchetti da aggiornare: %s\n\n```\n%s\n```\n' \ + "$DATE" "$COUNT" "$OUTDATED_LIST" > /tmp/body.md + + # Deduplica: se esiste già una issue aperta con lo stesso prefisso, + # aggiungi un commento invece di aprirne una nuova + EXISTING=$(curl -s \ + -H "Authorization: token $GITEA_TOKEN" \ + "$SERVER_URL/api/v1/repos/$REPOSITORY/issues?state=open&type=issues&limit=50" \ + | jq -r --arg p "$TITLE_PREFIX" '[.[] | select(.title | contains($p))] | (first // {}) | .number // empty') + + if [ -n "$EXISTING" ]; then + curl -s -X POST \ + -H "Content-Type: application/json" \ + -H "Authorization: token $GITEA_TOKEN" \ + "$SERVER_URL/api/v1/repos/$REPOSITORY/issues/$EXISTING/comments" \ + -d "{ \"body\": $(jq -Rs . /tmp/body.md) }" + else + curl -s -X POST \ + -H "Content-Type: application/json" \ + -H "Authorization: token $GITEA_TOKEN" \ + "$SERVER_URL/api/v1/repos/$REPOSITORY/issues" \ + -d "{ + \"title\": \"[$DATE] Dipendenze Python: $COUNT pacchetti obsoleti\", + \"body\": $(jq -Rs . /tmp/body.md) + }" + fi diff --git a/.gitea/workflows/python-dependency-outdated.yml b/.gitea/workflows/python-dependency-outdated.yml index 5e469a4..afc0828 100644 --- a/.gitea/workflows/python-dependency-outdated.yml +++ b/.gitea/workflows/python-dependency-outdated.yml @@ -38,25 +38,28 @@ jobs: ${{ runner.os }}-pip-${{ inputs.python-version }}- ${{ runner.os }}-pip- - - name: Install dependencies + - name: Install dependencies (isolated venv) run: | - python -m pip install --upgrade pip + # venv pulita: elenca come obsolete SOLO le dipendenze dichiarate dal repo, + # non i pacchetti globali del runner (torch/cuda/nvidia su runner ML/GPU) + python -m venv .audit-venv + .audit-venv/bin/pip install --upgrade pip if [ -n "${{ inputs.install-extras }}" ]; then - pip install -e ".[${{ inputs.install-extras }}]" + .audit-venv/bin/pip install -e ".[${{ inputs.install-extras }}]" elif [ -f requirements.txt ]; then - pip install -r requirements.txt + .audit-venv/bin/pip install -r requirements.txt else - pip install -e "." + .audit-venv/bin/pip install -e "." fi - name: Check outdated packages id: outdated run: | - pip list --outdated --format=json > outdated.json 2>/dev/null || echo '[]' > outdated.json + .audit-venv/bin/pip list --outdated --format=json > outdated.json 2>/dev/null || echo '[]' > outdated.json COUNT=$(python3 -c "import json; print(len(json.load(open('outdated.json'))))") echo "count=$COUNT" >> $GITHUB_OUTPUT - - name: Open issue if packages outdated + - name: Open or update issue if packages outdated if: steps.outdated.outputs.count != '0' env: GITEA_TOKEN: ${{ gitea.token }} @@ -65,6 +68,7 @@ jobs: run: | COUNT="${{ steps.outdated.outputs.count }}" DATE=$(date '+%Y-%m-%d') + TITLE_PREFIX="Dipendenze Python:" OUTDATED_LIST=$(python3 -c " import json @@ -79,11 +83,26 @@ jobs: printf '## Dipendenze Python Obsolete — %s\n\n### Pacchetti da aggiornare: %s\n\n```\n%s\n```\n' \ "$DATE" "$COUNT" "$OUTDATED_LIST" > /tmp/body.md - curl -s -X POST \ - -H "Content-Type: application/json" \ + # Deduplica: se esiste già una issue aperta con lo stesso prefisso, + # aggiungi un commento invece di aprirne una nuova + EXISTING=$(curl -s \ -H "Authorization: token $GITEA_TOKEN" \ - "$SERVER_URL/api/v1/repos/$REPOSITORY/issues" \ - -d "{ - \"title\": \"[$DATE] Dipendenze Python: $COUNT pacchetti obsoleti\", - \"body\": $(jq -Rs . /tmp/body.md) - }" + "$SERVER_URL/api/v1/repos/$REPOSITORY/issues?state=open&type=issues&limit=50" \ + | jq -r --arg p "$TITLE_PREFIX" '[.[] | select(.title | contains($p))] | (first // {}) | .number // empty') + + if [ -n "$EXISTING" ]; then + curl -s -X POST \ + -H "Content-Type: application/json" \ + -H "Authorization: token $GITEA_TOKEN" \ + "$SERVER_URL/api/v1/repos/$REPOSITORY/issues/$EXISTING/comments" \ + -d "{ \"body\": $(jq -Rs . /tmp/body.md) }" + else + curl -s -X POST \ + -H "Content-Type: application/json" \ + -H "Authorization: token $GITEA_TOKEN" \ + "$SERVER_URL/api/v1/repos/$REPOSITORY/issues" \ + -d "{ + \"title\": \"[$DATE] Dipendenze Python: $COUNT pacchetti obsoleti\", + \"body\": $(jq -Rs . /tmp/body.md) + }" + fi diff --git a/.gitea/workflows/python-docker-release-github.yml b/.gitea/workflows/python-docker-release-github.yml new file mode 100644 index 0000000..2a4d3cc --- /dev/null +++ b/.gitea/workflows/python-docker-release-github.yml @@ -0,0 +1,121 @@ +name: Python Docker Release + +on: + workflow_call: + inputs: + python-version: + type: string + default: '3.11' + install-extras: + description: 'Extras pip da installare (es: dev, test)' + type: string + default: 'dev' + runner: + type: string + default: 'catthehacker-latest' + working-directory: + description: 'Directory di lavoro se il progetto non è in root' + type: string + default: '.' + dockerfile: + description: 'Path al Dockerfile' + type: string + default: './Dockerfile' + +jobs: + python-docker-release: + runs-on: ${{ inputs.runner }} + defaults: + run: + working-directory: ${{ inputs.working-directory }} + steps: + - name: Checkout + uses: https://github.com/actions/checkout@v6 + + - name: Setup Python + uses: https://github.com/actions/setup-python@v5.2.0 + with: + python-version: ${{ inputs.python-version || '3.11' }} + + - name: Cache pip + uses: https://github.com/actions/cache@v4 + with: + path: ~/.cache/pip + key: ${{ runner.os }}-pip-${{ inputs.python-version }}-${{ hashFiles('**/pyproject.toml', '**/requirements*.txt') }} + restore-keys: | + ${{ runner.os }}-pip-${{ inputs.python-version }}- + ${{ runner.os }}-pip- + + - name: Install dependencies + run: | + python -m pip install --upgrade pip + if [ -n "${{ inputs.install-extras }}" ]; then + pip install -e ".[${{ inputs.install-extras }}]" + elif [ -f requirements-dev.txt ]; then + pip install -r requirements-dev.txt + elif [ -f requirements.txt ]; then + pip install -r requirements.txt + else + pip install -e "." + fi + + - name: Lint (ruff) + run: ruff check . + + - name: Format check (ruff) + run: ruff format --check . + + - name: Type check (mypy) + run: mypy . + + - name: Test (pytest) + run: pytest --tb=short -q + + - name: Login to container registry + uses: https://github.com/docker/login-action@v4 + with: + registry: gitea.pzetatouch.it + username: ${{ secrets.G_USER }} + password: ${{ secrets.NPM_TOKEN }} + + - name: Determine image tags + id: tags + run: | + APP_NAME=$(python -c " + import tomllib, pathlib + data = tomllib.loads(pathlib.Path('pyproject.toml').read_text()) + print(data['project']['name']) + " 2>/dev/null || python3 -c " + import re, pathlib + content = pathlib.Path('pyproject.toml').read_text() + m = re.search(r'^name\s*=\s*[\"\'](.*?)[\"\']', content, re.MULTILINE) + print(m.group(1) if m else 'unknown') + ") + VERSION=$(python -c " + import tomllib, pathlib + data = tomllib.loads(pathlib.Path('pyproject.toml').read_text()) + print(data['project']['version']) + " 2>/dev/null || python3 -c " + import re, pathlib + content = pathlib.Path('pyproject.toml').read_text() + m = re.search(r'^version\s*=\s*[\"\'](.*?)[\"\']', content, re.MULTILINE) + print(m.group(1) if m else '0.0.0') + ") + REGISTRY="gitea.pzetatouch.it/pzeta_touch" + echo "version_tag=${REGISTRY}/${APP_NAME}:${VERSION}" >> $GITHUB_OUTPUT + echo "latest_tag=${REGISTRY}/${APP_NAME}:latest" >> $GITHUB_OUTPUT + echo "version=${VERSION}" >> $GITHUB_OUTPUT + + - name: Build and push Docker image + uses: https://github.com/docker/build-push-action@v6 + with: + push: true + context: ${{ inputs.working-directory }} + file: ${{ inputs.dockerfile }} + tags: | + ${{ steps.tags.outputs.version_tag }} + ${{ steps.tags.outputs.latest_tag }} + labels: | + org.opencontainers.image.source=${{ gitea.server_url }}/${{ gitea.repository }} + org.opencontainers.image.revision=${{ gitea.sha }} + org.opencontainers.image.version=${{ steps.tags.outputs.version }} diff --git a/.gitea/workflows/python-quality-gates-github.yml b/.gitea/workflows/python-quality-gates-github.yml new file mode 100644 index 0000000..af20983 --- /dev/null +++ b/.gitea/workflows/python-quality-gates-github.yml @@ -0,0 +1,65 @@ +name: Python Quality Gates + +on: + workflow_call: + inputs: + python-version: + type: string + default: '3.11' + install-extras: + description: 'Extras pip da installare (es: dev, test). Lasciare vuoto per solo requirements.txt' + type: string + default: 'dev' + working-directory: + description: 'Directory di lavoro se il progetto non è in root' + type: string + default: '.' + +jobs: + python-quality-gates: + runs-on: ubuntu-latest + defaults: + run: + working-directory: ${{ inputs.working-directory }} + steps: + - name: Checkout + uses: https://github.com/actions/checkout@v6 + + - name: Setup Python + uses: https://github.com/actions/setup-python@v5.2.0 + with: + python-version: ${{ inputs.python-version || '3.11' }} + + - name: Cache pip + uses: https://github.com/actions/cache@v4 + with: + path: ~/.cache/pip + key: ${{ runner.os }}-pip-${{ inputs.python-version }}-${{ hashFiles('**/pyproject.toml', '**/requirements*.txt') }} + restore-keys: | + ${{ runner.os }}-pip-${{ inputs.python-version }}- + ${{ runner.os }}-pip- + + - name: Install dependencies + run: | + python -m pip install --upgrade pip + if [ -n "${{ inputs.install-extras }}" ]; then + pip install -e ".[${{ inputs.install-extras }}]" + elif [ -f requirements-dev.txt ]; then + pip install -r requirements-dev.txt + elif [ -f requirements.txt ]; then + pip install -r requirements.txt + else + pip install -e "." + fi + + - name: Lint (ruff) + run: ruff check . + + - name: Format check (ruff) + run: ruff format --check . + + - name: Type check (mypy) + run: mypy . + + - name: Test (pytest) + run: pytest --tb=short -q diff --git a/.gitea/workflows/quality-gates-github.yml b/.gitea/workflows/quality-gates-github.yml new file mode 100644 index 0000000..cf1d713 --- /dev/null +++ b/.gitea/workflows/quality-gates-github.yml @@ -0,0 +1,64 @@ +name: Quality Gates + +on: + workflow_call: + inputs: + node-version: + type: string + default: '24.16.0' + npm-version: + type: string + default: '' + +jobs: + quality-gates: + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: https://github.com/actions/checkout@v6 + + - name: Setup Node.js + uses: https://github.com/actions/setup-node@v4 + with: + node-version: ${{ inputs.node-version || '24.16.0' }} + + - name: Upgrade npm + if: inputs.npm-version != '' + run: npm install -g npm@${{ inputs.npm-version }} + + - name: Cache npm + uses: https://github.com/actions/cache@v4 + with: + path: ~/.npm + key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }} + restore-keys: | + ${{ runner.os }}-node- + + - name: Configure npm private registry + run: | + echo "@pzeta:registry=https://gitea.pzetatouch.it/api/packages/pzeta_touch/npm/" >> ~/.npmrc + echo "//gitea.pzetatouch.it/api/packages/pzeta_touch/npm/:_authToken=${{ secrets.NPM_TOKEN }}" >> ~/.npmrc + + - name: Check outdated packages + run: npm outdated || true + + - name: Install dependencies + run: npm ci + + - name: Security audit + run: npm audit --audit-level=high || true + + - name: Lint + run: npm run lint:check + + - name: Type check + run: npm run typecheck + + - name: Format check + run: npm run format:check + + - name: Build + run: npm run build + + - name: Test + run: npm run test diff --git a/examples/capacitor/ci-github.yml b/examples/capacitor/ci-github.yml new file mode 100644 index 0000000..6b8b587 --- /dev/null +++ b/examples/capacitor/ci-github.yml @@ -0,0 +1,30 @@ +# Copia in: .gitea/workflows/ci.yml +# Trigger: push su qualsiasi branch → quality gates + build debug Android +# +# Il debug APK viene uplodato come artifact scaricabile dalla PR. +# Non richiede firma: usato per test interni su device fisico o emulatore. + +name: CI + +on: + push: + branches: + - main + paths-ignore: + - '**.md' + - 'docs/**' + pull_request: + branches: + - main + +jobs: + quality-gates: + uses: https://gitea.pzetatouch.it/devops/shared-actions/.gitea/workflows/quality-gates-github.yml@v1 + secrets: inherit + + android-debug: + uses: https://gitea.pzetatouch.it/devops/shared-actions/.gitea/workflows/capacitor-android-github.yml@v1 + secrets: inherit + with: + build-type: debug + output-format: apk diff --git a/examples/capacitor/release-github.yml b/examples/capacitor/release-github.yml new file mode 100644 index 0000000..adfbaf0 --- /dev/null +++ b/examples/capacitor/release-github.yml @@ -0,0 +1,49 @@ +# Copia in: .gitea/workflows/release.yml +# Trigger: git tag v* → APK firmato + AAB Play Store + release Gitea +# +# Secrets richiesti nel repository consumer: +# KEYSTORE_BASE64 — keystore codificato in base64 +# KEYSTORE_PASSWORD — password del keystore +# KEY_ALIAS — alias della chiave +# KEY_PASSWORD — password della chiave +# GOOGLE_SERVICES_JSON — contenuto del file google-services.json (se Firebase) +# +# Prerequisito build.gradle (android/app/build.gradle): +# signingConfigs { +# release { +# storeFile file("keystore.jks") +# storePassword System.getenv("KEYSTORE_PASSWORD") +# keyAlias System.getenv("KEY_ALIAS") +# keyPassword System.getenv("KEY_PASSWORD") +# } +# } +# +# NOTA: gitea-release attende entrambe le build Android via needs. +# Workaround Gitea bug #31900: token esplicito nel checkout di auto-release.yml. + +name: Release + +on: + push: + tags: + - 'v*' + +jobs: + android-apk: + uses: https://gitea.pzetatouch.it/devops/shared-actions/.gitea/workflows/capacitor-android-github.yml@v1 + secrets: inherit + with: + build-type: release + output-format: apk + + android-aab: + uses: https://gitea.pzetatouch.it/devops/shared-actions/.gitea/workflows/capacitor-android-github.yml@v1 + secrets: inherit + with: + build-type: release + output-format: aab + + gitea-release: + needs: [android-apk, android-aab] + uses: https://gitea.pzetatouch.it/devops/shared-actions/.gitea/workflows/auto-release-github.yml@v1 + secrets: inherit diff --git a/examples/documentazione/ci-github.yml b/examples/documentazione/ci-github.yml new file mode 100644 index 0000000..143be19 --- /dev/null +++ b/examples/documentazione/ci-github.yml @@ -0,0 +1,26 @@ +# Copia in: .gitea/workflows/ci.yml +# Usato da: siti documentazione Nuxt 4 con SSR e Docker +# +# Prerequisiti: +# - package.json con script: lint:check, typecheck, format:check, build, test +# - Secrets: NPM_TOKEN (accesso registry @pzeta privato) + +name: CI + +on: + push: + branches: + - main + paths-ignore: + - '**.md' + - 'content/**' + pull_request: + branches: + - main + +jobs: + quality-gates: + uses: https://gitea.pzetatouch.it/devops/shared-actions/.gitea/workflows/quality-gates-github.yml@v1 + secrets: inherit + with: + npm-version: '11' # lockfile generato con npm@11, runner usa npm@10 di default diff --git a/examples/documentazione/release-github.yml b/examples/documentazione/release-github.yml new file mode 100644 index 0000000..9c1d7f6 --- /dev/null +++ b/examples/documentazione/release-github.yml @@ -0,0 +1,30 @@ +# Copia in: .gitea/workflows/release.yml +# Trigger: git tag v* → build Docker + crea release Gitea +# +# NOTA: auto-release attende docker-release via needs. +# Workaround Gitea bug #31900: token esplicito nel checkout di auto-release.yml. +# +# Secrets richiesti nel repository consumer: +# NPM_TOKEN — accesso registry @pzeta (npm install + Docker secret) +# G_USER — username Docker registry Gitea + +name: Release + +on: + push: + tags: + - 'v*' + +jobs: + docker-release: + runs-on: catthehacker-latest # workaround Gitea bug #34986: runs-on non rispettato in workflow_call + uses: https://gitea.pzetatouch.it/devops/shared-actions/.gitea/workflows/docker-release-github.yml@v1 + secrets: inherit + with: + runner: catthehacker-latest # runner con Docker pre-installato + npm-version: '11' # lockfile generato con npm@11, runner usa npm@10 di default + + auto-release: + needs: [docker-release] + uses: https://gitea.pzetatouch.it/devops/shared-actions/.gitea/workflows/auto-release-github.yml@v1 + secrets: inherit diff --git a/examples/libreria-npm/ci-github.yml b/examples/libreria-npm/ci-github.yml new file mode 100644 index 0000000..c137dee --- /dev/null +++ b/examples/libreria-npm/ci-github.yml @@ -0,0 +1,20 @@ +# Copia in: .gitea/workflows/ci.yml +# Usato da: librerie npm pubblicate su registry @pzeta + +name: CI + +on: + push: + branches: + - main + paths-ignore: + - '**.md' + - 'docs/**' + pull_request: + branches: + - main + +jobs: + quality-gates: + uses: https://gitea.pzetatouch.it/devops/shared-actions/.gitea/workflows/quality-gates-github.yml@v1 + secrets: inherit diff --git a/examples/libreria-npm/release-github.yml b/examples/libreria-npm/release-github.yml new file mode 100644 index 0000000..bd40c45 --- /dev/null +++ b/examples/libreria-npm/release-github.yml @@ -0,0 +1,22 @@ +# Copia in: .gitea/workflows/release.yml +# Trigger: git tag v* → pubblica su npm + crea release Gitea +# +# NOTA: auto-release attende npm-publish via needs. +# Workaround Gitea bug #31900: token esplicito nel checkout di auto-release.yml. + +name: Release + +on: + push: + tags: + - 'v*' + +jobs: + npm-publish: + uses: https://gitea.pzetatouch.it/devops/shared-actions/.gitea/workflows/npm-publish-github.yml@v1 + secrets: inherit + + auto-release: + needs: [npm-publish] + uses: https://gitea.pzetatouch.it/devops/shared-actions/.gitea/workflows/auto-release-github.yml@v1 + secrets: inherit diff --git a/examples/microservizio/ci-github.yml b/examples/microservizio/ci-github.yml new file mode 100644 index 0000000..b94da80 --- /dev/null +++ b/examples/microservizio/ci-github.yml @@ -0,0 +1,22 @@ +# Copia in: .gitea/workflows/ci.yml +# Usato da: microservizi Node.js con deploy Docker + +name: CI + +on: + push: + branches: + - main + paths-ignore: + - '**.md' + - 'docs/**' + pull_request: + branches: + - main + +jobs: + quality-gates: + uses: https://gitea.pzetatouch.it/devops/shared-actions/.gitea/workflows/quality-gates-github.yml@v1 + secrets: inherit + # with: + # node-version: '24.16.0' # opzionale, default già impostato diff --git a/examples/microservizio/release-github.yml b/examples/microservizio/release-github.yml new file mode 100644 index 0000000..384436a --- /dev/null +++ b/examples/microservizio/release-github.yml @@ -0,0 +1,25 @@ +# Copia in: .gitea/workflows/release.yml +# Trigger: git tag v* → build Docker + crea release Gitea +# +# NOTA: auto-release attende docker-release via needs. +# Workaround Gitea bug #31900: token esplicito nel checkout di auto-release.yml. + +name: Release + +on: + push: + tags: + - 'v*' + +jobs: + docker-release: + runs-on: catthehacker-latest # workaround Gitea bug #34986: runs-on non rispettato in workflow_call + uses: https://gitea.pzetatouch.it/devops/shared-actions/.gitea/workflows/docker-release-github.yml@v1 + secrets: inherit + with: + runner: catthehacker-latest # runner con Docker pre-installato + + auto-release: + needs: [docker-release] + uses: https://gitea.pzetatouch.it/devops/shared-actions/.gitea/workflows/auto-release-github.yml@v1 + secrets: inherit diff --git a/examples/python/ci-github.yml b/examples/python/ci-github.yml new file mode 100644 index 0000000..454ea77 --- /dev/null +++ b/examples/python/ci-github.yml @@ -0,0 +1,31 @@ +# Copia in: .gitea/workflows/ci.yml +# Usato da: microservizi Python con FastAPI / pyproject.toml +# +# Requisiti pyproject.toml: +# [project.optional-dependencies] +# dev = ["ruff", "mypy", "pytest", ...] +# +# Input opzionali: +# python-version: '3.11' # default già impostato +# install-extras: 'dev' # default già impostato + +name: CI + +on: + push: + branches: + - main + paths-ignore: + - '**.md' + - 'docs/**' + pull_request: + branches: + - main + +jobs: + quality-gates: + uses: https://gitea.pzetatouch.it/devops/shared-actions/.gitea/workflows/python-quality-gates-github.yml@v1 + secrets: inherit + # with: + # python-version: '3.11' # opzionale, default già impostato + # install-extras: 'dev' # opzionale, default già impostato diff --git a/examples/python/release-github.yml b/examples/python/release-github.yml new file mode 100644 index 0000000..c19b0ca --- /dev/null +++ b/examples/python/release-github.yml @@ -0,0 +1,32 @@ +# Copia in: .gitea/workflows/release.yml +# Trigger: git tag v* → build Docker + crea release Gitea +# +# NOTA: auto-release attende docker-release via needs. +# Workaround Gitea bug #31900: token esplicito nel checkout di python-auto-release.yml. +# +# Prerequisiti: +# - Dockerfile presente nella root del progetto +# - pyproject.toml con [project] name e version +# - Secrets: G_USER (docker login), NPM_TOKEN (usato come password registry) + +name: Release + +on: + push: + tags: + - 'v*' + +jobs: + docker-release: + runs-on: catthehacker-latest # workaround Gitea bug #34986: runs-on non rispettato in workflow_call + uses: https://gitea.pzetatouch.it/devops/shared-actions/.gitea/workflows/python-docker-release-github.yml@v1 + secrets: inherit + with: + runner: catthehacker-latest # runner con Docker pre-installato + # python-version: '3.11' # opzionale + # install-extras: 'dev' # opzionale + + auto-release: + needs: [docker-release] + uses: https://gitea.pzetatouch.it/devops/shared-actions/.gitea/workflows/python-auto-release-github.yml@v1 + secrets: inherit