Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b94bd6936a | ||
|
|
5973ec9fcc | ||
|
|
715860c357 | ||
|
|
9b5159d89e | ||
|
|
c593f29b0f | ||
|
|
8949bc7f31 | ||
|
|
81c871422e | ||
|
|
67fccd84e2 | ||
|
|
6aca13b460 | ||
|
|
c1a4b2723f | ||
|
|
c0524722e4 | ||
|
|
dae2a74437 | ||
|
|
f0896d775d | ||
|
|
e5411d9d2d | ||
|
|
94767592c5 | ||
|
|
0fc0251233 | ||
|
|
b609947f46 | ||
|
|
b21c3877c6 | ||
|
|
392cdf2580 | ||
|
|
0ed7e2b58a | ||
|
|
3b49d18d5b | ||
|
|
53b1c7a9c4 | ||
|
|
0f7688ac5e | ||
|
|
54c74d9c6a | ||
|
|
86a0cd416f | ||
|
|
3ee135b020 |
@@ -0,0 +1,59 @@
|
|||||||
|
name: Auto Release
|
||||||
|
|
||||||
|
on:
|
||||||
|
workflow_call:
|
||||||
|
inputs:
|
||||||
|
working-directory:
|
||||||
|
description: 'Cartella che contiene package.json, relativa alla root del repo. Default: la root.'
|
||||||
|
type: string
|
||||||
|
default: '.'
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
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: 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
|
||||||
|
}"
|
||||||
@@ -2,15 +2,24 @@ name: Auto Release
|
|||||||
|
|
||||||
on:
|
on:
|
||||||
workflow_call:
|
workflow_call:
|
||||||
|
inputs:
|
||||||
|
working-directory:
|
||||||
|
description: 'Cartella che contiene package.json, relativa alla root del repo. Default: la root.'
|
||||||
|
type: string
|
||||||
|
default: '.'
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
auto-release:
|
auto-release:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
|
defaults:
|
||||||
|
run:
|
||||||
|
working-directory: ${{ inputs.working-directory || '.' }}
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
uses: https://gitea.com/actions/checkout@v4
|
uses: https://gitea.com/actions/checkout@v6
|
||||||
with:
|
with:
|
||||||
fetch-depth: 0
|
fetch-depth: 0
|
||||||
|
token: ${{ gitea.token }}
|
||||||
|
|
||||||
- name: Generate changelog
|
- name: Generate changelog
|
||||||
id: changelog
|
id: changelog
|
||||||
|
|||||||
@@ -0,0 +1,261 @@
|
|||||||
|
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'
|
||||||
|
version-code:
|
||||||
|
description: 'versionCode Android esplicito. Se vuoto viene derivato da package.json: major*10000 + minor*100 + patch'
|
||||||
|
type: string
|
||||||
|
default: ''
|
||||||
|
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
|
||||||
|
|
||||||
|
# La piattaforma Android puo essere generata da 'cap add' (default Capacitor:
|
||||||
|
# versionName "1.0", versionCode 1) oppure versionata nel repo consumer.
|
||||||
|
# In entrambi i casi la versione pubblicata deve derivare da package.json,
|
||||||
|
# unica fonte di verita, altrimenti l'APK/AAB dichiara una versione diversa
|
||||||
|
# da quella del tag e Play Store rifiuta upload con versionCode non crescente.
|
||||||
|
- name: Inject Android version
|
||||||
|
id: android-version
|
||||||
|
env:
|
||||||
|
PKG_VERSION: ${{ steps.app-info.outputs.version }}
|
||||||
|
VERSION_CODE_OVERRIDE: ${{ inputs.version-code }}
|
||||||
|
run: |
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
if [ -f android/app/build.gradle ]; then
|
||||||
|
GRADLE_FILE="android/app/build.gradle"
|
||||||
|
KTS=0
|
||||||
|
elif [ -f android/app/build.gradle.kts ]; then
|
||||||
|
GRADLE_FILE="android/app/build.gradle.kts"
|
||||||
|
KTS=1
|
||||||
|
else
|
||||||
|
echo "::error::Nessun build.gradle in android/app/ — piattaforma Android non generata"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
VERSION_NAME="$PKG_VERSION"
|
||||||
|
|
||||||
|
if [ -n "$VERSION_CODE_OVERRIDE" ]; then
|
||||||
|
VERSION_CODE="$VERSION_CODE_OVERRIDE"
|
||||||
|
else
|
||||||
|
CORE="${PKG_VERSION%%-*}" # scarta il pre-release: 1.2.3-beta.1 -> 1.2.3
|
||||||
|
CORE="${CORE%%+*}" # scarta il build metadata: 1.2.3+abc -> 1.2.3
|
||||||
|
MAJOR="$(echo "$CORE" | cut -d. -f1)"
|
||||||
|
MINOR="$(echo "$CORE" | cut -d. -f2)"
|
||||||
|
PATCH="$(echo "$CORE" | cut -d. -f3)"
|
||||||
|
MINOR="${MINOR:-0}"
|
||||||
|
PATCH="${PATCH:-0}"
|
||||||
|
|
||||||
|
case "${MAJOR}${MINOR}${PATCH}" in
|
||||||
|
''|*[!0-9]*)
|
||||||
|
echo "::error::Versione package.json non semver: '$PKG_VERSION'. Passare version-code esplicito."
|
||||||
|
exit 1
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
if [ "$MINOR" -gt 99 ] || [ "$PATCH" -gt 99 ]; then
|
||||||
|
echo "::error::minor/patch > 99 non rappresentabili ('$PKG_VERSION'). Passare version-code esplicito."
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
VERSION_CODE=$(( MAJOR * 10000 + MINOR * 100 + PATCH ))
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ "$KTS" -eq 1 ]; then
|
||||||
|
sed -i -E "s/versionCode[[:space:]]*=[[:space:]]*[0-9]+/versionCode = ${VERSION_CODE}/" "$GRADLE_FILE"
|
||||||
|
sed -i -E "s/versionName[[:space:]]*=[[:space:]]*\"[^\"]*\"/versionName = \"${VERSION_NAME}\"/" "$GRADLE_FILE"
|
||||||
|
else
|
||||||
|
sed -i -E "s/versionCode[[:space:]]+[0-9]+/versionCode ${VERSION_CODE}/" "$GRADLE_FILE"
|
||||||
|
sed -i -E "s/versionName[[:space:]]+\"[^\"]*\"/versionName \"${VERSION_NAME}\"/" "$GRADLE_FILE"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Il sed silenzioso e' peggio di un fallimento: senza questa verifica una
|
||||||
|
# variazione del template Capacitor produrrebbe build con versione sbagliata.
|
||||||
|
# Si confrontano i valori estratti, non si rilegge il file con una regex
|
||||||
|
# costruita sulla versione: '+' e '.' di un semver sono metacaratteri ERE.
|
||||||
|
# '|| true': senza, pipefail farebbe uscire lo step su un file privo di
|
||||||
|
# versionCode/versionName, perdendo la diagnostica del blocco sottostante.
|
||||||
|
ACTUAL_CODE="$(grep -oE 'versionCode[[:space:]]*=?[[:space:]]*[0-9]+' "$GRADLE_FILE" | head -1 | grep -oE '[0-9]+$' || true)"
|
||||||
|
ACTUAL_NAME="$(grep -oE 'versionName[[:space:]]*=?[[:space:]]*"[^"]*"' "$GRADLE_FILE" | head -1 | cut -d'"' -f2 || true)"
|
||||||
|
|
||||||
|
if [ "$ACTUAL_CODE" != "$VERSION_CODE" ] || [ "$ACTUAL_NAME" != "$VERSION_NAME" ]; then
|
||||||
|
echo "::error::Iniezione versione fallita in $GRADLE_FILE"
|
||||||
|
echo " atteso: versionName='${VERSION_NAME}' versionCode=${VERSION_CODE}"
|
||||||
|
echo " trovato: versionName='${ACTUAL_NAME}' versionCode=${ACTUAL_CODE}"
|
||||||
|
grep -nE 'versionCode|versionName' "$GRADLE_FILE" || true
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "version-name=${VERSION_NAME}" >> $GITHUB_OUTPUT
|
||||||
|
echo "version-code=${VERSION_CODE}" >> $GITHUB_OUTPUT
|
||||||
|
echo "Android: versionName=${VERSION_NAME} versionCode=${VERSION_CODE} ($GRADLE_FILE)"
|
||||||
|
|
||||||
|
- 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
|
||||||
|
|
||||||
|
# Il wrapper arriva dal repo senza bit di esecuzione quando il progetto e'
|
||||||
|
# committato da Windows: git registra mode 100644 e il checkout sul runner
|
||||||
|
# Linux produce "./gradlew: Permission denied". Il chmod qui vale per ogni
|
||||||
|
# repo Capacitor, cosi' il difetto non va rincorso uno per uno.
|
||||||
|
- name: Rendi eseguibile gradlew
|
||||||
|
run: chmod +x android/gradlew
|
||||||
|
|
||||||
|
- 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
|
||||||
@@ -5,7 +5,7 @@ on:
|
|||||||
inputs:
|
inputs:
|
||||||
node-version:
|
node-version:
|
||||||
type: string
|
type: string
|
||||||
default: '22.17'
|
default: '24.16.0'
|
||||||
java-version:
|
java-version:
|
||||||
type: string
|
type: string
|
||||||
default: '21'
|
default: '21'
|
||||||
@@ -20,6 +20,10 @@ on:
|
|||||||
description: 'apk (sideload/test) | aab (Play Store)'
|
description: 'apk (sideload/test) | aab (Play Store)'
|
||||||
type: string
|
type: string
|
||||||
default: 'apk'
|
default: 'apk'
|
||||||
|
version-code:
|
||||||
|
description: 'versionCode Android esplicito. Se vuoto viene derivato da package.json: major*10000 + minor*100 + patch'
|
||||||
|
type: string
|
||||||
|
default: ''
|
||||||
secrets:
|
secrets:
|
||||||
NPM_TOKEN:
|
NPM_TOKEN:
|
||||||
required: false
|
required: false
|
||||||
@@ -39,12 +43,12 @@ jobs:
|
|||||||
runs-on: ${{ inputs.runner }}
|
runs-on: ${{ inputs.runner }}
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
uses: https://gitea.com/actions/checkout@v4
|
uses: https://gitea.com/actions/checkout@v6
|
||||||
|
|
||||||
- name: Setup Node.js
|
- name: Setup Node.js
|
||||||
uses: https://gitea.com/actions/setup-node@v4
|
uses: https://gitea.com/actions/setup-node@v4
|
||||||
with:
|
with:
|
||||||
node-version: ${{ inputs.node-version || '22.17' }}
|
node-version: ${{ inputs.node-version || '24.16.0' }}
|
||||||
|
|
||||||
- name: Setup Java
|
- name: Setup Java
|
||||||
uses: https://github.com/actions/setup-java@v4
|
uses: https://github.com/actions/setup-java@v4
|
||||||
@@ -53,10 +57,10 @@ jobs:
|
|||||||
java-version: ${{ inputs.java-version || '17' }}
|
java-version: ${{ inputs.java-version || '17' }}
|
||||||
|
|
||||||
- name: Setup Android SDK
|
- name: Setup Android SDK
|
||||||
uses: https://github.com/android-actions/setup-android@v3
|
uses: https://github.com/android-actions/setup-android@v4
|
||||||
|
|
||||||
- name: Cache npm
|
- name: Cache npm
|
||||||
uses: https://gitea.com/actions/cache@v4
|
uses: https://github.com/actions/cache@v4
|
||||||
with:
|
with:
|
||||||
path: ~/.npm
|
path: ~/.npm
|
||||||
key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }}
|
key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }}
|
||||||
@@ -64,7 +68,7 @@ jobs:
|
|||||||
${{ runner.os }}-node-
|
${{ runner.os }}-node-
|
||||||
|
|
||||||
- name: Cache Gradle
|
- name: Cache Gradle
|
||||||
uses: https://gitea.com/actions/cache@v4
|
uses: https://github.com/actions/cache@v4
|
||||||
with:
|
with:
|
||||||
path: |
|
path: |
|
||||||
~/.gradle/caches
|
~/.gradle/caches
|
||||||
@@ -75,14 +79,14 @@ jobs:
|
|||||||
|
|
||||||
- name: Configure npm private registry
|
- name: Configure npm private registry
|
||||||
run: |
|
run: |
|
||||||
echo "@pzeta:registry=https://gitea.pzetatouch.it/api/packages/pzeta_touch/npm/" >> ~/.npmrc
|
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
|
echo "//gitea.pzetatouch.it/api/packages/PZeta_Touch/npm/:_authToken=${{ secrets.NPM_TOKEN }}" >> ~/.npmrc
|
||||||
|
|
||||||
- name: Read app info from package.json
|
- name: Read app info from package.json
|
||||||
id: app-info
|
id: app-info
|
||||||
run: |
|
run: |
|
||||||
echo "name=$(node -e \"console.log(require('./package.json').name)\")" >> $GITHUB_OUTPUT
|
echo "name=$(jq -r '.name' package.json)" >> $GITHUB_OUTPUT
|
||||||
echo "version=$(node -e \"console.log(require('./package.json').version)\")" >> $GITHUB_OUTPUT
|
echo "version=$(jq -r '.version' package.json)" >> $GITHUB_OUTPUT
|
||||||
|
|
||||||
- name: Install dependencies
|
- name: Install dependencies
|
||||||
run: npm ci
|
run: npm ci
|
||||||
@@ -96,6 +100,87 @@ jobs:
|
|||||||
- name: Sync Capacitor
|
- name: Sync Capacitor
|
||||||
run: npx cap sync android
|
run: npx cap sync android
|
||||||
|
|
||||||
|
# La piattaforma Android puo essere generata da 'cap add' (default Capacitor:
|
||||||
|
# versionName "1.0", versionCode 1) oppure versionata nel repo consumer.
|
||||||
|
# In entrambi i casi la versione pubblicata deve derivare da package.json,
|
||||||
|
# unica fonte di verita, altrimenti l'APK/AAB dichiara una versione diversa
|
||||||
|
# da quella del tag e Play Store rifiuta upload con versionCode non crescente.
|
||||||
|
- name: Inject Android version
|
||||||
|
id: android-version
|
||||||
|
env:
|
||||||
|
PKG_VERSION: ${{ steps.app-info.outputs.version }}
|
||||||
|
VERSION_CODE_OVERRIDE: ${{ inputs.version-code }}
|
||||||
|
run: |
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
if [ -f android/app/build.gradle ]; then
|
||||||
|
GRADLE_FILE="android/app/build.gradle"
|
||||||
|
KTS=0
|
||||||
|
elif [ -f android/app/build.gradle.kts ]; then
|
||||||
|
GRADLE_FILE="android/app/build.gradle.kts"
|
||||||
|
KTS=1
|
||||||
|
else
|
||||||
|
echo "::error::Nessun build.gradle in android/app/ — piattaforma Android non generata"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
VERSION_NAME="$PKG_VERSION"
|
||||||
|
|
||||||
|
if [ -n "$VERSION_CODE_OVERRIDE" ]; then
|
||||||
|
VERSION_CODE="$VERSION_CODE_OVERRIDE"
|
||||||
|
else
|
||||||
|
CORE="${PKG_VERSION%%-*}" # scarta il pre-release: 1.2.3-beta.1 -> 1.2.3
|
||||||
|
CORE="${CORE%%+*}" # scarta il build metadata: 1.2.3+abc -> 1.2.3
|
||||||
|
MAJOR="$(echo "$CORE" | cut -d. -f1)"
|
||||||
|
MINOR="$(echo "$CORE" | cut -d. -f2)"
|
||||||
|
PATCH="$(echo "$CORE" | cut -d. -f3)"
|
||||||
|
MINOR="${MINOR:-0}"
|
||||||
|
PATCH="${PATCH:-0}"
|
||||||
|
|
||||||
|
case "${MAJOR}${MINOR}${PATCH}" in
|
||||||
|
''|*[!0-9]*)
|
||||||
|
echo "::error::Versione package.json non semver: '$PKG_VERSION'. Passare version-code esplicito."
|
||||||
|
exit 1
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
if [ "$MINOR" -gt 99 ] || [ "$PATCH" -gt 99 ]; then
|
||||||
|
echo "::error::minor/patch > 99 non rappresentabili ('$PKG_VERSION'). Passare version-code esplicito."
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
VERSION_CODE=$(( MAJOR * 10000 + MINOR * 100 + PATCH ))
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ "$KTS" -eq 1 ]; then
|
||||||
|
sed -i -E "s/versionCode[[:space:]]*=[[:space:]]*[0-9]+/versionCode = ${VERSION_CODE}/" "$GRADLE_FILE"
|
||||||
|
sed -i -E "s/versionName[[:space:]]*=[[:space:]]*\"[^\"]*\"/versionName = \"${VERSION_NAME}\"/" "$GRADLE_FILE"
|
||||||
|
else
|
||||||
|
sed -i -E "s/versionCode[[:space:]]+[0-9]+/versionCode ${VERSION_CODE}/" "$GRADLE_FILE"
|
||||||
|
sed -i -E "s/versionName[[:space:]]+\"[^\"]*\"/versionName \"${VERSION_NAME}\"/" "$GRADLE_FILE"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Il sed silenzioso e' peggio di un fallimento: senza questa verifica una
|
||||||
|
# variazione del template Capacitor produrrebbe build con versione sbagliata.
|
||||||
|
# Si confrontano i valori estratti, non si rilegge il file con una regex
|
||||||
|
# costruita sulla versione: '+' e '.' di un semver sono metacaratteri ERE.
|
||||||
|
# '|| true': senza, pipefail farebbe uscire lo step su un file privo di
|
||||||
|
# versionCode/versionName, perdendo la diagnostica del blocco sottostante.
|
||||||
|
ACTUAL_CODE="$(grep -oE 'versionCode[[:space:]]*=?[[:space:]]*[0-9]+' "$GRADLE_FILE" | head -1 | grep -oE '[0-9]+$' || true)"
|
||||||
|
ACTUAL_NAME="$(grep -oE 'versionName[[:space:]]*=?[[:space:]]*"[^"]*"' "$GRADLE_FILE" | head -1 | cut -d'"' -f2 || true)"
|
||||||
|
|
||||||
|
if [ "$ACTUAL_CODE" != "$VERSION_CODE" ] || [ "$ACTUAL_NAME" != "$VERSION_NAME" ]; then
|
||||||
|
echo "::error::Iniezione versione fallita in $GRADLE_FILE"
|
||||||
|
echo " atteso: versionName='${VERSION_NAME}' versionCode=${VERSION_CODE}"
|
||||||
|
echo " trovato: versionName='${ACTUAL_NAME}' versionCode=${ACTUAL_CODE}"
|
||||||
|
grep -nE 'versionCode|versionName' "$GRADLE_FILE" || true
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "version-name=${VERSION_NAME}" >> $GITHUB_OUTPUT
|
||||||
|
echo "version-code=${VERSION_CODE}" >> $GITHUB_OUTPUT
|
||||||
|
echo "Android: versionName=${VERSION_NAME} versionCode=${VERSION_CODE} ($GRADLE_FILE)"
|
||||||
|
|
||||||
- name: Setup google-services.json
|
- name: Setup google-services.json
|
||||||
if: secrets.GOOGLE_SERVICES_JSON != ''
|
if: secrets.GOOGLE_SERVICES_JSON != ''
|
||||||
run: echo '${{ secrets.GOOGLE_SERVICES_JSON }}' > android/app/google-services.json
|
run: echo '${{ secrets.GOOGLE_SERVICES_JSON }}' > android/app/google-services.json
|
||||||
@@ -104,6 +189,13 @@ jobs:
|
|||||||
if: inputs.build-type == 'release'
|
if: inputs.build-type == 'release'
|
||||||
run: echo '${{ secrets.KEYSTORE_BASE64 }}' | base64 -d > android/app/keystore.jks
|
run: echo '${{ secrets.KEYSTORE_BASE64 }}' | base64 -d > android/app/keystore.jks
|
||||||
|
|
||||||
|
# Il wrapper arriva dal repo senza bit di esecuzione quando il progetto e'
|
||||||
|
# committato da Windows: git registra mode 100644 e il checkout sul runner
|
||||||
|
# Linux produce "./gradlew: Permission denied". Il chmod qui vale per ogni
|
||||||
|
# repo Capacitor, cosi' il difetto non va rincorso uno per uno.
|
||||||
|
- name: Rendi eseguibile gradlew
|
||||||
|
run: chmod +x android/gradlew
|
||||||
|
|
||||||
- name: Build Android (APK)
|
- name: Build Android (APK)
|
||||||
if: inputs.output-format == 'apk'
|
if: inputs.output-format == 'apk'
|
||||||
working-directory: android
|
working-directory: android
|
||||||
@@ -145,7 +237,7 @@ jobs:
|
|||||||
|
|
||||||
- name: Upload APK artifact
|
- name: Upload APK artifact
|
||||||
if: inputs.output-format == 'apk'
|
if: inputs.output-format == 'apk'
|
||||||
uses: https://github.com/actions/upload-artifact@v3
|
uses: https://gitea.com/actions/upload-artifact@v3
|
||||||
with:
|
with:
|
||||||
name: ${{ steps.app-info.outputs.name }}-${{ steps.app-info.outputs.version }}-${{ inputs.build-type }}-apk
|
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
|
path: android/app/build/outputs/apk/${{ inputs.build-type }}/${{ steps.app-info.outputs.name }}-${{ steps.app-info.outputs.version }}-${{ inputs.build-type }}.apk
|
||||||
@@ -153,7 +245,7 @@ jobs:
|
|||||||
|
|
||||||
- name: Upload AAB artifact
|
- name: Upload AAB artifact
|
||||||
if: inputs.output-format == 'aab'
|
if: inputs.output-format == 'aab'
|
||||||
uses: https://github.com/actions/upload-artifact@v3
|
uses: https://gitea.com/actions/upload-artifact@v3
|
||||||
with:
|
with:
|
||||||
name: ${{ steps.app-info.outputs.name }}-${{ steps.app-info.outputs.version }}-release-aab
|
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
|
path: android/app/build/outputs/bundle/release/${{ steps.app-info.outputs.name }}-${{ steps.app-info.outputs.version }}-release.aab
|
||||||
@@ -161,7 +253,7 @@ jobs:
|
|||||||
|
|
||||||
- name: Upload Gradle build reports
|
- name: Upload Gradle build reports
|
||||||
if: always()
|
if: always()
|
||||||
uses: https://github.com/actions/upload-artifact@v3
|
uses: https://gitea.com/actions/upload-artifact@v3
|
||||||
with:
|
with:
|
||||||
name: gradle-build-reports
|
name: gradle-build-reports
|
||||||
path: android/build/reports/
|
path: android/build/reports/
|
||||||
|
|||||||
@@ -0,0 +1,75 @@
|
|||||||
|
name: Dependency Audit
|
||||||
|
|
||||||
|
on:
|
||||||
|
workflow_call:
|
||||||
|
inputs:
|
||||||
|
working-directory:
|
||||||
|
description: 'Cartella che contiene package.json, relativa alla root del repo. Default: la root.'
|
||||||
|
type: string
|
||||||
|
default: '.'
|
||||||
|
node-version:
|
||||||
|
type: string
|
||||||
|
default: '24.16.0'
|
||||||
|
workflow_dispatch:
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
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 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)
|
||||||
|
}"
|
||||||
@@ -3,25 +3,32 @@ name: Dependency Audit
|
|||||||
on:
|
on:
|
||||||
workflow_call:
|
workflow_call:
|
||||||
inputs:
|
inputs:
|
||||||
|
working-directory:
|
||||||
|
description: 'Cartella che contiene package.json, relativa alla root del repo. Default: la root.'
|
||||||
|
type: string
|
||||||
|
default: '.'
|
||||||
node-version:
|
node-version:
|
||||||
type: string
|
type: string
|
||||||
default: '22.17'
|
default: '24.16.0'
|
||||||
workflow_dispatch:
|
workflow_dispatch:
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
dependency-audit:
|
dependency-audit:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
|
defaults:
|
||||||
|
run:
|
||||||
|
working-directory: ${{ inputs.working-directory || '.' }}
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
uses: https://gitea.com/actions/checkout@v4
|
uses: https://gitea.com/actions/checkout@v6
|
||||||
|
|
||||||
- name: Setup Node.js
|
- name: Setup Node.js
|
||||||
uses: https://gitea.com/actions/setup-node@v4
|
uses: https://gitea.com/actions/setup-node@v4
|
||||||
with:
|
with:
|
||||||
node-version: ${{ inputs.node-version || '22.17' }}
|
node-version: ${{ inputs.node-version || '24.16.0' }}
|
||||||
|
|
||||||
- name: Cache npm
|
- name: Cache npm
|
||||||
uses: https://gitea.com/actions/cache@v4
|
uses: https://github.com/actions/cache@v4
|
||||||
with:
|
with:
|
||||||
path: ~/.npm
|
path: ~/.npm
|
||||||
key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }}
|
key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }}
|
||||||
@@ -30,8 +37,8 @@ jobs:
|
|||||||
|
|
||||||
- name: Configure npm private registry
|
- name: Configure npm private registry
|
||||||
run: |
|
run: |
|
||||||
echo "@pzeta:registry=https://gitea.pzetatouch.it/api/packages/pzeta_touch/npm/" >> ~/.npmrc
|
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
|
echo "//gitea.pzetatouch.it/api/packages/PZeta_Touch/npm/:_authToken=${{ secrets.NPM_TOKEN }}" >> ~/.npmrc
|
||||||
|
|
||||||
- name: Install dependencies
|
- name: Install dependencies
|
||||||
run: npm ci
|
run: npm ci
|
||||||
|
|||||||
@@ -0,0 +1,75 @@
|
|||||||
|
name: Dependency Outdated
|
||||||
|
|
||||||
|
on:
|
||||||
|
workflow_call:
|
||||||
|
inputs:
|
||||||
|
working-directory:
|
||||||
|
description: 'Cartella che contiene package.json, relativa alla root del repo. Default: la root.'
|
||||||
|
type: string
|
||||||
|
default: '.'
|
||||||
|
node-version:
|
||||||
|
type: string
|
||||||
|
default: '24.16.0'
|
||||||
|
workflow_dispatch:
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
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 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)
|
||||||
|
}"
|
||||||
@@ -3,25 +3,32 @@ name: Dependency Outdated
|
|||||||
on:
|
on:
|
||||||
workflow_call:
|
workflow_call:
|
||||||
inputs:
|
inputs:
|
||||||
|
working-directory:
|
||||||
|
description: 'Cartella che contiene package.json, relativa alla root del repo. Default: la root.'
|
||||||
|
type: string
|
||||||
|
default: '.'
|
||||||
node-version:
|
node-version:
|
||||||
type: string
|
type: string
|
||||||
default: '22.17'
|
default: '24.16.0'
|
||||||
workflow_dispatch:
|
workflow_dispatch:
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
dependency-outdated:
|
dependency-outdated:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
|
defaults:
|
||||||
|
run:
|
||||||
|
working-directory: ${{ inputs.working-directory || '.' }}
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
uses: https://gitea.com/actions/checkout@v4
|
uses: https://gitea.com/actions/checkout@v6
|
||||||
|
|
||||||
- name: Setup Node.js
|
- name: Setup Node.js
|
||||||
uses: https://gitea.com/actions/setup-node@v4
|
uses: https://gitea.com/actions/setup-node@v4
|
||||||
with:
|
with:
|
||||||
node-version: ${{ inputs.node-version || '22.17' }}
|
node-version: ${{ inputs.node-version || '24.16.0' }}
|
||||||
|
|
||||||
- name: Cache npm
|
- name: Cache npm
|
||||||
uses: https://gitea.com/actions/cache@v4
|
uses: https://github.com/actions/cache@v4
|
||||||
with:
|
with:
|
||||||
path: ~/.npm
|
path: ~/.npm
|
||||||
key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }}
|
key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }}
|
||||||
@@ -30,8 +37,8 @@ jobs:
|
|||||||
|
|
||||||
- name: Configure npm private registry
|
- name: Configure npm private registry
|
||||||
run: |
|
run: |
|
||||||
echo "@pzeta:registry=https://gitea.pzetatouch.it/api/packages/pzeta_touch/npm/" >> ~/.npmrc
|
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
|
echo "//gitea.pzetatouch.it/api/packages/PZeta_Touch/npm/:_authToken=${{ secrets.NPM_TOKEN }}" >> ~/.npmrc
|
||||||
|
|
||||||
- name: Install dependencies
|
- name: Install dependencies
|
||||||
run: npm ci
|
run: npm ci
|
||||||
|
|||||||
@@ -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 }}
|
||||||
@@ -5,7 +5,10 @@ on:
|
|||||||
inputs:
|
inputs:
|
||||||
node-version:
|
node-version:
|
||||||
type: string
|
type: string
|
||||||
default: '22.17'
|
default: '24.16.0'
|
||||||
|
npm-version:
|
||||||
|
type: string
|
||||||
|
default: ''
|
||||||
runner:
|
runner:
|
||||||
type: string
|
type: string
|
||||||
default: 'catthehacker-latest'
|
default: 'catthehacker-latest'
|
||||||
@@ -15,15 +18,19 @@ jobs:
|
|||||||
runs-on: ${{ inputs.runner }}
|
runs-on: ${{ inputs.runner }}
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
uses: https://gitea.com/actions/checkout@v4
|
uses: https://gitea.com/actions/checkout@v6
|
||||||
|
|
||||||
- name: Setup Node.js
|
- name: Setup Node.js
|
||||||
uses: https://gitea.com/actions/setup-node@v4
|
uses: https://gitea.com/actions/setup-node@v4
|
||||||
with:
|
with:
|
||||||
node-version: ${{ inputs.node-version || '22.17' }}
|
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
|
- name: Cache npm
|
||||||
uses: https://gitea.com/actions/cache@v4
|
uses: https://github.com/actions/cache@v4
|
||||||
with:
|
with:
|
||||||
path: ~/.npm
|
path: ~/.npm
|
||||||
key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }}
|
key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }}
|
||||||
@@ -32,8 +39,8 @@ jobs:
|
|||||||
|
|
||||||
- name: Configure npm private registry
|
- name: Configure npm private registry
|
||||||
run: |
|
run: |
|
||||||
echo "@pzeta:registry=https://gitea.pzetatouch.it/api/packages/pzeta_touch/npm/" >> ~/.npmrc
|
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
|
echo "//gitea.pzetatouch.it/api/packages/PZeta_Touch/npm/:_authToken=${{ secrets.NPM_TOKEN }}" >> ~/.npmrc
|
||||||
|
|
||||||
- name: Install dependencies
|
- name: Install dependencies
|
||||||
run: npm ci
|
run: npm ci
|
||||||
@@ -54,7 +61,7 @@ jobs:
|
|||||||
run: npm run test
|
run: npm run test
|
||||||
|
|
||||||
- name: Login to container registry
|
- name: Login to container registry
|
||||||
uses: https://gitea.com/docker/login-action@v3
|
uses: https://gitea.com/docker/login-action@v4
|
||||||
with:
|
with:
|
||||||
registry: gitea.pzetatouch.it
|
registry: gitea.pzetatouch.it
|
||||||
username: ${{ secrets.G_USER }}
|
username: ${{ secrets.G_USER }}
|
||||||
@@ -69,6 +76,7 @@ jobs:
|
|||||||
REGISTRY="gitea.pzetatouch.it/pzeta_touch"
|
REGISTRY="gitea.pzetatouch.it/pzeta_touch"
|
||||||
echo "version_tag=${REGISTRY}/${APP_NAME}:${VERSION}" >> $GITHUB_OUTPUT
|
echo "version_tag=${REGISTRY}/${APP_NAME}:${VERSION}" >> $GITHUB_OUTPUT
|
||||||
echo "latest_tag=${REGISTRY}/${APP_NAME}:latest" >> $GITHUB_OUTPUT
|
echo "latest_tag=${REGISTRY}/${APP_NAME}:latest" >> $GITHUB_OUTPUT
|
||||||
|
echo "version=${VERSION}" >> $GITHUB_OUTPUT
|
||||||
|
|
||||||
- name: Build and push Docker image
|
- name: Build and push Docker image
|
||||||
uses: https://gitea.com/docker/build-push-action@v6
|
uses: https://gitea.com/docker/build-push-action@v6
|
||||||
@@ -79,5 +87,13 @@ jobs:
|
|||||||
tags: |
|
tags: |
|
||||||
${{ steps.tags.outputs.version_tag }}
|
${{ steps.tags.outputs.version_tag }}
|
||||||
${{ steps.tags.outputs.latest_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: |
|
build-args: |
|
||||||
NPM_TOKEN=${{ secrets.NPM_TOKEN }}
|
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 }}
|
||||||
|
|||||||
@@ -0,0 +1,61 @@
|
|||||||
|
name: Publish npm Package
|
||||||
|
|
||||||
|
on:
|
||||||
|
workflow_call:
|
||||||
|
inputs:
|
||||||
|
working-directory:
|
||||||
|
description: 'Cartella che contiene package.json, relativa alla root del repo. Default: la root.'
|
||||||
|
type: string
|
||||||
|
default: '.'
|
||||||
|
node-version:
|
||||||
|
type: string
|
||||||
|
default: '24.16.0'
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
npm-publish:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
defaults:
|
||||||
|
run:
|
||||||
|
working-directory: ${{ inputs.working-directory || '.' }}
|
||||||
|
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
|
||||||
@@ -3,24 +3,31 @@ name: Publish npm Package
|
|||||||
on:
|
on:
|
||||||
workflow_call:
|
workflow_call:
|
||||||
inputs:
|
inputs:
|
||||||
|
working-directory:
|
||||||
|
description: 'Cartella che contiene package.json, relativa alla root del repo. Default: la root.'
|
||||||
|
type: string
|
||||||
|
default: '.'
|
||||||
node-version:
|
node-version:
|
||||||
type: string
|
type: string
|
||||||
default: '22.17'
|
default: '24.16.0'
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
npm-publish:
|
npm-publish:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
|
defaults:
|
||||||
|
run:
|
||||||
|
working-directory: ${{ inputs.working-directory || '.' }}
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
uses: https://gitea.com/actions/checkout@v4
|
uses: https://gitea.com/actions/checkout@v6
|
||||||
|
|
||||||
- name: Setup Node.js
|
- name: Setup Node.js
|
||||||
uses: https://gitea.com/actions/setup-node@v4
|
uses: https://gitea.com/actions/setup-node@v4
|
||||||
with:
|
with:
|
||||||
node-version: ${{ inputs.node-version || '22.17' }}
|
node-version: ${{ inputs.node-version || '24.16.0' }}
|
||||||
|
|
||||||
- name: Cache npm
|
- name: Cache npm
|
||||||
uses: https://gitea.com/actions/cache@v4
|
uses: https://github.com/actions/cache@v4
|
||||||
with:
|
with:
|
||||||
path: ~/.npm
|
path: ~/.npm
|
||||||
key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }}
|
key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }}
|
||||||
@@ -29,8 +36,8 @@ jobs:
|
|||||||
|
|
||||||
- name: Configure npm private registry
|
- name: Configure npm private registry
|
||||||
run: |
|
run: |
|
||||||
echo "@pzeta:registry=https://gitea.pzetatouch.it/api/packages/pzeta_touch/npm/" >> ~/.npmrc
|
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
|
echo "//gitea.pzetatouch.it/api/packages/PZeta_Touch/npm/:_authToken=${{ secrets.NPM_TOKEN }}" >> ~/.npmrc
|
||||||
|
|
||||||
- name: Install dependencies
|
- name: Install dependencies
|
||||||
run: npm ci
|
run: npm ci
|
||||||
|
|||||||
@@ -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
|
||||||
|
}"
|
||||||
@@ -16,9 +16,10 @@ jobs:
|
|||||||
working-directory: ${{ inputs.working-directory }}
|
working-directory: ${{ inputs.working-directory }}
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
uses: https://gitea.com/actions/checkout@v4
|
uses: https://gitea.com/actions/checkout@v6
|
||||||
with:
|
with:
|
||||||
fetch-depth: 0
|
fetch-depth: 0
|
||||||
|
token: ${{ gitea.token }}
|
||||||
|
|
||||||
- name: Generate changelog
|
- name: Generate changelog
|
||||||
id: changelog
|
id: changelog
|
||||||
|
|||||||
@@ -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
|
||||||
@@ -22,15 +22,15 @@ jobs:
|
|||||||
working-directory: ${{ inputs.working-directory }}
|
working-directory: ${{ inputs.working-directory }}
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
uses: https://gitea.com/actions/checkout@v4
|
uses: https://gitea.com/actions/checkout@v6
|
||||||
|
|
||||||
- name: Setup Python
|
- name: Setup Python
|
||||||
uses: https://github.com/actions/setup-python@v5
|
uses: https://github.com/actions/setup-python@v5.2.0
|
||||||
with:
|
with:
|
||||||
python-version: ${{ inputs.python-version || '3.11' }}
|
python-version: ${{ inputs.python-version || '3.11' }}
|
||||||
|
|
||||||
- name: Cache pip
|
- name: Cache pip
|
||||||
uses: https://gitea.com/actions/cache@v4
|
uses: https://github.com/actions/cache@v4
|
||||||
with:
|
with:
|
||||||
path: ~/.cache/pip
|
path: ~/.cache/pip
|
||||||
key: ${{ runner.os }}-pip-${{ inputs.python-version }}-${{ hashFiles('**/pyproject.toml', '**/requirements*.txt') }}
|
key: ${{ runner.os }}-pip-${{ inputs.python-version }}-${{ hashFiles('**/pyproject.toml', '**/requirements*.txt') }}
|
||||||
@@ -38,21 +38,24 @@ jobs:
|
|||||||
${{ runner.os }}-pip-${{ inputs.python-version }}-
|
${{ runner.os }}-pip-${{ inputs.python-version }}-
|
||||||
${{ runner.os }}-pip-
|
${{ runner.os }}-pip-
|
||||||
|
|
||||||
- name: Install dependencies
|
- name: Install dependencies (isolated venv)
|
||||||
run: |
|
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
|
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
|
elif [ -f requirements.txt ]; then
|
||||||
pip install -r requirements.txt
|
.audit-venv/bin/pip install -r requirements.txt
|
||||||
else
|
else
|
||||||
pip install -e "."
|
.audit-venv/bin/pip install -e "."
|
||||||
fi
|
fi
|
||||||
|
|
||||||
- name: Security audit (pip-audit)
|
- name: Security audit (pip-audit)
|
||||||
id: audit
|
id: audit
|
||||||
run: |
|
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 "
|
VULNS=$(python3 -c "
|
||||||
import json, sys
|
import json, sys
|
||||||
try:
|
try:
|
||||||
@@ -65,7 +68,7 @@ jobs:
|
|||||||
")
|
")
|
||||||
echo "vulnerabilities=$VULNS" >> $GITHUB_OUTPUT
|
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'
|
if: steps.audit.outputs.vulnerabilities != '0'
|
||||||
env:
|
env:
|
||||||
GITEA_TOKEN: ${{ gitea.token }}
|
GITEA_TOKEN: ${{ gitea.token }}
|
||||||
@@ -74,6 +77,7 @@ jobs:
|
|||||||
run: |
|
run: |
|
||||||
VULNS="${{ steps.audit.outputs.vulnerabilities }}"
|
VULNS="${{ steps.audit.outputs.vulnerabilities }}"
|
||||||
DATE=$(date '+%Y-%m-%d')
|
DATE=$(date '+%Y-%m-%d')
|
||||||
|
TITLE_PREFIX="Security Python:"
|
||||||
|
|
||||||
VULN_LIST=$(python3 -c "
|
VULN_LIST=$(python3 -c "
|
||||||
import json
|
import json
|
||||||
@@ -91,11 +95,26 @@ jobs:
|
|||||||
printf '## Security Audit Python — %s\n\n### Vulnerabilità trovate: %s\n\n```\n%s\n```\n' \
|
printf '## Security Audit Python — %s\n\n### Vulnerabilità trovate: %s\n\n```\n%s\n```\n' \
|
||||||
"$DATE" "$VULNS" "$VULN_LIST" > /tmp/body.md
|
"$DATE" "$VULNS" "$VULN_LIST" > /tmp/body.md
|
||||||
|
|
||||||
curl -s -X POST \
|
# Deduplica: se esiste già una issue aperta con lo stesso prefisso,
|
||||||
-H "Content-Type: application/json" \
|
# aggiungi un commento invece di aprirne una nuova
|
||||||
|
EXISTING=$(curl -s \
|
||||||
-H "Authorization: token $GITEA_TOKEN" \
|
-H "Authorization: token $GITEA_TOKEN" \
|
||||||
"$SERVER_URL/api/v1/repos/$REPOSITORY/issues" \
|
"$SERVER_URL/api/v1/repos/$REPOSITORY/issues?state=open&type=issues&limit=50" \
|
||||||
-d "{
|
| jq -r --arg p "$TITLE_PREFIX" '[.[] | select(.title | contains($p))] | (first // {}) | .number // empty')
|
||||||
\"title\": \"[$DATE] Security Python: $VULNS vulnerabilità rilevate\",
|
|
||||||
\"body\": $(jq -Rs . /tmp/body.md)
|
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
|
||||||
|
|||||||
@@ -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
|
||||||
@@ -22,15 +22,15 @@ jobs:
|
|||||||
working-directory: ${{ inputs.working-directory }}
|
working-directory: ${{ inputs.working-directory }}
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
uses: https://gitea.com/actions/checkout@v4
|
uses: https://gitea.com/actions/checkout@v6
|
||||||
|
|
||||||
- name: Setup Python
|
- name: Setup Python
|
||||||
uses: https://github.com/actions/setup-python@v5
|
uses: https://github.com/actions/setup-python@v5.2.0
|
||||||
with:
|
with:
|
||||||
python-version: ${{ inputs.python-version || '3.11' }}
|
python-version: ${{ inputs.python-version || '3.11' }}
|
||||||
|
|
||||||
- name: Cache pip
|
- name: Cache pip
|
||||||
uses: https://gitea.com/actions/cache@v4
|
uses: https://github.com/actions/cache@v4
|
||||||
with:
|
with:
|
||||||
path: ~/.cache/pip
|
path: ~/.cache/pip
|
||||||
key: ${{ runner.os }}-pip-${{ inputs.python-version }}-${{ hashFiles('**/pyproject.toml', '**/requirements*.txt') }}
|
key: ${{ runner.os }}-pip-${{ inputs.python-version }}-${{ hashFiles('**/pyproject.toml', '**/requirements*.txt') }}
|
||||||
@@ -38,25 +38,28 @@ jobs:
|
|||||||
${{ runner.os }}-pip-${{ inputs.python-version }}-
|
${{ runner.os }}-pip-${{ inputs.python-version }}-
|
||||||
${{ runner.os }}-pip-
|
${{ runner.os }}-pip-
|
||||||
|
|
||||||
- name: Install dependencies
|
- name: Install dependencies (isolated venv)
|
||||||
run: |
|
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
|
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
|
elif [ -f requirements.txt ]; then
|
||||||
pip install -r requirements.txt
|
.audit-venv/bin/pip install -r requirements.txt
|
||||||
else
|
else
|
||||||
pip install -e "."
|
.audit-venv/bin/pip install -e "."
|
||||||
fi
|
fi
|
||||||
|
|
||||||
- name: Check outdated packages
|
- name: Check outdated packages
|
||||||
id: outdated
|
id: outdated
|
||||||
run: |
|
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'))))")
|
COUNT=$(python3 -c "import json; print(len(json.load(open('outdated.json'))))")
|
||||||
echo "count=$COUNT" >> $GITHUB_OUTPUT
|
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'
|
if: steps.outdated.outputs.count != '0'
|
||||||
env:
|
env:
|
||||||
GITEA_TOKEN: ${{ gitea.token }}
|
GITEA_TOKEN: ${{ gitea.token }}
|
||||||
@@ -65,6 +68,7 @@ jobs:
|
|||||||
run: |
|
run: |
|
||||||
COUNT="${{ steps.outdated.outputs.count }}"
|
COUNT="${{ steps.outdated.outputs.count }}"
|
||||||
DATE=$(date '+%Y-%m-%d')
|
DATE=$(date '+%Y-%m-%d')
|
||||||
|
TITLE_PREFIX="Dipendenze Python:"
|
||||||
|
|
||||||
OUTDATED_LIST=$(python3 -c "
|
OUTDATED_LIST=$(python3 -c "
|
||||||
import json
|
import json
|
||||||
@@ -79,11 +83,26 @@ jobs:
|
|||||||
printf '## Dipendenze Python Obsolete — %s\n\n### Pacchetti da aggiornare: %s\n\n```\n%s\n```\n' \
|
printf '## Dipendenze Python Obsolete — %s\n\n### Pacchetti da aggiornare: %s\n\n```\n%s\n```\n' \
|
||||||
"$DATE" "$COUNT" "$OUTDATED_LIST" > /tmp/body.md
|
"$DATE" "$COUNT" "$OUTDATED_LIST" > /tmp/body.md
|
||||||
|
|
||||||
curl -s -X POST \
|
# Deduplica: se esiste già una issue aperta con lo stesso prefisso,
|
||||||
-H "Content-Type: application/json" \
|
# aggiungi un commento invece di aprirne una nuova
|
||||||
|
EXISTING=$(curl -s \
|
||||||
-H "Authorization: token $GITEA_TOKEN" \
|
-H "Authorization: token $GITEA_TOKEN" \
|
||||||
"$SERVER_URL/api/v1/repos/$REPOSITORY/issues" \
|
"$SERVER_URL/api/v1/repos/$REPOSITORY/issues?state=open&type=issues&limit=50" \
|
||||||
-d "{
|
| jq -r --arg p "$TITLE_PREFIX" '[.[] | select(.title | contains($p))] | (first // {}) | .number // empty')
|
||||||
\"title\": \"[$DATE] Dipendenze Python: $COUNT pacchetti obsoleti\",
|
|
||||||
\"body\": $(jq -Rs . /tmp/body.md)
|
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
|
||||||
|
|||||||
@@ -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 }}
|
||||||
@@ -30,15 +30,15 @@ jobs:
|
|||||||
working-directory: ${{ inputs.working-directory }}
|
working-directory: ${{ inputs.working-directory }}
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
uses: https://gitea.com/actions/checkout@v4
|
uses: https://gitea.com/actions/checkout@v6
|
||||||
|
|
||||||
- name: Setup Python
|
- name: Setup Python
|
||||||
uses: https://github.com/actions/setup-python@v5
|
uses: https://github.com/actions/setup-python@v5.2.0
|
||||||
with:
|
with:
|
||||||
python-version: ${{ inputs.python-version || '3.11' }}
|
python-version: ${{ inputs.python-version || '3.11' }}
|
||||||
|
|
||||||
- name: Cache pip
|
- name: Cache pip
|
||||||
uses: https://gitea.com/actions/cache@v4
|
uses: https://github.com/actions/cache@v4
|
||||||
with:
|
with:
|
||||||
path: ~/.cache/pip
|
path: ~/.cache/pip
|
||||||
key: ${{ runner.os }}-pip-${{ inputs.python-version }}-${{ hashFiles('**/pyproject.toml', '**/requirements*.txt') }}
|
key: ${{ runner.os }}-pip-${{ inputs.python-version }}-${{ hashFiles('**/pyproject.toml', '**/requirements*.txt') }}
|
||||||
@@ -72,7 +72,7 @@ jobs:
|
|||||||
run: pytest --tb=short -q
|
run: pytest --tb=short -q
|
||||||
|
|
||||||
- name: Login to container registry
|
- name: Login to container registry
|
||||||
uses: https://gitea.com/docker/login-action@v3
|
uses: https://gitea.com/docker/login-action@v4
|
||||||
with:
|
with:
|
||||||
registry: gitea.pzetatouch.it
|
registry: gitea.pzetatouch.it
|
||||||
username: ${{ secrets.G_USER }}
|
username: ${{ secrets.G_USER }}
|
||||||
@@ -104,6 +104,7 @@ jobs:
|
|||||||
REGISTRY="gitea.pzetatouch.it/pzeta_touch"
|
REGISTRY="gitea.pzetatouch.it/pzeta_touch"
|
||||||
echo "version_tag=${REGISTRY}/${APP_NAME}:${VERSION}" >> $GITHUB_OUTPUT
|
echo "version_tag=${REGISTRY}/${APP_NAME}:${VERSION}" >> $GITHUB_OUTPUT
|
||||||
echo "latest_tag=${REGISTRY}/${APP_NAME}:latest" >> $GITHUB_OUTPUT
|
echo "latest_tag=${REGISTRY}/${APP_NAME}:latest" >> $GITHUB_OUTPUT
|
||||||
|
echo "version=${VERSION}" >> $GITHUB_OUTPUT
|
||||||
|
|
||||||
- name: Build and push Docker image
|
- name: Build and push Docker image
|
||||||
uses: https://gitea.com/docker/build-push-action@v6
|
uses: https://gitea.com/docker/build-push-action@v6
|
||||||
@@ -114,3 +115,7 @@ jobs:
|
|||||||
tags: |
|
tags: |
|
||||||
${{ steps.tags.outputs.version_tag }}
|
${{ steps.tags.outputs.version_tag }}
|
||||||
${{ steps.tags.outputs.latest_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 }}
|
||||||
|
|||||||
@@ -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
|
||||||
@@ -23,15 +23,15 @@ jobs:
|
|||||||
working-directory: ${{ inputs.working-directory }}
|
working-directory: ${{ inputs.working-directory }}
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
uses: https://gitea.com/actions/checkout@v4
|
uses: https://gitea.com/actions/checkout@v6
|
||||||
|
|
||||||
- name: Setup Python
|
- name: Setup Python
|
||||||
uses: https://github.com/actions/setup-python@v5
|
uses: https://github.com/actions/setup-python@v5.2.0
|
||||||
with:
|
with:
|
||||||
python-version: ${{ inputs.python-version || '3.11' }}
|
python-version: ${{ inputs.python-version || '3.11' }}
|
||||||
|
|
||||||
- name: Cache pip
|
- name: Cache pip
|
||||||
uses: https://gitea.com/actions/cache@v4
|
uses: https://github.com/actions/cache@v4
|
||||||
with:
|
with:
|
||||||
path: ~/.cache/pip
|
path: ~/.cache/pip
|
||||||
key: ${{ runner.os }}-pip-${{ inputs.python-version }}-${{ hashFiles('**/pyproject.toml', '**/requirements*.txt') }}
|
key: ${{ runner.os }}-pip-${{ inputs.python-version }}-${{ hashFiles('**/pyproject.toml', '**/requirements*.txt') }}
|
||||||
|
|||||||
@@ -0,0 +1,254 @@
|
|||||||
|
name: Quality Gates
|
||||||
|
|
||||||
|
on:
|
||||||
|
workflow_call:
|
||||||
|
inputs:
|
||||||
|
working-directory:
|
||||||
|
description: 'Cartella che contiene package.json, relativa alla root del repo. Default: la root.'
|
||||||
|
type: string
|
||||||
|
default: '.'
|
||||||
|
node-version:
|
||||||
|
type: string
|
||||||
|
default: '24.16.0'
|
||||||
|
npm-version:
|
||||||
|
type: string
|
||||||
|
default: ''
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
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 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: Dockerfile - registry @pzeta e ARG per stage
|
||||||
|
shell: bash
|
||||||
|
# BLOCCANTE dal 12/09/2026, chiusa la tappa 2 di PZeta_Touch/flux-repo#133.
|
||||||
|
# Prima era solo un avviso, perche' 56 repo avevano ancora uno dei due
|
||||||
|
# difetti e bloccare li avrebbe fatti diventare rossi tutti insieme. Ora
|
||||||
|
# sono corretti: su 238 Dockerfile del portale ne restano difettosi due,
|
||||||
|
# `vue-conservazione` e `telegram-media-bot`, che non sono repository git
|
||||||
|
# e quindi non passano di qui.
|
||||||
|
run: |
|
||||||
|
# Due difetti che hanno rotto le release di node-xmlvalidation per due
|
||||||
|
# mesi senza che nessuno se ne accorgesse (PZeta_Touch/flux-repo#129,
|
||||||
|
# #133): (a) il registry @pzeta scritto in minuscolo nell'.npmrc
|
||||||
|
# generato dal Dockerfile, mentre i lockfile risolvono su PZeta_Touch;
|
||||||
|
# (b) una ARG usata in uno stage che non la dichiara, e che li' arriva
|
||||||
|
# vuota. Insieme, `npm install -g npm@` installa npm 12, che rifiuta
|
||||||
|
# l'URL scritto diverso (EALLOWREMOTE). Questo job non puo' accorgersene
|
||||||
|
# da solo: qui l'immagine non si costruisce, e la release fallisce solo
|
||||||
|
# al tag.
|
||||||
|
set +e
|
||||||
|
|
||||||
|
# La radice del repository e non working-directory: i Dockerfile stanno
|
||||||
|
# spesso fuori dalla cartella del package.
|
||||||
|
cd "${GITHUB_WORKSPACE:-.}" || exit 0
|
||||||
|
|
||||||
|
files=$(find . \( -name node_modules -o -name .git -o -name dist -o -name build \
|
||||||
|
-o -name .nuxt -o -name .output -o -name coverage \) -prune -o \
|
||||||
|
-type f \( -name 'Dockerfile' -o -name 'Dockerfile.*' -o -name '*.Dockerfile' \
|
||||||
|
-o -name '*.dockerfile' \) -print 2>/dev/null | sed 's|^\./||' | sort)
|
||||||
|
|
||||||
|
if [ -z "$files" ]; then
|
||||||
|
echo "Nessun Dockerfile: controllo non applicabile."
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
# (b) ARG fuori scope: una ARG vale SOLO nello stage che la dichiara.
|
||||||
|
# Quelle dichiarate prima del primo FROM valgono solo nelle righe FROM,
|
||||||
|
# e vanno ridichiarate dentro lo stage per essere viste dai RUN
|
||||||
|
# (documentazione Docker, "Scoping" in build/building/variables).
|
||||||
|
# Nessuna eredita' da `FROM <stage>`: le ENV si ereditano, le ARG no.
|
||||||
|
# Una versione precedente di questa guardia presumeva il contrario e
|
||||||
|
# lasciava passare proprio i casi come nuxt-vue-components-docs, dove
|
||||||
|
# la ARG dichiarata in `base` veniva usata in `deps` (#133).
|
||||||
|
arg_scope() {
|
||||||
|
${AWK:-awk} '
|
||||||
|
function trim(s) { sub(/^[ \t]+/, "", s); sub(/[ \t]+$/, "", s); return s }
|
||||||
|
# Nomi dichiarati da ARG/ENV: "A", "A=1", "A=1 B=2", "A valore".
|
||||||
|
function declared(rest, out, n, i, t) {
|
||||||
|
rest = trim(rest)
|
||||||
|
split("", out)
|
||||||
|
if (rest !~ /=/) { n = split(rest, t, /[ \t]+/); if (n > 0) out[t[1]] = 1; return }
|
||||||
|
n = split(rest, t, /[ \t]+/)
|
||||||
|
for (i = 1; i <= n; i++)
|
||||||
|
if (t[i] ~ /^[A-Za-z_][A-Za-z0-9_]*(=|$)/) { sub(/=.*/, "", t[i]); out[t[i]] = 1 }
|
||||||
|
}
|
||||||
|
function handle(kw, rest, ln, n, i, t, base, alias, k, p, s, v, d) {
|
||||||
|
if (pass == 1) {
|
||||||
|
if (kw == "ARG") { declared(rest, d); for (k in d) allargs[k] = 1 }
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if (kw == "FROM") {
|
||||||
|
n = split(trim(rest), t, /[ \t]+/); i = 1
|
||||||
|
while (i <= n && t[i] ~ /^--/) i++
|
||||||
|
base = tolower(t[i]); alias = ""
|
||||||
|
if (i + 2 <= n && toupper(t[i + 1]) == "AS") alias = tolower(t[i + 2])
|
||||||
|
stages++
|
||||||
|
stage = (alias != "" ? alias : "#" stages)
|
||||||
|
# Scope nuovo e vuoto: niente viene ereditato dallo stage di base.
|
||||||
|
# (Nessun apostrofo qui dentro: chiuderebbe la stringa awk.)
|
||||||
|
split("", scope)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if (stage == "") return
|
||||||
|
if (kw == "ARG") { declared(rest, d); for (k in d) { scope[k] = 1; varof[stage, k] = 1 }; return }
|
||||||
|
s = rest
|
||||||
|
while (match(s, /[$][{]?[A-Za-z_][A-Za-z0-9_]*/)) {
|
||||||
|
v = substr(s, RSTART, RLENGTH); sub(/^[$][{]?/, "", v)
|
||||||
|
s = substr(s, RSTART + RLENGTH)
|
||||||
|
# In un RUN espande la shell: una variabile assegnata nel comando
|
||||||
|
# stesso (VERSIONE="$(...)" && ... ${VERSIONE}) non va scambiata per la ARG.
|
||||||
|
if (kw == "RUN" && match(rest, "(^|[^A-Za-z0-9_$])" v "=")) continue
|
||||||
|
if ((v in allargs) && !(v in scope) && !(v in predefined) && !((ln, v) in seen)) {
|
||||||
|
seen[ln, v] = 1
|
||||||
|
printf "%d\t%s\t%s\n", ln, v, stage
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (kw == "ENV") { declared(rest, d); for (k in d) { scope[k] = 1; varof[stage, k] = 1 } }
|
||||||
|
}
|
||||||
|
function flush() {
|
||||||
|
if (buf != "" && match(buf, /^[ \t]*[A-Za-z]+/)) {
|
||||||
|
kw = toupper(trim(substr(buf, RSTART, RLENGTH)))
|
||||||
|
handle(kw, substr(buf, RSTART + RLENGTH), start)
|
||||||
|
}
|
||||||
|
buf = ""
|
||||||
|
}
|
||||||
|
BEGIN {
|
||||||
|
np = split("TARGETPLATFORM TARGETOS TARGETARCH TARGETVARIANT BUILDPLATFORM BUILDOS BUILDARCH BUILDVARIANT HTTP_PROXY HTTPS_PROXY FTP_PROXY NO_PROXY ALL_PROXY http_proxy https_proxy ftp_proxy no_proxy all_proxy", pp, " ")
|
||||||
|
for (i = 1; i <= np; i++) predefined[pp[i]] = 1
|
||||||
|
}
|
||||||
|
FNR == 1 { pass++; buf = ""; stage = ""; stages = 0; split("", scope); split("", varof) }
|
||||||
|
{
|
||||||
|
line = $0; sub(/\r$/, "", line)
|
||||||
|
if (line ~ /^[ \t]*#/) next # commenti, anche dentro una continuazione
|
||||||
|
if (buf == "" && line ~ /^[ \t]*$/) next
|
||||||
|
if (buf == "") start = FNR
|
||||||
|
if (line ~ /\\[ \t]*$/) { sub(/\\[ \t]*$/, " ", line); buf = buf line; next }
|
||||||
|
buf = buf line
|
||||||
|
flush()
|
||||||
|
}
|
||||||
|
' "$1" "$1"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Caso di prova: se l'awk di questo runner non riconosce una ARG fuori
|
||||||
|
# scope nota, il controllo (b) non e' affidabile e lo si dice, invece di
|
||||||
|
# dichiarare in regola un Dockerfile che non si e' potuto leggere.
|
||||||
|
argcheck=1
|
||||||
|
prova=$(mktemp)
|
||||||
|
printf 'ARG X=1\nFROM scratch AS a\nRUN echo ${X}\n' > "$prova"
|
||||||
|
if [ "$(arg_scope "$prova" 2>/dev/null | cut -f2)" != "X" ]; then
|
||||||
|
argcheck=0
|
||||||
|
echo "::warning::Guardia Dockerfile: l'analisi delle ARG non funziona con l'awk di questo runner ($(${AWK:-awk} -W version 2>&1 | head -1)). Il controllo (b) e' saltato, il (a) resta."
|
||||||
|
fi
|
||||||
|
rm -f "$prova"
|
||||||
|
|
||||||
|
findings=""
|
||||||
|
for f in $files; do
|
||||||
|
# (a) registry: npm confronta l'URL del lockfile come stringa, e i lockfile
|
||||||
|
# risolvono tutti su PZeta_Touch.
|
||||||
|
reg=$(grep -nE 'packages/(pzeta_touch|pzeta)/' "$f" 2>/dev/null | cut -d: -f1 | tr '\n' ' ' | sed 's/ *$//')
|
||||||
|
if [ -n "$reg" ]; then
|
||||||
|
findings="${findings}${f} ${reg%% *} registry $(echo "$reg" | sed 's/ /, /g') -
|
||||||
|
"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# (b) ARG fuori scope, con arg_scope definita sopra.
|
||||||
|
args=""
|
||||||
|
[ "$argcheck" = "1" ] && args=$(arg_scope "$f" 2>/dev/null)
|
||||||
|
while IFS=' ' read -r n v st; do
|
||||||
|
[ -n "$n" ] || continue
|
||||||
|
findings="${findings}${f} ${n} arg ${v} ${st}
|
||||||
|
"
|
||||||
|
done <<EOF
|
||||||
|
$args
|
||||||
|
EOF
|
||||||
|
done
|
||||||
|
|
||||||
|
if [ -z "$findings" ]; then
|
||||||
|
if [ "$argcheck" = "1" ]; then
|
||||||
|
echo "Dockerfile: registry @pzeta e ARG per stage in regola."
|
||||||
|
else
|
||||||
|
echo "Dockerfile: registry @pzeta in regola; ARG per stage non verificate (vedi l'avviso sopra)."
|
||||||
|
fi
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
summary="## ❌ Dockerfile: difetti della #133"$'\n\n'"| File | Riga | Difetto |"$'\n'"|---|---|---|"$'\n'
|
||||||
|
count=0
|
||||||
|
while IFS=' ' read -r f n kind v st; do
|
||||||
|
[ -n "$f" ] || continue
|
||||||
|
count=$((count + 1))
|
||||||
|
if [ "$kind" = "registry" ]; then
|
||||||
|
msg="registry @pzeta in minuscolo (righe ${v}): i lockfile risolvono su PZeta_Touch e da npm 12 un URL scritto diverso viene rifiutato (EALLOWREMOTE). Scrivere https://gitea.pzetatouch.it/api/packages/PZeta_Touch/npm/"
|
||||||
|
else
|
||||||
|
case "$st" in \#*) st="n. ${st#\#}, senza AS" ;; esac
|
||||||
|
effetto="il valore e' vuoto"
|
||||||
|
[ "$v" = "NPM_VERSION" ] && effetto="e' vuota, e 'npm install -g npm@' installa l'ultima ignorando il pin"
|
||||||
|
msg="ARG ${v} usata nello stage '${st}' senza dichiararla: li' ${effetto}. Aggiungere 'ARG ${v}' dopo il FROM dello stage."
|
||||||
|
fi
|
||||||
|
echo "::error file=${f},line=${n}::${msg}"
|
||||||
|
summary="${summary}| \`${f}\` | ${n} | ${msg} |"$'\n'
|
||||||
|
done <<EOF
|
||||||
|
$findings
|
||||||
|
EOF
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
parola="difetti"; [ "$count" -eq 1 ] && parola="difetto"
|
||||||
|
echo "${count} ${parola}. Il job si ferma qui: con npm 12 la build dell'immagine"
|
||||||
|
echo "fallirebbe al tag, cioe' molto piu' tardi e su un log che nessuno guarda"
|
||||||
|
echo "(e' andata cosi' per due mesi con node-xmlvalidation, PZeta_Touch/flux-repo#129)."
|
||||||
|
if [ -n "${GITHUB_STEP_SUMMARY:-}" ]; then
|
||||||
|
printf '%s\n%s\n' "$summary" "Riferimento: PZeta_Touch/flux-repo#133" >> "$GITHUB_STEP_SUMMARY" 2>/dev/null
|
||||||
|
fi
|
||||||
|
exit 1
|
||||||
|
|
||||||
|
- 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
|
||||||
@@ -3,24 +3,45 @@ name: Quality Gates
|
|||||||
on:
|
on:
|
||||||
workflow_call:
|
workflow_call:
|
||||||
inputs:
|
inputs:
|
||||||
|
working-directory:
|
||||||
|
description: 'Cartella che contiene package.json, relativa alla root del repo. Default: la root.'
|
||||||
|
type: string
|
||||||
|
default: '.'
|
||||||
node-version:
|
node-version:
|
||||||
type: string
|
type: string
|
||||||
default: '22.17'
|
default: '24.16.0'
|
||||||
|
npm-version:
|
||||||
|
type: string
|
||||||
|
default: ''
|
||||||
|
owns-auth-roles:
|
||||||
|
description: >-
|
||||||
|
Solo per il repository proprietario di auth.ruoli (node-user-profiling):
|
||||||
|
gli consente di dichiarare ruoli nelle proprie migrazioni. Ogni altro
|
||||||
|
repo deve lasciarlo a false, e il gate qui sotto glielo impedisce.
|
||||||
|
type: boolean
|
||||||
|
default: false
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
quality-gates:
|
quality-gates:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
|
defaults:
|
||||||
|
run:
|
||||||
|
working-directory: ${{ inputs.working-directory || '.' }}
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
uses: https://gitea.com/actions/checkout@v4
|
uses: https://gitea.com/actions/checkout@v6
|
||||||
|
|
||||||
- name: Setup Node.js
|
- name: Setup Node.js
|
||||||
uses: https://gitea.com/actions/setup-node@v4
|
uses: https://gitea.com/actions/setup-node@v4
|
||||||
with:
|
with:
|
||||||
node-version: ${{ inputs.node-version || '22.17' }}
|
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
|
- name: Cache npm
|
||||||
uses: https://gitea.com/actions/cache@v4
|
uses: https://github.com/actions/cache@v4
|
||||||
with:
|
with:
|
||||||
path: ~/.npm
|
path: ~/.npm
|
||||||
key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }}
|
key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }}
|
||||||
@@ -29,8 +50,263 @@ jobs:
|
|||||||
|
|
||||||
- name: Configure npm private registry
|
- name: Configure npm private registry
|
||||||
run: |
|
run: |
|
||||||
echo "@pzeta:registry=https://gitea.pzetatouch.it/api/packages/pzeta_touch/npm/" >> ~/.npmrc
|
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
|
echo "//gitea.pzetatouch.it/api/packages/PZeta_Touch/npm/:_authToken=${{ secrets.NPM_TOKEN }}" >> ~/.npmrc
|
||||||
|
|
||||||
|
- name: Nessun ruolo dichiarato fuori da node-user-profiling
|
||||||
|
shell: bash
|
||||||
|
env:
|
||||||
|
# La deroga stava nel campo `if:` dello step, e li' non arriva: nel
|
||||||
|
# workflow_call di act_runner i valori `with:` del chiamante non
|
||||||
|
# raggiungono il contesto `inputs` in quella posizione, quindi
|
||||||
|
# `!inputs.owns-auth-roles` restava vero anche con l'input a true e il
|
||||||
|
# gate falliva proprio in node-user-profiling, l'unico repository
|
||||||
|
# autorizzato a dichiarare ruoli. Letta come variabile d'ambiente la
|
||||||
|
# deroga arriva, e la si confronta come stringa.
|
||||||
|
OWNS_AUTH_ROLES: ${{ inputs.owns-auth-roles }}
|
||||||
|
run: |
|
||||||
|
# `auth.ruoli` appartiene a node-user-profiling e il suo contratto (seed
|
||||||
|
# 13, esteso dalla migrazione 19) vieta agli altri moduli di crearne.
|
||||||
|
# Non e' una formalita': il claim `role` del JWT e' il primo ruolo
|
||||||
|
# applicativo dell'utente e PostgREST ci fa un SET ROLE, ma i ruoli
|
||||||
|
# PostgreSQL esistono solo per i tredici livelli di piattaforma. Un
|
||||||
|
# ruolo per-modulo in quel claim e' una sessione che non parte.
|
||||||
|
# Nove microfrontend lo avevano disatteso: 21 ruoli, 27 su 35 senza
|
||||||
|
# omonimo PostgreSQL. Questo controllo esiste perche' non si ripeta.
|
||||||
|
set -uo pipefail
|
||||||
|
|
||||||
|
# Il nome del repository e' la rete di sicurezza della deroga: se
|
||||||
|
# nemmeno l'env dovesse arrivare, il proprietario dello schema si
|
||||||
|
# riconosce lo stesso e non resta bloccato dal proprio gate. Le due
|
||||||
|
# condizioni dicono la stessa cosa, una dichiarata e una constatata.
|
||||||
|
repo="${GITHUB_REPOSITORY:-}"
|
||||||
|
if [ "${OWNS_AUTH_ROLES:-}" = "true" ] || [ "${repo##*/}" = "node-user-profiling" ]; then
|
||||||
|
echo "Repository proprietario di auth.ruoli: controllo non applicabile."
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
dirs=""
|
||||||
|
for d in migrations seeds sql database/migrations; do
|
||||||
|
[ -d "$d" ] && dirs="$dirs $d"
|
||||||
|
done
|
||||||
|
if [ -z "$dirs" ]; then
|
||||||
|
echo "Nessuna cartella di migrazioni: controllo non applicabile."
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Il boundary dopo `ruoli` evita che auth.ruolipermessi finisca fra i
|
||||||
|
# match; il filtro sulle righe che iniziano per -- lascia passare i
|
||||||
|
# commenti, che spiegano spesso proprio questa regola.
|
||||||
|
# Fuori dal controllo le cartelle che non alimentano il catalogo delle
|
||||||
|
# migrazioni: `una-tantum` raccoglie i delta generati per riallineare a
|
||||||
|
# mano un tenant, `rollback` gli script di ritorno. Sono strumenti
|
||||||
|
# operativi, spesso fotografie di uno stato passato, e riscriverli
|
||||||
|
# significherebbe falsare la storia che documentano.
|
||||||
|
hits=$(grep -rniE --include='*.sql' \
|
||||||
|
--exclude-dir=una-tantum --exclude-dir=rollback \
|
||||||
|
'insert[[:space:]]+into[[:space:]]+auth\.ruoli([[:space:]]|\(|$)' \
|
||||||
|
$dirs 2>/dev/null \
|
||||||
|
| awk -F: '{ riga=$0; sub(/^[^:]*:[^:]*:/, "", riga); gsub(/^[[:space:]]+/, "", riga); if (riga !~ /^--/) print }' || true)
|
||||||
|
|
||||||
|
if [ -n "$hits" ]; then
|
||||||
|
echo "::error::Questo repository dichiara ruoli in auth.ruoli, che appartiene a node-user-profiling."
|
||||||
|
echo ""
|
||||||
|
echo "$hits"
|
||||||
|
echo ""
|
||||||
|
echo "Cosa fare invece: dichiarare un GRUPPO d'area con i permessi del modulo."
|
||||||
|
echo " INSERT INTO auth.gruppi (nome, nomecompleto, descrizione, tipogruppo, idruololivello)"
|
||||||
|
echo " ... poi INSERT INTO auth.gruppipermessi per collegarvi i propri permessi."
|
||||||
|
echo ""
|
||||||
|
echo "Il livello che accompagna il gruppo si sceglie fra i tredici di piattaforma"
|
||||||
|
echo "(manager, contabile, auditor, cfo, dipendente, viewer, operatore, cliente):"
|
||||||
|
echo "sono gli unici ad avere un ruolo PostgreSQL, senza il quale il SET ROLE fallisce."
|
||||||
|
echo "Esempio: vue-timesheet/migrations/12_gruppi_area.sql"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
echo "Nessun INSERT INTO auth.ruoli: contratto rispettato."
|
||||||
|
|
||||||
|
- name: Dockerfile - registry @pzeta e ARG per stage
|
||||||
|
shell: bash
|
||||||
|
# BLOCCANTE dal 12/09/2026, chiusa la tappa 2 di PZeta_Touch/flux-repo#133.
|
||||||
|
# Prima era solo un avviso, perche' 56 repo avevano ancora uno dei due
|
||||||
|
# difetti e bloccare li avrebbe fatti diventare rossi tutti insieme. Ora
|
||||||
|
# sono corretti: su 238 Dockerfile del portale ne restano difettosi due,
|
||||||
|
# `vue-conservazione` e `telegram-media-bot`, che non sono repository git
|
||||||
|
# e quindi non passano di qui.
|
||||||
|
run: |
|
||||||
|
# Due difetti che hanno rotto le release di node-xmlvalidation per due
|
||||||
|
# mesi senza che nessuno se ne accorgesse (PZeta_Touch/flux-repo#129,
|
||||||
|
# #133): (a) il registry @pzeta scritto in minuscolo nell'.npmrc
|
||||||
|
# generato dal Dockerfile, mentre i lockfile risolvono su PZeta_Touch;
|
||||||
|
# (b) una ARG usata in uno stage che non la dichiara, e che li' arriva
|
||||||
|
# vuota. Insieme, `npm install -g npm@` installa npm 12, che rifiuta
|
||||||
|
# l'URL scritto diverso (EALLOWREMOTE). Questo job non puo' accorgersene
|
||||||
|
# da solo: qui l'immagine non si costruisce, e la release fallisce solo
|
||||||
|
# al tag.
|
||||||
|
set +e
|
||||||
|
|
||||||
|
# La radice del repository e non working-directory: i Dockerfile stanno
|
||||||
|
# spesso fuori dalla cartella del package.
|
||||||
|
cd "${GITHUB_WORKSPACE:-.}" || exit 0
|
||||||
|
|
||||||
|
files=$(find . \( -name node_modules -o -name .git -o -name dist -o -name build \
|
||||||
|
-o -name .nuxt -o -name .output -o -name coverage \) -prune -o \
|
||||||
|
-type f \( -name 'Dockerfile' -o -name 'Dockerfile.*' -o -name '*.Dockerfile' \
|
||||||
|
-o -name '*.dockerfile' \) -print 2>/dev/null | sed 's|^\./||' | sort)
|
||||||
|
|
||||||
|
if [ -z "$files" ]; then
|
||||||
|
echo "Nessun Dockerfile: controllo non applicabile."
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
# (b) ARG fuori scope: una ARG vale SOLO nello stage che la dichiara.
|
||||||
|
# Quelle dichiarate prima del primo FROM valgono solo nelle righe FROM,
|
||||||
|
# e vanno ridichiarate dentro lo stage per essere viste dai RUN
|
||||||
|
# (documentazione Docker, "Scoping" in build/building/variables).
|
||||||
|
# Nessuna eredita' da `FROM <stage>`: le ENV si ereditano, le ARG no.
|
||||||
|
# Una versione precedente di questa guardia presumeva il contrario e
|
||||||
|
# lasciava passare proprio i casi come nuxt-vue-components-docs, dove
|
||||||
|
# la ARG dichiarata in `base` veniva usata in `deps` (#133).
|
||||||
|
arg_scope() {
|
||||||
|
${AWK:-awk} '
|
||||||
|
function trim(s) { sub(/^[ \t]+/, "", s); sub(/[ \t]+$/, "", s); return s }
|
||||||
|
# Nomi dichiarati da ARG/ENV: "A", "A=1", "A=1 B=2", "A valore".
|
||||||
|
function declared(rest, out, n, i, t) {
|
||||||
|
rest = trim(rest)
|
||||||
|
split("", out)
|
||||||
|
if (rest !~ /=/) { n = split(rest, t, /[ \t]+/); if (n > 0) out[t[1]] = 1; return }
|
||||||
|
n = split(rest, t, /[ \t]+/)
|
||||||
|
for (i = 1; i <= n; i++)
|
||||||
|
if (t[i] ~ /^[A-Za-z_][A-Za-z0-9_]*(=|$)/) { sub(/=.*/, "", t[i]); out[t[i]] = 1 }
|
||||||
|
}
|
||||||
|
function handle(kw, rest, ln, n, i, t, base, alias, k, p, s, v, d) {
|
||||||
|
if (pass == 1) {
|
||||||
|
if (kw == "ARG") { declared(rest, d); for (k in d) allargs[k] = 1 }
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if (kw == "FROM") {
|
||||||
|
n = split(trim(rest), t, /[ \t]+/); i = 1
|
||||||
|
while (i <= n && t[i] ~ /^--/) i++
|
||||||
|
base = tolower(t[i]); alias = ""
|
||||||
|
if (i + 2 <= n && toupper(t[i + 1]) == "AS") alias = tolower(t[i + 2])
|
||||||
|
stages++
|
||||||
|
stage = (alias != "" ? alias : "#" stages)
|
||||||
|
# Scope nuovo e vuoto: niente viene ereditato dallo stage di base.
|
||||||
|
# (Nessun apostrofo qui dentro: chiuderebbe la stringa awk.)
|
||||||
|
split("", scope)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if (stage == "") return
|
||||||
|
if (kw == "ARG") { declared(rest, d); for (k in d) { scope[k] = 1; varof[stage, k] = 1 }; return }
|
||||||
|
s = rest
|
||||||
|
while (match(s, /[$][{]?[A-Za-z_][A-Za-z0-9_]*/)) {
|
||||||
|
v = substr(s, RSTART, RLENGTH); sub(/^[$][{]?/, "", v)
|
||||||
|
s = substr(s, RSTART + RLENGTH)
|
||||||
|
# In un RUN espande la shell: una variabile assegnata nel comando
|
||||||
|
# stesso (VERSIONE="$(...)" && ... ${VERSIONE}) non va scambiata per la ARG.
|
||||||
|
if (kw == "RUN" && match(rest, "(^|[^A-Za-z0-9_$])" v "=")) continue
|
||||||
|
if ((v in allargs) && !(v in scope) && !(v in predefined) && !((ln, v) in seen)) {
|
||||||
|
seen[ln, v] = 1
|
||||||
|
printf "%d\t%s\t%s\n", ln, v, stage
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (kw == "ENV") { declared(rest, d); for (k in d) { scope[k] = 1; varof[stage, k] = 1 } }
|
||||||
|
}
|
||||||
|
function flush() {
|
||||||
|
if (buf != "" && match(buf, /^[ \t]*[A-Za-z]+/)) {
|
||||||
|
kw = toupper(trim(substr(buf, RSTART, RLENGTH)))
|
||||||
|
handle(kw, substr(buf, RSTART + RLENGTH), start)
|
||||||
|
}
|
||||||
|
buf = ""
|
||||||
|
}
|
||||||
|
BEGIN {
|
||||||
|
np = split("TARGETPLATFORM TARGETOS TARGETARCH TARGETVARIANT BUILDPLATFORM BUILDOS BUILDARCH BUILDVARIANT HTTP_PROXY HTTPS_PROXY FTP_PROXY NO_PROXY ALL_PROXY http_proxy https_proxy ftp_proxy no_proxy all_proxy", pp, " ")
|
||||||
|
for (i = 1; i <= np; i++) predefined[pp[i]] = 1
|
||||||
|
}
|
||||||
|
FNR == 1 { pass++; buf = ""; stage = ""; stages = 0; split("", scope); split("", varof) }
|
||||||
|
{
|
||||||
|
line = $0; sub(/\r$/, "", line)
|
||||||
|
if (line ~ /^[ \t]*#/) next # commenti, anche dentro una continuazione
|
||||||
|
if (buf == "" && line ~ /^[ \t]*$/) next
|
||||||
|
if (buf == "") start = FNR
|
||||||
|
if (line ~ /\\[ \t]*$/) { sub(/\\[ \t]*$/, " ", line); buf = buf line; next }
|
||||||
|
buf = buf line
|
||||||
|
flush()
|
||||||
|
}
|
||||||
|
' "$1" "$1"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Caso di prova: se l'awk di questo runner non riconosce una ARG fuori
|
||||||
|
# scope nota, il controllo (b) non e' affidabile e lo si dice, invece di
|
||||||
|
# dichiarare in regola un Dockerfile che non si e' potuto leggere.
|
||||||
|
argcheck=1
|
||||||
|
prova=$(mktemp)
|
||||||
|
printf 'ARG X=1\nFROM scratch AS a\nRUN echo ${X}\n' > "$prova"
|
||||||
|
if [ "$(arg_scope "$prova" 2>/dev/null | cut -f2)" != "X" ]; then
|
||||||
|
argcheck=0
|
||||||
|
echo "::warning::Guardia Dockerfile: l'analisi delle ARG non funziona con l'awk di questo runner ($(${AWK:-awk} -W version 2>&1 | head -1)). Il controllo (b) e' saltato, il (a) resta."
|
||||||
|
fi
|
||||||
|
rm -f "$prova"
|
||||||
|
|
||||||
|
findings=""
|
||||||
|
for f in $files; do
|
||||||
|
# (a) registry: npm confronta l'URL del lockfile come stringa, e i lockfile
|
||||||
|
# risolvono tutti su PZeta_Touch.
|
||||||
|
reg=$(grep -nE 'packages/(pzeta_touch|pzeta)/' "$f" 2>/dev/null | cut -d: -f1 | tr '\n' ' ' | sed 's/ *$//')
|
||||||
|
if [ -n "$reg" ]; then
|
||||||
|
findings="${findings}${f} ${reg%% *} registry $(echo "$reg" | sed 's/ /, /g') -
|
||||||
|
"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# (b) ARG fuori scope, con arg_scope definita sopra.
|
||||||
|
args=""
|
||||||
|
[ "$argcheck" = "1" ] && args=$(arg_scope "$f" 2>/dev/null)
|
||||||
|
while IFS=' ' read -r n v st; do
|
||||||
|
[ -n "$n" ] || continue
|
||||||
|
findings="${findings}${f} ${n} arg ${v} ${st}
|
||||||
|
"
|
||||||
|
done <<EOF
|
||||||
|
$args
|
||||||
|
EOF
|
||||||
|
done
|
||||||
|
|
||||||
|
if [ -z "$findings" ]; then
|
||||||
|
if [ "$argcheck" = "1" ]; then
|
||||||
|
echo "Dockerfile: registry @pzeta e ARG per stage in regola."
|
||||||
|
else
|
||||||
|
echo "Dockerfile: registry @pzeta in regola; ARG per stage non verificate (vedi l'avviso sopra)."
|
||||||
|
fi
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
summary="## ❌ Dockerfile: difetti della #133"$'\n\n'"| File | Riga | Difetto |"$'\n'"|---|---|---|"$'\n'
|
||||||
|
count=0
|
||||||
|
while IFS=' ' read -r f n kind v st; do
|
||||||
|
[ -n "$f" ] || continue
|
||||||
|
count=$((count + 1))
|
||||||
|
if [ "$kind" = "registry" ]; then
|
||||||
|
msg="registry @pzeta in minuscolo (righe ${v}): i lockfile risolvono su PZeta_Touch e da npm 12 un URL scritto diverso viene rifiutato (EALLOWREMOTE). Scrivere https://gitea.pzetatouch.it/api/packages/PZeta_Touch/npm/"
|
||||||
|
else
|
||||||
|
case "$st" in \#*) st="n. ${st#\#}, senza AS" ;; esac
|
||||||
|
effetto="il valore e' vuoto"
|
||||||
|
[ "$v" = "NPM_VERSION" ] && effetto="e' vuota, e 'npm install -g npm@' installa l'ultima ignorando il pin"
|
||||||
|
msg="ARG ${v} usata nello stage '${st}' senza dichiararla: li' ${effetto}. Aggiungere 'ARG ${v}' dopo il FROM dello stage."
|
||||||
|
fi
|
||||||
|
echo "::error file=${f},line=${n}::${msg}"
|
||||||
|
summary="${summary}| \`${f}\` | ${n} | ${msg} |"$'\n'
|
||||||
|
done <<EOF
|
||||||
|
$findings
|
||||||
|
EOF
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
parola="difetti"; [ "$count" -eq 1 ] && parola="difetto"
|
||||||
|
echo "${count} ${parola}. Il job si ferma qui: con npm 12 la build dell'immagine"
|
||||||
|
echo "fallirebbe al tag, cioe' molto piu' tardi e su un log che nessuno guarda"
|
||||||
|
echo "(e' andata cosi' per due mesi con node-xmlvalidation, PZeta_Touch/flux-repo#129)."
|
||||||
|
if [ -n "${GITHUB_STEP_SUMMARY:-}" ]; then
|
||||||
|
printf '%s\n%s\n' "$summary" "Riferimento: PZeta_Touch/flux-repo#133" >> "$GITHUB_STEP_SUMMARY" 2>/dev/null
|
||||||
|
fi
|
||||||
|
exit 1
|
||||||
|
|
||||||
- name: Check outdated packages
|
- name: Check outdated packages
|
||||||
run: npm outdated || true
|
run: npm outdated || true
|
||||||
|
|||||||
@@ -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
|
||||||
@@ -19,11 +19,11 @@ on:
|
|||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
quality-gates:
|
quality-gates:
|
||||||
uses: https://gitea.com/Punga78/shared-actions/.gitea/workflows/quality-gates.yml@v1
|
uses: https://gitea.pzetatouch.it/devops/shared-actions/.gitea/workflows/quality-gates.yml@v1
|
||||||
secrets: inherit
|
secrets: inherit
|
||||||
|
|
||||||
android-debug:
|
android-debug:
|
||||||
uses: https://gitea.com/Punga78/shared-actions/.gitea/workflows/capacitor-android.yml@v1
|
uses: https://gitea.pzetatouch.it/devops/shared-actions/.gitea/workflows/capacitor-android.yml@v1
|
||||||
secrets: inherit
|
secrets: inherit
|
||||||
with:
|
with:
|
||||||
build-type: debug
|
build-type: debug
|
||||||
|
|||||||
@@ -18,19 +18,19 @@ on:
|
|||||||
jobs:
|
jobs:
|
||||||
branch-cleanup:
|
branch-cleanup:
|
||||||
if: gitea.event_name == 'pull_request' && gitea.event.pull_request.merged == true
|
if: gitea.event_name == 'pull_request' && gitea.event.pull_request.merged == true
|
||||||
uses: https://gitea.com/Punga78/shared-actions/.gitea/workflows/branch-cleanup.yml@v1
|
uses: https://gitea.pzetatouch.it/devops/shared-actions/.gitea/workflows/branch-cleanup.yml@v1
|
||||||
secrets: inherit
|
secrets: inherit
|
||||||
|
|
||||||
dependency-audit:
|
dependency-audit:
|
||||||
if: >
|
if: >
|
||||||
gitea.event_name == 'workflow_dispatch' ||
|
gitea.event_name == 'workflow_dispatch' ||
|
||||||
(gitea.event_name == 'schedule' && gitea.event.schedule == '0 8 * * 1')
|
(gitea.event_name == 'schedule' && gitea.event.schedule == '0 8 * * 1')
|
||||||
uses: https://gitea.com/Punga78/shared-actions/.gitea/workflows/dependency-check.yml@v1
|
uses: https://gitea.pzetatouch.it/devops/shared-actions/.gitea/workflows/dependency-check.yml@v1
|
||||||
secrets: inherit
|
secrets: inherit
|
||||||
|
|
||||||
dependency-outdated:
|
dependency-outdated:
|
||||||
if: >
|
if: >
|
||||||
gitea.event_name == 'workflow_dispatch' ||
|
gitea.event_name == 'workflow_dispatch' ||
|
||||||
(gitea.event_name == 'schedule' && gitea.event.schedule == '0 8 1 * *')
|
(gitea.event_name == 'schedule' && gitea.event.schedule == '0 8 1 * *')
|
||||||
uses: https://gitea.com/Punga78/shared-actions/.gitea/workflows/dependency-outdated.yml@v1
|
uses: https://gitea.pzetatouch.it/devops/shared-actions/.gitea/workflows/dependency-outdated.yml@v1
|
||||||
secrets: inherit
|
secrets: inherit
|
||||||
|
|||||||
@@ -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
|
||||||
@@ -18,8 +18,8 @@
|
|||||||
# }
|
# }
|
||||||
# }
|
# }
|
||||||
#
|
#
|
||||||
# NOTA: i job girano in parallelo (no needs).
|
# NOTA: gitea-release attende entrambe le build Android via needs.
|
||||||
# Gitea bug #31900: needs + workflow_call + checkout causa errori di autenticazione.
|
# Workaround Gitea bug #31900: token esplicito nel checkout di auto-release.yml.
|
||||||
|
|
||||||
name: Release
|
name: Release
|
||||||
|
|
||||||
@@ -30,19 +30,20 @@ on:
|
|||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
android-apk:
|
android-apk:
|
||||||
uses: https://gitea.com/Punga78/shared-actions/.gitea/workflows/capacitor-android.yml@v1
|
uses: https://gitea.pzetatouch.it/devops/shared-actions/.gitea/workflows/capacitor-android.yml@v1
|
||||||
secrets: inherit
|
secrets: inherit
|
||||||
with:
|
with:
|
||||||
build-type: release
|
build-type: release
|
||||||
output-format: apk
|
output-format: apk
|
||||||
|
|
||||||
android-aab:
|
android-aab:
|
||||||
uses: https://gitea.com/Punga78/shared-actions/.gitea/workflows/capacitor-android.yml@v1
|
uses: https://gitea.pzetatouch.it/devops/shared-actions/.gitea/workflows/capacitor-android.yml@v1
|
||||||
secrets: inherit
|
secrets: inherit
|
||||||
with:
|
with:
|
||||||
build-type: release
|
build-type: release
|
||||||
output-format: aab
|
output-format: aab
|
||||||
|
|
||||||
gitea-release:
|
gitea-release:
|
||||||
uses: https://gitea.com/Punga78/shared-actions/.gitea/workflows/auto-release.yml@v1
|
needs: [android-apk, android-aab]
|
||||||
|
uses: https://gitea.pzetatouch.it/devops/shared-actions/.gitea/workflows/auto-release.yml@v1
|
||||||
secrets: inherit
|
secrets: inherit
|
||||||
|
|||||||
@@ -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
|
||||||
@@ -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.yml@v1
|
||||||
|
secrets: inherit
|
||||||
|
with:
|
||||||
|
npm-version: '11' # lockfile generato con npm@11, runner usa npm@10 di default
|
||||||
@@ -0,0 +1,36 @@
|
|||||||
|
# Copia in: .gitea/workflows/maintenance.yml
|
||||||
|
# Trigger:
|
||||||
|
# - PR merged → cleanup branch sorgente
|
||||||
|
# - Ogni martedì 02:00 → security audit vulnerabilità (settimanale)
|
||||||
|
# - Ogni 1° del mese → controllo pacchetti obsoleti (mensile)
|
||||||
|
# - Manuale → workflow_dispatch (esegue tutti i job di manutenzione)
|
||||||
|
|
||||||
|
name: Maintenance
|
||||||
|
|
||||||
|
on:
|
||||||
|
pull_request:
|
||||||
|
types: [closed]
|
||||||
|
schedule:
|
||||||
|
- cron: '0 2 * * 2' # ogni martedì alle 02:00 → security audit
|
||||||
|
- cron: '0 3 1 * *' # ogni 1° del mese alle 03:00 → outdated check
|
||||||
|
workflow_dispatch:
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
branch-cleanup:
|
||||||
|
if: gitea.event_name == 'pull_request' && gitea.event.pull_request.merged == true
|
||||||
|
uses: https://gitea.pzetatouch.it/devops/shared-actions/.gitea/workflows/branch-cleanup.yml@v1
|
||||||
|
secrets: inherit
|
||||||
|
|
||||||
|
dependency-audit:
|
||||||
|
if: >
|
||||||
|
gitea.event_name == 'workflow_dispatch' ||
|
||||||
|
(gitea.event_name == 'schedule' && gitea.event.schedule == '0 2 * * 2')
|
||||||
|
uses: https://gitea.pzetatouch.it/devops/shared-actions/.gitea/workflows/dependency-check.yml@v1
|
||||||
|
secrets: inherit
|
||||||
|
|
||||||
|
dependency-outdated:
|
||||||
|
if: >
|
||||||
|
gitea.event_name == 'workflow_dispatch' ||
|
||||||
|
(gitea.event_name == 'schedule' && gitea.event.schedule == '0 3 1 * *')
|
||||||
|
uses: https://gitea.pzetatouch.it/devops/shared-actions/.gitea/workflows/dependency-outdated.yml@v1
|
||||||
|
secrets: inherit
|
||||||
@@ -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
|
||||||
@@ -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.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.yml@v1
|
||||||
|
secrets: inherit
|
||||||
@@ -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
|
||||||
@@ -16,5 +16,5 @@ on:
|
|||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
quality-gates:
|
quality-gates:
|
||||||
uses: https://gitea.com/Punga78/shared-actions/.gitea/workflows/quality-gates.yml@v1
|
uses: https://gitea.pzetatouch.it/devops/shared-actions/.gitea/workflows/quality-gates.yml@v1
|
||||||
secrets: inherit
|
secrets: inherit
|
||||||
|
|||||||
@@ -1,5 +1,9 @@
|
|||||||
# Copia in: .gitea/workflows/maintenance.yml
|
# Copia in: .gitea/workflows/maintenance.yml
|
||||||
# Combina branch-cleanup (PR merge) e dependency-check (settimanale)
|
# Trigger:
|
||||||
|
# - PR merged → cleanup branch sorgente
|
||||||
|
# - Ogni lunedì 08:00 → security audit vulnerabilità (settimanale)
|
||||||
|
# - Ogni 1° del mese → controllo pacchetti obsoleti (mensile)
|
||||||
|
# - Manuale → workflow_dispatch (esegue tutti i job di manutenzione)
|
||||||
|
|
||||||
name: Maintenance
|
name: Maintenance
|
||||||
|
|
||||||
@@ -7,16 +11,26 @@ on:
|
|||||||
pull_request:
|
pull_request:
|
||||||
types: [closed]
|
types: [closed]
|
||||||
schedule:
|
schedule:
|
||||||
- cron: '0 8 * * 1'
|
- cron: '0 2 * * 3' # ogni mercoledì alle 02:00 → security audit
|
||||||
|
- cron: '0 2 1 * *' # ogni 1° del mese alle 02:00 → outdated check
|
||||||
workflow_dispatch:
|
workflow_dispatch:
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
branch-cleanup:
|
branch-cleanup:
|
||||||
if: gitea.event_name == 'pull_request' && gitea.event.pull_request.merged == true
|
if: gitea.event_name == 'pull_request' && gitea.event.pull_request.merged == true
|
||||||
uses: https://gitea.com/Punga78/shared-actions/.gitea/workflows/branch-cleanup.yml@v1
|
uses: https://gitea.pzetatouch.it/devops/shared-actions/.gitea/workflows/branch-cleanup.yml@v1
|
||||||
secrets: inherit
|
secrets: inherit
|
||||||
|
|
||||||
dependency-check:
|
dependency-audit:
|
||||||
if: gitea.event_name == 'schedule' || gitea.event_name == 'workflow_dispatch'
|
if: >
|
||||||
uses: https://gitea.com/Punga78/shared-actions/.gitea/workflows/dependency-check.yml@v1
|
gitea.event_name == 'workflow_dispatch' ||
|
||||||
|
(gitea.event_name == 'schedule' && gitea.event.schedule == '0 2 * * 3')
|
||||||
|
uses: https://gitea.pzetatouch.it/devops/shared-actions/.gitea/workflows/dependency-check.yml@v1
|
||||||
|
secrets: inherit
|
||||||
|
|
||||||
|
dependency-outdated:
|
||||||
|
if: >
|
||||||
|
gitea.event_name == 'workflow_dispatch' ||
|
||||||
|
(gitea.event_name == 'schedule' && gitea.event.schedule == '0 2 1 * *')
|
||||||
|
uses: https://gitea.pzetatouch.it/devops/shared-actions/.gitea/workflows/dependency-outdated.yml@v1
|
||||||
secrets: inherit
|
secrets: inherit
|
||||||
|
|||||||
@@ -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
|
||||||
@@ -1,8 +1,8 @@
|
|||||||
# Copia in: .gitea/workflows/release.yml
|
# Copia in: .gitea/workflows/release.yml
|
||||||
# Trigger: git tag v* → pubblica su npm + crea release Gitea
|
# Trigger: git tag v* → pubblica su npm + crea release Gitea
|
||||||
#
|
#
|
||||||
# NOTA: i job girano in parallelo (non sequenziali con needs).
|
# NOTA: auto-release attende npm-publish via needs.
|
||||||
# Gitea bug #31900: needs + workflow_call + checkout causa errori di autenticazione.
|
# Workaround Gitea bug #31900: token esplicito nel checkout di auto-release.yml.
|
||||||
|
|
||||||
name: Release
|
name: Release
|
||||||
|
|
||||||
@@ -13,9 +13,10 @@ on:
|
|||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
npm-publish:
|
npm-publish:
|
||||||
uses: https://gitea.com/Punga78/shared-actions/.gitea/workflows/npm-publish.yml@v1
|
uses: https://gitea.pzetatouch.it/devops/shared-actions/.gitea/workflows/npm-publish.yml@v1
|
||||||
secrets: inherit
|
secrets: inherit
|
||||||
|
|
||||||
auto-release:
|
auto-release:
|
||||||
uses: https://gitea.com/Punga78/shared-actions/.gitea/workflows/auto-release.yml@v1
|
needs: [npm-publish]
|
||||||
|
uses: https://gitea.pzetatouch.it/devops/shared-actions/.gitea/workflows/auto-release.yml@v1
|
||||||
secrets: inherit
|
secrets: inherit
|
||||||
|
|||||||
@@ -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
|
||||||
@@ -16,7 +16,7 @@ on:
|
|||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
quality-gates:
|
quality-gates:
|
||||||
uses: https://gitea.com/Punga78/shared-actions/.gitea/workflows/quality-gates.yml@v1
|
uses: https://gitea.pzetatouch.it/devops/shared-actions/.gitea/workflows/quality-gates.yml@v1
|
||||||
secrets: inherit
|
secrets: inherit
|
||||||
# with:
|
# with:
|
||||||
# node-version: '22.17' # opzionale, default già impostato
|
# node-version: '24.16.0' # opzionale, default già impostato
|
||||||
|
|||||||
@@ -11,26 +11,26 @@ on:
|
|||||||
pull_request:
|
pull_request:
|
||||||
types: [closed]
|
types: [closed]
|
||||||
schedule:
|
schedule:
|
||||||
- cron: '0 8 * * 1' # ogni lunedì alle 08:00 → security audit
|
- cron: '0 2 * * 1' # ogni lunedì alle 02:00 → security audit
|
||||||
- cron: '0 8 1 * *' # ogni 1° del mese alle 08:00 → outdated check
|
- cron: '0 4 1 * *' # ogni 1° del mese alle 04:00 → outdated check
|
||||||
workflow_dispatch:
|
workflow_dispatch:
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
branch-cleanup:
|
branch-cleanup:
|
||||||
if: gitea.event_name == 'pull_request' && gitea.event.pull_request.merged == true
|
if: gitea.event_name == 'pull_request' && gitea.event.pull_request.merged == true
|
||||||
uses: https://gitea.com/Punga78/shared-actions/.gitea/workflows/branch-cleanup.yml@v1
|
uses: https://gitea.pzetatouch.it/devops/shared-actions/.gitea/workflows/branch-cleanup.yml@v1
|
||||||
secrets: inherit
|
secrets: inherit
|
||||||
|
|
||||||
dependency-audit:
|
dependency-audit:
|
||||||
if: >
|
if: >
|
||||||
gitea.event_name == 'workflow_dispatch' ||
|
gitea.event_name == 'workflow_dispatch' ||
|
||||||
(gitea.event_name == 'schedule' && gitea.event.schedule == '0 8 * * 1')
|
(gitea.event_name == 'schedule' && gitea.event.schedule == '0 2 * * 1')
|
||||||
uses: https://gitea.com/Punga78/shared-actions/.gitea/workflows/dependency-check.yml@v1
|
uses: https://gitea.pzetatouch.it/devops/shared-actions/.gitea/workflows/dependency-check.yml@v1
|
||||||
secrets: inherit
|
secrets: inherit
|
||||||
|
|
||||||
dependency-outdated:
|
dependency-outdated:
|
||||||
if: >
|
if: >
|
||||||
gitea.event_name == 'workflow_dispatch' ||
|
gitea.event_name == 'workflow_dispatch' ||
|
||||||
(gitea.event_name == 'schedule' && gitea.event.schedule == '0 8 1 * *')
|
(gitea.event_name == 'schedule' && gitea.event.schedule == '0 4 1 * *')
|
||||||
uses: https://gitea.com/Punga78/shared-actions/.gitea/workflows/dependency-outdated.yml@v1
|
uses: https://gitea.pzetatouch.it/devops/shared-actions/.gitea/workflows/dependency-outdated.yml@v1
|
||||||
secrets: inherit
|
secrets: inherit
|
||||||
|
|||||||
@@ -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
|
||||||
@@ -1,8 +1,8 @@
|
|||||||
# Copia in: .gitea/workflows/release.yml
|
# Copia in: .gitea/workflows/release.yml
|
||||||
# Trigger: git tag v* → build Docker + crea release Gitea
|
# Trigger: git tag v* → build Docker + crea release Gitea
|
||||||
#
|
#
|
||||||
# NOTA: i job girano in parallelo (non sequenziali con needs).
|
# NOTA: auto-release attende docker-release via needs.
|
||||||
# Gitea bug #31900: needs + workflow_call + checkout causa errori di autenticazione.
|
# Workaround Gitea bug #31900: token esplicito nel checkout di auto-release.yml.
|
||||||
|
|
||||||
name: Release
|
name: Release
|
||||||
|
|
||||||
@@ -13,11 +13,13 @@ on:
|
|||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
docker-release:
|
docker-release:
|
||||||
uses: https://gitea.com/Punga78/shared-actions/.gitea/workflows/docker-release.yml@v1
|
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.yml@v1
|
||||||
secrets: inherit
|
secrets: inherit
|
||||||
with:
|
with:
|
||||||
runner: catthehacker-latest # runner con Docker pre-installato
|
runner: catthehacker-latest # runner con Docker pre-installato
|
||||||
|
|
||||||
auto-release:
|
auto-release:
|
||||||
uses: https://gitea.com/Punga78/shared-actions/.gitea/workflows/auto-release.yml@v1
|
needs: [docker-release]
|
||||||
|
uses: https://gitea.pzetatouch.it/devops/shared-actions/.gitea/workflows/auto-release.yml@v1
|
||||||
secrets: inherit
|
secrets: inherit
|
||||||
|
|||||||
@@ -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
|
||||||
@@ -24,7 +24,7 @@ on:
|
|||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
quality-gates:
|
quality-gates:
|
||||||
uses: https://gitea.com/Punga78/shared-actions/.gitea/workflows/python-quality-gates.yml@v1
|
uses: https://gitea.pzetatouch.it/devops/shared-actions/.gitea/workflows/python-quality-gates.yml@v1
|
||||||
secrets: inherit
|
secrets: inherit
|
||||||
# with:
|
# with:
|
||||||
# python-version: '3.11' # opzionale, default già impostato
|
# python-version: '3.11' # opzionale, default già impostato
|
||||||
|
|||||||
@@ -18,14 +18,14 @@ on:
|
|||||||
jobs:
|
jobs:
|
||||||
branch-cleanup:
|
branch-cleanup:
|
||||||
if: gitea.event_name == 'pull_request' && gitea.event.pull_request.merged == true
|
if: gitea.event_name == 'pull_request' && gitea.event.pull_request.merged == true
|
||||||
uses: https://gitea.com/Punga78/shared-actions/.gitea/workflows/branch-cleanup.yml@v1
|
uses: https://gitea.pzetatouch.it/devops/shared-actions/.gitea/workflows/branch-cleanup.yml@v1
|
||||||
secrets: inherit
|
secrets: inherit
|
||||||
|
|
||||||
dependency-audit:
|
dependency-audit:
|
||||||
if: >
|
if: >
|
||||||
gitea.event_name == 'workflow_dispatch' ||
|
gitea.event_name == 'workflow_dispatch' ||
|
||||||
(gitea.event_name == 'schedule' && gitea.event.schedule == '0 8 * * 1')
|
(gitea.event_name == 'schedule' && gitea.event.schedule == '0 8 * * 1')
|
||||||
uses: https://gitea.com/Punga78/shared-actions/.gitea/workflows/python-dependency-check.yml@v1
|
uses: https://gitea.pzetatouch.it/devops/shared-actions/.gitea/workflows/python-dependency-check.yml@v1
|
||||||
secrets: inherit
|
secrets: inherit
|
||||||
# with:
|
# with:
|
||||||
# python-version: '3.11'
|
# python-version: '3.11'
|
||||||
@@ -35,7 +35,7 @@ jobs:
|
|||||||
if: >
|
if: >
|
||||||
gitea.event_name == 'workflow_dispatch' ||
|
gitea.event_name == 'workflow_dispatch' ||
|
||||||
(gitea.event_name == 'schedule' && gitea.event.schedule == '0 8 1 * *')
|
(gitea.event_name == 'schedule' && gitea.event.schedule == '0 8 1 * *')
|
||||||
uses: https://gitea.com/Punga78/shared-actions/.gitea/workflows/python-dependency-outdated.yml@v1
|
uses: https://gitea.pzetatouch.it/devops/shared-actions/.gitea/workflows/python-dependency-outdated.yml@v1
|
||||||
secrets: inherit
|
secrets: inherit
|
||||||
# with:
|
# with:
|
||||||
# python-version: '3.11'
|
# python-version: '3.11'
|
||||||
|
|||||||
@@ -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
|
||||||
@@ -1,8 +1,8 @@
|
|||||||
# Copia in: .gitea/workflows/release.yml
|
# Copia in: .gitea/workflows/release.yml
|
||||||
# Trigger: git tag v* → build Docker + crea release Gitea
|
# Trigger: git tag v* → build Docker + crea release Gitea
|
||||||
#
|
#
|
||||||
# NOTA: i job girano in parallelo (non sequenziali con needs).
|
# NOTA: auto-release attende docker-release via needs.
|
||||||
# Gitea bug #31900: needs + workflow_call + checkout causa errori di autenticazione.
|
# Workaround Gitea bug #31900: token esplicito nel checkout di python-auto-release.yml.
|
||||||
#
|
#
|
||||||
# Prerequisiti:
|
# Prerequisiti:
|
||||||
# - Dockerfile presente nella root del progetto
|
# - Dockerfile presente nella root del progetto
|
||||||
@@ -18,7 +18,8 @@ on:
|
|||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
docker-release:
|
docker-release:
|
||||||
uses: https://gitea.com/Punga78/shared-actions/.gitea/workflows/python-docker-release.yml@v1
|
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.yml@v1
|
||||||
secrets: inherit
|
secrets: inherit
|
||||||
with:
|
with:
|
||||||
runner: catthehacker-latest # runner con Docker pre-installato
|
runner: catthehacker-latest # runner con Docker pre-installato
|
||||||
@@ -26,5 +27,6 @@ jobs:
|
|||||||
# install-extras: 'dev' # opzionale
|
# install-extras: 'dev' # opzionale
|
||||||
|
|
||||||
auto-release:
|
auto-release:
|
||||||
uses: https://gitea.com/Punga78/shared-actions/.gitea/workflows/python-auto-release.yml@v1
|
needs: [docker-release]
|
||||||
|
uses: https://gitea.pzetatouch.it/devops/shared-actions/.gitea/workflows/python-auto-release.yml@v1
|
||||||
secrets: inherit
|
secrets: inherit
|
||||||
|
|||||||
Reference in New Issue
Block a user