name: Build package # One workflow for checks, build and release, because the publish step has to # depend on the checks and `needs:` only works between jobs of one workflow. on: push: branches: - main tags: - 'v*' pull_request: jobs: php-lint: runs-on: gitea-runner-server03 strategy: matrix: php-version: ['8.2', '8.3', '8.4'] steps: - uses: actions/checkout@v7 - uses: shivammathur/setup-php@v2 with: php-version: ${{ matrix.php-version }} coverage: none - name: Syntax check run: | find lib tests appinfo -name '*.php' -print0 | xargs -0 -n1 -- php -l xml-lint: runs-on: gitea-runner-server03 steps: - uses: actions/checkout@v7 - name: Install xmllint run: | apt-get update apt-get install -y --no-install-recommends libxml2-utils - name: Download appstore schema run: wget -q https://raw.githubusercontent.com/nextcloud/appstore/master/nextcloudappstore/api/v1/release/info.xsd -O info.xsd - name: Validate appinfo/info.xml run: xmllint --schema info.xsd appinfo/info.xml --noout unit-tests: runs-on: gitea-runner-server03 steps: - uses: actions/checkout@v7 - uses: shivammathur/setup-php@v2 with: php-version: '8.3' extensions: sqlite, pdo_sqlite coverage: none - name: Install dependencies run: composer install --no-progress --prefer-dist - name: Run unit tests run: composer run test:unit # Building and publishing stay in one job on purpose: handing the tarball to a # separate publish job would mean actions/upload-artifact (unusable here, see # CLAUDE.md) or actions/cache, and neither is worth a second Gitea backend API # in the critical path. On a pull request this job stops after `make appstore` # and just acts as a build check. package: needs: [php-lint, xml-lint, unit-tests] runs-on: gitea-runner-server03 # contents: write maps to Code: write (deleting the latest-main tag) plus # Releases: write (creating releases and uploading the asset) - everything # the publish step below needs, so it runs on the built-in GITEA_TOKEN. permissions: contents: write steps: - uses: actions/checkout@v7 - uses: actions/setup-node@v7 with: node-version: '24' - name: Install JS dependencies run: npm install - name: Build frontend run: npm run build - name: Package appstore artifact run: make appstore - name: Publish release if: gitea.event_name == 'push' env: GITEA_API: ${{ gitea.server_url }}/api/v1 REPO: ${{ gitea.repository }} TOKEN: ${{ secrets.GITEA_TOKEN }} SHA: ${{ gitea.sha }} REF: ${{ gitea.ref }} run: | set -e ASSET="build/artifacts/appstore/workflow_deck_automation.tar.gz" case "$REF" in refs/tags/*) TAG="${REF#refs/tags/}" RECREATE_TAG=false PRERELEASE=false TITLE="$TAG" BODY="Release $TAG" ;; *) TAG="latest-main" RECREATE_TAG=true PRERELEASE=true TITLE="Latest main build" BODY="Automatisch aus $SHA gebaut - nur zum schnellen Testen/Deployen, kein offizielles Release." ;; esac api() { curl -sS -H "Authorization: token $TOKEN" "$@"; } # Always drop an existing release for this tag first: the rolling tag is # rebuilt on every push, and a moved version tag has to publish the new # build instead of failing on a duplicate asset name. api "$GITEA_API/repos/$REPO/releases/tags/$TAG" -o /tmp/old_release.json OLD_ID=$(node -e "try{const j=require('/tmp/old_release.json');console.log(j.id||'')}catch(e){console.log('')}") if [ -n "$OLD_ID" ]; then api -X DELETE "$GITEA_API/repos/$REPO/releases/$OLD_ID" fi # Only latest-main gets its tag recreated - a version tag was just pushed # and must survive, otherwise this job would delete what triggered it. if [ "$RECREATE_TAG" = true ]; then api -X DELETE "$GITEA_API/repos/$REPO/tags/$TAG" > /dev/null || true fi api -X POST -H "Content-Type: application/json" \ -d "{\"tag_name\":\"$TAG\",\"target_commitish\":\"$SHA\",\"name\":\"$TITLE\",\"body\":\"$BODY\",\"prerelease\":$PRERELEASE}" \ "$GITEA_API/repos/$REPO/releases" -o /tmp/new_release.json NEW_ID=$(node -e "console.log(require('/tmp/new_release.json').id)") api -X POST -F "attachment=@$ASSET" \ "$GITEA_API/repos/$REPO/releases/$NEW_ID/assets?name=workflow_deck_automation.tar.gz"