From ee515caaf082661caf1a3b7257797301a166df64 Mon Sep 17 00:00:00 2001 From: Lukas Schwarz Date: Mon, 9 Feb 2026 12:11:27 +0100 Subject: [PATCH 01/25] feat: Add basic GH Actions file --- .github/workflows/release.yml | 544 ++++++++++++++++++++++++++++++++++ 1 file changed, 544 insertions(+) create mode 100644 .github/workflows/release.yml diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 00000000000..21309af236f --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,544 @@ +name: Release + +on: + push: + tags: + - 'v*' + +env: + # Production release tags (semver patterns) + PRODUCTION_RELEASE_TAGS: '5.0,7,8' + + # Docker configuration + DOCKER_REPO_ROLLING: kwlschwarz/ocis-rolling + DOCKER_REPO_PRODUCTION: kwlschwarz/ocis + + # Build configuration + GO_VERSION: '1.25.7' + NODE_VERSION: '24' + PHP_VERSION: '8.4' + PNPM_VERSION: '10.11.0' + +jobs: + # ============================================================================ + # PREPARATION JOBS + # ============================================================================ + + determine-release-type: + name: Determine Release Type + runs-on: ubuntu-latest + outputs: + version: ${{ steps.version.outputs.version }} + is_production: ${{ steps.check.outputs.is_production }} + is_prerelease: ${{ steps.check.outputs.is_prerelease }} + release_folder: ${{ steps.check.outputs.release_folder }} + docker_repos: ${{ steps.check.outputs.docker_repos }} + steps: + - name: Extract version + id: version + run: | + VERSION=${GITHUB_REF#refs/tags/v} + echo "version=$VERSION" >> $GITHUB_OUTPUT + echo "Version: $VERSION" + + - name: Check release type + id: check + run: | + VERSION="${{ steps.version.outputs.version }}" + + # Check if production release + IS_PRODUCTION=false + for TAG in ${PRODUCTION_RELEASE_TAGS//,/ }; do + if [[ "$VERSION" == "$TAG"* ]]; then + IS_PRODUCTION=true + break + fi + done + echo "is_production=$IS_PRODUCTION" >> $GITHUB_OUTPUT + + # Check if prerelease (contains -, like alpha/beta/rc) + IS_PRERELEASE=false + if [[ "$VERSION" == *"-"* ]]; then + IS_PRERELEASE=true + fi + echo "is_prerelease=$IS_PRERELEASE" >> $GITHUB_OUTPUT + + # Determine release folder + if [[ "$IS_PRERELEASE" == "true" ]]; then + FOLDER="testing" + else + FOLDER="stable" + fi + echo "release_folder=$FOLDER" >> $GITHUB_OUTPUT + + # Determine Docker repos + if [[ "$IS_PRODUCTION" == "true" ]]; then + REPOS=[\"$DOCKER_REPO_ROLLING\",\"$DOCKER_REPO_PRODUCTION\"] + else + REPOS=[\"$DOCKER_REPO_ROLLING\"] + fi + echo "docker_repos=$REPOS" >> $GITHUB_OUTPUT + + echo "Release Type Summary:" + echo " Version: $VERSION" + echo " Production: $IS_PRODUCTION" + echo " Prerelease: $IS_PRERELEASE" + echo " Folder: $FOLDER" + echo " Docker Repos: $REPOS" + + # ============================================================================ + # CODE GENERATION + # ============================================================================ + + + debug-outputs: + name: Debug + runs-on: ubuntu-latest + needs: determine-release-type + steps: + - name: Checkout code + run: echo ${{ fromJSON(needs.determine-release-type.outputs.docker_repos) }} + + generate-code: + name: Generate code + runs-on: ubuntu-latest + steps: + - name: Checkout code + uses: actions/checkout@v6 + + - name: Setup Go + uses: actions/setup-go@v6 + with: + go-version: ${{ env.GO_VERSION }} + + - name: Setup Node.js + uses: actions/setup-node@v6 + with: + node-version: ${{ env.NODE_VERSION }} + + - name: Install npm packages + run: npm install --silent -g yarn npx --force + + - name: Setup pnpm + uses: pnpm/action-setup@v4 + with: + version: ${{ env.PNPM_VERSION }} + + - name: Generate Node.js code + run: | + pnpm config set store-dir ./.pnpm-store + make ci-node-generate + env: + CHROMEDRIVER_SKIP_DOWNLOAD: 'true' + + - name: Generate Go code + run: make ci-go-generate + env: + BUF_TOKEN: ${{ secrets.BUF_API_TOKEN }} + + - name: Upload generated code + uses: actions/upload-artifact@v6 + with: + name: generated-code + path: | + . + !.git + retention-days: 1 + + # ============================================================================ + # DOCKER BUILDS + # ============================================================================ + + docker-build: + name: Build Docker Image (${{ matrix.arch }}-${{ matrix.repo }}) + runs-on: ${{ matrix.arch == 'amd64' && 'ubuntu-24.04' || matrix.arch == 'arm64' && 'ubuntu-24.04-arm' }} + needs: [determine-release-type, generate-code] + outputs: + digest-amd64-rolling: ${{ steps.write-digest.outputs.digest-amd64-rolling }} + digest-arm64-rolling: ${{ steps.write-digest.outputs.digest-arm64-rolling }} + digest-amd64: ${{ steps.write-digest.outputs.digest-amd64 }} + digest-arm64: ${{ steps.write-digest.outputs.digest-arm64 }} + strategy: + matrix: + arch: [amd64, arm64] + repo: ${{ fromJSON(needs.determine-release-type.outputs.docker_repos) }} + steps: + - name: Checkout code + uses: actions/checkout@v6 + + - name: Download generated code + uses: actions/download-artifact@v7 + with: + name: generated-code + path: . + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v3 + + - name: Login to DockerHub + uses: docker/login-action@v3 + with: + username: ${{ secrets.DOCKER_USERNAME }} + password: ${{ secrets.DOCKER_PASSWORD }} + + - name: Setup Go + uses: actions/setup-go@v6 + with: + go-version: ${{ env.GO_VERSION }} + + - name: Install additional packages + run: | + sudo apt update + sudo apt install -y libvips libvips-dev + + - name: Build binary + run: make -C ocis release-linux-docker-${{ matrix.arch }} + env: + CGO_ENABLED: 1 + GOOS: linux + ENABLE_VIPS: true + + - name: Extract metadata + id: meta + uses: docker/metadata-action@v5 + with: + images: ${{ matrix.repo }} + tags: | + type=semver,pattern={{version}},suffix=-linux-${{ matrix.arch }} + type=semver,pattern={{major}}.{{minor}},suffix=-linux-${{ matrix.arch }} + type=semver,pattern={{major}},suffix=-linux-${{ matrix.arch }} + + - name: Build and push Docker image + id: build-and-push + uses: docker/build-push-action@v7 + with: + context: ocis + file: ocis/docker/Dockerfile.linux.${{ matrix.arch }} + platforms: linux/${{ matrix.arch }} + push: true + provenance: false + tags: ${{ steps.meta.outputs.tags }} + labels: ${{ steps.meta.outputs.labels }} + build-args: | + REVISION=${{ github.sha }} + VERSION=${{ needs.determine-release-type.outputs.version }} + + - name: Write Digest + id: write-digest + run: | + if [[ "${{ matrix.repo }}" == *"rolling"* ]]; then + echo "digest-${{ matrix.arch }}-rolling=${{ steps.build-and-push.outputs.digest }}" >> $GITHUB_OUTPUT + else + echo "digest-${{ matrix.arch }}=${{ steps.build-and-push.outputs.digest }}" >> $GITHUB_OUTPUT + fi + + + docker-manifest: + name: Create Docker Manifest (${{ matrix.repo }}) + runs-on: ubuntu-latest + needs: [determine-release-type, docker-build] + strategy: + matrix: + repo: ${{ fromJSON(needs.determine-release-type.outputs.docker_repos) }} + steps: + - name: Login to DockerHub + uses: docker/login-action@v3 + with: + username: ${{ secrets.DOCKER_USERNAME }} + password: ${{ secrets.DOCKER_PASSWORD }} + + - name: Create and push multiarch manifest (rolling) + uses: int128/docker-manifest-create-action@v2.16.0 + if: ${{ contains(matrix.repo, 'rolling') }} + with: + tags: ${{ matrix.repo }}:${{ needs.determine-release-type.outputs.version }} + sources: | + ${{ needs.docker-build.outputs.digest-amd64-rolling }} + ${{ needs.docker-build.outputs.digest-arm64-rolling }} + + - name: Create and push multiarch manifest + uses: int128/docker-manifest-create-action@v2.16.0 + if: ${{ ! contains(matrix.repo, 'rolling') }} + with: + tags: ${{ matrix.repo }}:${{ needs.determine-release-type.outputs.version }} + sources: | + ${{ needs.docker-build.outputs.digest-amd64 }} + ${{ needs.docker-build.outputs.digest-arm64 }} + + docker-readme: + name: Update Docker README + runs-on: ubuntu-latest + needs: [determine-release-type, docker-manifest] + strategy: + matrix: + repo: ${{ fromJSON(needs.determine-release-type.outputs.docker_repos) }} + steps: + - name: Checkout code + uses: actions/checkout@v6 + + - name: Update DockerHub README + uses: peter-evans/dockerhub-description@v5 + with: + username: ${{ secrets.DOCKER_USERNAME }} + password: ${{ secrets.DOCKER_PASSWORD }} + repository: ${{ matrix.repo }} + short-description: Docker images for ownCloud Infinite Scale + + # ============================================================================ + # BINARY BUILDS + # ============================================================================ + + build-binaries: + name: Build Binaries (${{ matrix.os }}) + runs-on: ubuntu-latest + needs: [determine-release-type, generate-code] + strategy: + matrix: + os: [linux, darwin] + steps: + - name: Checkout code + uses: actions/checkout@v6 + + - name: Download generated code + uses: actions/download-artifact@v7 + with: + name: generated-code + path: . + + - name: Setup Go + uses: actions/setup-go@v5 + with: + go-version: ${{ env.GO_VERSION }} + + - name: Build binaries + run: make -C ocis release-${{ matrix.os }} + + - name: Finish build + run: | + make -C ocis release-finish + if [ "${{ matrix.os }}" == "linux" ]; then + cp assets/End-User-License-Agreement-for-ownCloud-Infinite-Scale.pdf ocis/dist/release/ + fi + + - name: Upload binaries + uses: actions/upload-artifact@v6 + with: + name: binaries-${{ matrix.os }} + path: ocis/dist/release/* + retention-days: 1 + + # ============================================================================ + # SECURITY SCAN + # ============================================================================ + + security-scan-trivy: + name: Trivy Security Scan + runs-on: ubuntu-latest + steps: + - name: Checkout code + uses: actions/checkout@v6 + + - name: Run Trivy vulnerability scanner + uses: aquasecurity/trivy-action@0.35.0 + with: + scan-type: 'fs' + format: 'table' + exit-code: '0' + severity: 'CRITICAL,HIGH' + + # ============================================================================ + # LICENSE CHECK + # ============================================================================ + + license-check: + name: Check and Upload Licenses + runs-on: ubuntu-latest + needs: [determine-release-type, generate-code] + steps: + - name: Checkout code + uses: actions/checkout@v6 + + - name: Download generated code + uses: actions/download-artifact@v7 + with: + name: generated-code + path: . + + - name: Setup Node.js + uses: actions/setup-node@v4 + with: + node-version: ${{ env.NODE_VERSION }} + + - name: Setup Go + uses: actions/setup-go@v5 + with: + go-version: ${{ env.GO_VERSION }} + + - name: Install pnpm + run: npm install --silent -g yarn npx "pnpm@$PNPM_VERSION" --force + + - name: Check Node.js licenses + run: make ci-node-check-licenses + + - name: Save Node.js licenses + run: make ci-node-save-licenses + + - name: Check Go licenses + run: make ci-go-check-licenses + + - name: Save Go licenses + run: make ci-go-save-licenses + + - name: Create tarball + run: | + cd third-party-licenses + tar -czf ../third-party-licenses.tar.gz * + + - name: Upload licenses artifact + uses: actions/upload-artifact@v6 + with: + name: third-party-licenses + path: third-party-licenses.tar.gz + retention-days: 1 + + # ============================================================================ + # CHANGELOG GENERATION + # ============================================================================ + + generate-changelog: + name: Generate Changelog + runs-on: ubuntu-latest + needs: [determine-release-type] + steps: + - name: Checkout code + uses: actions/checkout@v6 + with: + fetch-depth: 0 + + - name: Setup Go + uses: actions/setup-go@v5 + with: + go-version: ${{ env.GO_VERSION }} + + - name: Generate changelog + run: | + VERSION="${{ needs.determine-release-type.outputs.version }}" + # Remove pre-release suffix for changelog + CHANGELOG_VERSION=$(echo $VERSION | cut -d'-' -f1) + make changelog CHANGELOG_VERSION=$CHANGELOG_VERSION + + - name: Upload changelog + uses: actions/upload-artifact@v6 + with: + name: changelog + path: ocis/dist/CHANGELOG.md + retention-days: 1 + + # ============================================================================ + # GITHUB RELEASE + # ============================================================================ + + create-github-release: + name: Create GitHub Release + runs-on: ubuntu-latest + needs: + - determine-release-type + - build-binaries + - docker-build + - license-check + - generate-changelog + steps: + - name: Download Linux binaries + uses: actions/download-artifact@v7 + with: + name: binaries-linux + path: release-assets + + - name: Download Darwin binaries + uses: actions/download-artifact@v7 + with: + name: binaries-darwin + path: release-assets + + - name: Download licenses + uses: actions/download-artifact@v7 + with: + name: third-party-licenses + path: release-assets + + - name: Download changelog + uses: actions/download-artifact@v7 + with: + name: changelog + path: . + + - name: Create GitHub Release + uses: softprops/action-gh-release@v2.4.2 + with: + name: ${{ needs.determine-release-type.outputs.version }} + body_path: CHANGELOG.md + files: release-assets/* + prerelease: ${{ needs.determine-release-type.outputs.is_prerelease == 'true' }} + draft: false + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + + + # ============================================================================ + # NOTIFICATION + # ============================================================================ + + notify: + name: Notify Matrix room + runs-on: ubuntu-latest + if: always() + needs: + - determine-release-type + - docker-build + - docker-manifest + - docker-readme + - generate-code + - build-binaries + - license-check + - generate-changelog + - create-github-release + - security-scan-trivy + steps: + - name: Set short git commit SHA + run: echo "SHORT_SHA=`echo ${{ github.sha }} | cut -c1-8`" >> $GITHUB_ENV + + - name: Decide whether the needed jobs succeeded or failed + id: check-state + continue-on-error: true + uses: re-actors/alls-green@release/v1 + with: + jobs: ${{ toJSON(needs) }} + + - name: Set failure message + if: ${{ steps.check-state.outcome != 'success' }} + run: echo 'BUILD_STATUS=❌️ Failure' >> $GITHUB_ENV + + - name: Set success message + if: ${{ steps.check-state.outcome == 'success' }} + run: echo 'BUILD_STATUS=✅ Success' >> $GITHUB_ENV + + - name: Set build source default + run: echo 'BUILD_SOURCE=${{ github.ref_name }}' >> $GITHUB_ENV + + - name: Set build source cron/schedule + if: github.event_name == 'schedule' + run: echo 'BUILD_SOURCE=nightly-${{ github.ref_name }}' >> $GITHUB_ENV + + - name: Set build source tag + if: github.ref_type == 'tag' + run: echo 'BUILD_SOURCE=tag ${{ github.ref_name }}' >> $GITHUB_ENV + + - name: Send message to Matrix room + id: matrix-chat-message + uses: fadenb/matrix-chat-message@v0.0.6 + with: + homeserver: ${{ secrets.MATRIX_HOMESERVER }} + token: ${{ secrets.MATRIX_TOKEN }} + channel: ${{ secrets.MATRIX_ROOMID }} + message: | + **${{ env.BUILD_STATUS }}** [${{ github.repository }}#${{ env.SHORT_SHA }}](${{ github.server_url}}/${{ github.repository }}/actions/runs/${{ github.run_id }}) (${{ env.BUILD_SOURCE }}) by **${{ github.triggering_actor }}** From 52f56ae7fd926152b2b50b4563aec7dbe9650eb1 Mon Sep 17 00:00:00 2001 From: Michal Klos Date: Wed, 8 Apr 2026 13:26:25 +0200 Subject: [PATCH 02/25] feat: [OCISDEV-783] release pipeline --- .github/workflows/release.yml | 53 +++++++++++++++++++++++++++++++++-- 1 file changed, 50 insertions(+), 3 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 21309af236f..3993d94e17c 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -4,6 +4,16 @@ on: push: tags: - 'v*' + workflow_dispatch: + inputs: + dry_run: + description: 'Dry run — build everything but skip Docker push and GitHub Release creation' + type: boolean + default: true + version_override: + description: 'Version to use for dry-run (e.g. 8.0.2-dryrun). Leave empty to auto-detect from latest tag.' + type: string + default: '' env: # Production release tags (semver patterns) @@ -33,13 +43,35 @@ jobs: is_prerelease: ${{ steps.check.outputs.is_prerelease }} release_folder: ${{ steps.check.outputs.release_folder }} docker_repos: ${{ steps.check.outputs.docker_repos }} + dry_run: ${{ steps.version.outputs.dry_run }} steps: + - name: Checkout code + if: ${{ github.event_name == 'workflow_dispatch' && inputs.dry_run && inputs.version_override == '' }} + uses: actions/checkout@v6 + with: + fetch-depth: 0 + - name: Extract version id: version run: | - VERSION=${GITHUB_REF#refs/tags/v} + if [[ "${{ github.event_name }}" == "workflow_dispatch" ]]; then + DRY_RUN="${{ inputs.dry_run }}" + if [[ -n "${{ inputs.version_override }}" ]]; then + VERSION="${{ inputs.version_override }}" + else + # Auto-detect: bump patch of latest tag and append -dryrun + LATEST_TAG=$(git describe --tags --abbrev=0 2>/dev/null || echo "v0.0.0") + LATEST_VERSION="${LATEST_TAG#v}" + IFS='.' read -r MAJOR MINOR PATCH <<< "${LATEST_VERSION%%-*}" + VERSION="${MAJOR}.${MINOR}.$((PATCH + 1))-dryrun" + fi + else + VERSION=${GITHUB_REF#refs/tags/v} + DRY_RUN=false + fi echo "version=$VERSION" >> $GITHUB_OUTPUT - echo "Version: $VERSION" + echo "dry_run=$DRY_RUN" >> $GITHUB_OUTPUT + echo "Version: $VERSION Dry-run: $DRY_RUN" - name: Check release type id: check @@ -152,6 +184,7 @@ jobs: docker-build: name: Build Docker Image (${{ matrix.arch }}-${{ matrix.repo }}) runs-on: ${{ matrix.arch == 'amd64' && 'ubuntu-24.04' || matrix.arch == 'arm64' && 'ubuntu-24.04-arm' }} + if: ${{ needs.determine-release-type.outputs.dry_run != 'true' }} needs: [determine-release-type, generate-code] outputs: digest-amd64-rolling: ${{ steps.write-digest.outputs.digest-amd64-rolling }} @@ -236,6 +269,7 @@ jobs: docker-manifest: name: Create Docker Manifest (${{ matrix.repo }}) runs-on: ubuntu-latest + if: ${{ needs.determine-release-type.outputs.dry_run != 'true' }} needs: [determine-release-type, docker-build] strategy: matrix: @@ -268,6 +302,7 @@ jobs: docker-readme: name: Update Docker README runs-on: ubuntu-latest + if: ${{ needs.determine-release-type.outputs.dry_run != 'true' }} needs: [determine-release-type, docker-manifest] strategy: matrix: @@ -444,7 +479,6 @@ jobs: needs: - determine-release-type - build-binaries - - docker-build - license-check - generate-changelog steps: @@ -473,6 +507,7 @@ jobs: path: . - name: Create GitHub Release + if: ${{ needs.determine-release-type.outputs.dry_run != 'true' }} uses: softprops/action-gh-release@v2.4.2 with: name: ${{ needs.determine-release-type.outputs.version }} @@ -483,6 +518,16 @@ jobs: env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + - name: Dry-run summary + if: ${{ needs.determine-release-type.outputs.dry_run == 'true' }} + run: | + echo "## DRY RUN — artifacts that would be uploaded to a GitHub Release:" + find release-assets/ -type f | sort | while read f; do + size=$(stat -c%s "$f") + hash=$(sha256sum "$f" | awk '{print $1}') + printf " %-60s %s bytes sha256:%s\n" "$(basename $f)" "$size" "$hash" + done + # ============================================================================ # NOTIFICATION @@ -512,6 +557,8 @@ jobs: continue-on-error: true uses: re-actors/alls-green@release/v1 with: + # docker-build/manifest/readme are skipped on dry-run — treat skip as success + allowed-skips: docker-build, docker-manifest, docker-readme jobs: ${{ toJSON(needs) }} - name: Set failure message From 0bd726cecdca64c2e0cae44df0efebb1b9179184 Mon Sep 17 00:00:00 2001 From: Michal Klos Date: Wed, 8 Apr 2026 13:58:22 +0200 Subject: [PATCH 03/25] feat: [OCISDEV-783] release pipeline --- .github/workflows/release.yml | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 3993d94e17c..aa565824ed3 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -4,6 +4,8 @@ on: push: tags: - 'v*' + branches: + - 'feat/release-pipeline**' workflow_dispatch: inputs: dry_run: @@ -46,7 +48,7 @@ jobs: dry_run: ${{ steps.version.outputs.dry_run }} steps: - name: Checkout code - if: ${{ github.event_name == 'workflow_dispatch' && inputs.dry_run && inputs.version_override == '' }} + if: ${{ (github.event_name == 'workflow_dispatch' && inputs.dry_run && inputs.version_override == '') || github.ref_type == 'branch' }} uses: actions/checkout@v6 with: fetch-depth: 0 @@ -65,6 +67,13 @@ jobs: IFS='.' read -r MAJOR MINOR PATCH <<< "${LATEST_VERSION%%-*}" VERSION="${MAJOR}.${MINOR}.$((PATCH + 1))-dryrun" fi + elif [[ "${{ github.ref_type }}" == "branch" ]]; then + # Branch push (e.g. feat/release-pipeline**) — always a dry-run + DRY_RUN=true + LATEST_TAG=$(git describe --tags --abbrev=0 2>/dev/null || echo "v0.0.0") + LATEST_VERSION="${LATEST_TAG#v}" + IFS='.' read -r MAJOR MINOR PATCH <<< "${LATEST_VERSION%%-*}" + VERSION="${MAJOR}.${MINOR}.$((PATCH + 1))-dryrun" else VERSION=${GITHUB_REF#refs/tags/v} DRY_RUN=false From b9c6a06a027521d50f2230de92b4f3cc403195bd Mon Sep 17 00:00:00 2001 From: Michal Klos Date: Wed, 8 Apr 2026 14:46:36 +0200 Subject: [PATCH 04/25] feat: [OCISDEV-783] release pipeline, DeepDiver's review comments --- .github/workflows/release.yml | 117 ++++++++++++++++++---------------- 1 file changed, 63 insertions(+), 54 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index aa565824ed3..d33ea97a812 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -22,8 +22,8 @@ env: PRODUCTION_RELEASE_TAGS: '5.0,7,8' # Docker configuration - DOCKER_REPO_ROLLING: kwlschwarz/ocis-rolling - DOCKER_REPO_PRODUCTION: kwlschwarz/ocis + DOCKER_REPO_ROLLING: owncloud/ocis-rolling + DOCKER_REPO_PRODUCTION: owncloud/ocis # Build configuration GO_VERSION: '1.25.7' @@ -49,7 +49,7 @@ jobs: steps: - name: Checkout code if: ${{ (github.event_name == 'workflow_dispatch' && inputs.dry_run && inputs.version_override == '') || github.ref_type == 'branch' }} - uses: actions/checkout@v6 + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: fetch-depth: 0 @@ -131,29 +131,20 @@ jobs: # CODE GENERATION # ============================================================================ - - debug-outputs: - name: Debug - runs-on: ubuntu-latest - needs: determine-release-type - steps: - - name: Checkout code - run: echo ${{ fromJSON(needs.determine-release-type.outputs.docker_repos) }} - generate-code: name: Generate code runs-on: ubuntu-latest steps: - name: Checkout code - uses: actions/checkout@v6 + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - name: Setup Go - uses: actions/setup-go@v6 + uses: actions/setup-go@4b73464bb391d4059bd26b0524d20df3927bd417 # v6.3.0 with: go-version: ${{ env.GO_VERSION }} - name: Setup Node.js - uses: actions/setup-node@v6 + uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v6.3.0 with: node-version: ${{ env.NODE_VERSION }} @@ -161,7 +152,7 @@ jobs: run: npm install --silent -g yarn npx --force - name: Setup pnpm - uses: pnpm/action-setup@v4 + uses: pnpm/action-setup@fc06bc1257f339d1d5d8b3a19a8cae5388b55320 # v4 with: version: ${{ env.PNPM_VERSION }} @@ -178,7 +169,7 @@ jobs: BUF_TOKEN: ${{ secrets.BUF_API_TOKEN }} - name: Upload generated code - uses: actions/upload-artifact@v6 + uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4 with: name: generated-code path: | @@ -206,25 +197,25 @@ jobs: repo: ${{ fromJSON(needs.determine-release-type.outputs.docker_repos) }} steps: - name: Checkout code - uses: actions/checkout@v6 + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - name: Download generated code - uses: actions/download-artifact@v7 + uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4 with: name: generated-code path: . - name: Set up Docker Buildx - uses: docker/setup-buildx-action@v3 + uses: docker/setup-buildx-action@8d2750c68a42422c14e847fe6c8ac0403b4cbd6f # v3 - name: Login to DockerHub - uses: docker/login-action@v3 + uses: docker/login-action@c94ce9fb468520275223c153574b00df6fe4bcc9 # v3 with: username: ${{ secrets.DOCKER_USERNAME }} password: ${{ secrets.DOCKER_PASSWORD }} - name: Setup Go - uses: actions/setup-go@v6 + uses: actions/setup-go@4b73464bb391d4059bd26b0524d20df3927bd417 # v6.3.0 with: go-version: ${{ env.GO_VERSION }} @@ -242,7 +233,7 @@ jobs: - name: Extract metadata id: meta - uses: docker/metadata-action@v5 + uses: docker/metadata-action@c299e40c65443455700f0fdfc63efafe5b349051 # v5 with: images: ${{ matrix.repo }} tags: | @@ -252,7 +243,7 @@ jobs: - name: Build and push Docker image id: build-and-push - uses: docker/build-push-action@v7 + uses: docker/build-push-action@10e90e3645eae34f1e60eeb005ba3a3d33f178e8 # v6 with: context: ocis file: ocis/docker/Dockerfile.linux.${{ matrix.arch }} @@ -274,6 +265,24 @@ jobs: echo "digest-${{ matrix.arch }}=${{ steps.build-and-push.outputs.digest }}" >> $GITHUB_OUTPUT fi + docker-scan: + name: Scan Docker Image (${{ matrix.arch }}-${{ matrix.repo }}) + runs-on: ubuntu-latest + if: ${{ needs.determine-release-type.outputs.dry_run != 'true' }} + needs: [determine-release-type, docker-build] + strategy: + matrix: + arch: [amd64] + repo: ${{ fromJSON(needs.determine-release-type.outputs.docker_repos) }} + steps: + - name: Run Trivy vulnerability scanner on Docker image + uses: aquasecurity/trivy-action@57a97c7e7821a5776cebc9bb87c984fa69cba8f1 # 0.35.0 + with: + image-ref: ${{ matrix.repo }}:${{ needs.determine-release-type.outputs.version }}-linux-${{ matrix.arch }} + scan-type: 'image' + format: 'table' + exit-code: '0' + severity: 'CRITICAL,HIGH' docker-manifest: name: Create Docker Manifest (${{ matrix.repo }}) @@ -285,13 +294,13 @@ jobs: repo: ${{ fromJSON(needs.determine-release-type.outputs.docker_repos) }} steps: - name: Login to DockerHub - uses: docker/login-action@v3 + uses: docker/login-action@c94ce9fb468520275223c153574b00df6fe4bcc9 # v3 with: username: ${{ secrets.DOCKER_USERNAME }} password: ${{ secrets.DOCKER_PASSWORD }} - name: Create and push multiarch manifest (rolling) - uses: int128/docker-manifest-create-action@v2.16.0 + uses: int128/docker-manifest-create-action@44422a4b046d55dc036df622039ed3aec43c613c # v2.17.0 if: ${{ contains(matrix.repo, 'rolling') }} with: tags: ${{ matrix.repo }}:${{ needs.determine-release-type.outputs.version }} @@ -300,7 +309,7 @@ jobs: ${{ needs.docker-build.outputs.digest-arm64-rolling }} - name: Create and push multiarch manifest - uses: int128/docker-manifest-create-action@v2.16.0 + uses: int128/docker-manifest-create-action@44422a4b046d55dc036df622039ed3aec43c613c # v2.17.0 if: ${{ ! contains(matrix.repo, 'rolling') }} with: tags: ${{ matrix.repo }}:${{ needs.determine-release-type.outputs.version }} @@ -318,10 +327,10 @@ jobs: repo: ${{ fromJSON(needs.determine-release-type.outputs.docker_repos) }} steps: - name: Checkout code - uses: actions/checkout@v6 + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - name: Update DockerHub README - uses: peter-evans/dockerhub-description@v5 + uses: peter-evans/dockerhub-description@dc67fad7001ef9e8e3c124cb7a64e16d0a63d864 # v3 with: username: ${{ secrets.DOCKER_USERNAME }} password: ${{ secrets.DOCKER_PASSWORD }} @@ -341,16 +350,16 @@ jobs: os: [linux, darwin] steps: - name: Checkout code - uses: actions/checkout@v6 + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - name: Download generated code - uses: actions/download-artifact@v7 + uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4 with: name: generated-code path: . - name: Setup Go - uses: actions/setup-go@v5 + uses: actions/setup-go@4b73464bb391d4059bd26b0524d20df3927bd417 # v6.3.0 with: go-version: ${{ env.GO_VERSION }} @@ -365,7 +374,7 @@ jobs: fi - name: Upload binaries - uses: actions/upload-artifact@v6 + uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4 with: name: binaries-${{ matrix.os }} path: ocis/dist/release/* @@ -376,14 +385,14 @@ jobs: # ============================================================================ security-scan-trivy: - name: Trivy Security Scan + name: Trivy Filesystem Scan runs-on: ubuntu-latest steps: - name: Checkout code - uses: actions/checkout@v6 + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - name: Run Trivy vulnerability scanner - uses: aquasecurity/trivy-action@0.35.0 + uses: aquasecurity/trivy-action@57a97c7e7821a5776cebc9bb87c984fa69cba8f1 # 0.35.0 with: scan-type: 'fs' format: 'table' @@ -400,21 +409,21 @@ jobs: needs: [determine-release-type, generate-code] steps: - name: Checkout code - uses: actions/checkout@v6 + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - name: Download generated code - uses: actions/download-artifact@v7 + uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4 with: name: generated-code path: . - name: Setup Node.js - uses: actions/setup-node@v4 + uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v6.3.0 with: node-version: ${{ env.NODE_VERSION }} - name: Setup Go - uses: actions/setup-go@v5 + uses: actions/setup-go@4b73464bb391d4059bd26b0524d20df3927bd417 # v6.3.0 with: go-version: ${{ env.GO_VERSION }} @@ -439,7 +448,7 @@ jobs: tar -czf ../third-party-licenses.tar.gz * - name: Upload licenses artifact - uses: actions/upload-artifact@v6 + uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4 with: name: third-party-licenses path: third-party-licenses.tar.gz @@ -455,12 +464,12 @@ jobs: needs: [determine-release-type] steps: - name: Checkout code - uses: actions/checkout@v6 + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: fetch-depth: 0 - name: Setup Go - uses: actions/setup-go@v5 + uses: actions/setup-go@4b73464bb391d4059bd26b0524d20df3927bd417 # v6.3.0 with: go-version: ${{ env.GO_VERSION }} @@ -472,7 +481,7 @@ jobs: make changelog CHANGELOG_VERSION=$CHANGELOG_VERSION - name: Upload changelog - uses: actions/upload-artifact@v6 + uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4 with: name: changelog path: ocis/dist/CHANGELOG.md @@ -492,32 +501,32 @@ jobs: - generate-changelog steps: - name: Download Linux binaries - uses: actions/download-artifact@v7 + uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4 with: name: binaries-linux path: release-assets - name: Download Darwin binaries - uses: actions/download-artifact@v7 + uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4 with: name: binaries-darwin path: release-assets - name: Download licenses - uses: actions/download-artifact@v7 + uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4 with: name: third-party-licenses path: release-assets - name: Download changelog - uses: actions/download-artifact@v7 + uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4 with: name: changelog path: . - name: Create GitHub Release if: ${{ needs.determine-release-type.outputs.dry_run != 'true' }} - uses: softprops/action-gh-release@v2.4.2 + uses: softprops/action-gh-release@153bb8e04406b158c6c84fc1615b65b24149a1fe # v2.6.1 with: name: ${{ needs.determine-release-type.outputs.version }} body_path: CHANGELOG.md @@ -537,7 +546,6 @@ jobs: printf " %-60s %s bytes sha256:%s\n" "$(basename $f)" "$size" "$hash" done - # ============================================================================ # NOTIFICATION # ============================================================================ @@ -549,6 +557,7 @@ jobs: needs: - determine-release-type - docker-build + - docker-scan - docker-manifest - docker-readme - generate-code @@ -564,10 +573,10 @@ jobs: - name: Decide whether the needed jobs succeeded or failed id: check-state continue-on-error: true - uses: re-actors/alls-green@release/v1 + uses: re-actors/alls-green@05ac9388f0aebcb5727afa17fcccfecd6f8ec5fe # v1.2.2 with: - # docker-build/manifest/readme are skipped on dry-run — treat skip as success - allowed-skips: docker-build, docker-manifest, docker-readme + # docker jobs are skipped on dry-run — treat skip as success + allowed-skips: docker-build, docker-scan, docker-manifest, docker-readme jobs: ${{ toJSON(needs) }} - name: Set failure message @@ -591,7 +600,7 @@ jobs: - name: Send message to Matrix room id: matrix-chat-message - uses: fadenb/matrix-chat-message@v0.0.6 + uses: fadenb/matrix-chat-message@89baab2b9ea06ffdd5f5b1ca80e9f888c3d7c9d3 # v0.0.6 with: homeserver: ${{ secrets.MATRIX_HOMESERVER }} token: ${{ secrets.MATRIX_TOKEN }} From aa285e276e18b8797d3df5f6d7bd76361ac2f563 Mon Sep 17 00:00:00 2001 From: Michal Klos Date: Wed, 8 Apr 2026 15:28:51 +0200 Subject: [PATCH 05/25] feat: [OCISDEV-783] release pipeline, DeepDiver's review comments --- .github/workflows/release.yml | 554 ++++++++++------------------------ 1 file changed, 153 insertions(+), 401 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index d33ea97a812..3180d05d69f 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -9,167 +9,97 @@ on: workflow_dispatch: inputs: dry_run: - description: 'Dry run — build everything but skip Docker push and GitHub Release creation' + description: 'Skip Docker push and GitHub Release creation' type: boolean default: true version_override: - description: 'Version to use for dry-run (e.g. 8.0.2-dryrun). Leave empty to auto-detect from latest tag.' + description: 'Version override (leave empty to auto-detect from latest tag)' type: string default: '' env: - # Production release tags (semver patterns) PRODUCTION_RELEASE_TAGS: '5.0,7,8' - - # Docker configuration DOCKER_REPO_ROLLING: owncloud/ocis-rolling DOCKER_REPO_PRODUCTION: owncloud/ocis - - # Build configuration GO_VERSION: '1.25.7' NODE_VERSION: '24' - PHP_VERSION: '8.4' PNPM_VERSION: '10.11.0' jobs: - # ============================================================================ - # PREPARATION JOBS - # ============================================================================ - determine-release-type: - name: Determine Release Type runs-on: ubuntu-latest outputs: - version: ${{ steps.version.outputs.version }} - is_production: ${{ steps.check.outputs.is_production }} - is_prerelease: ${{ steps.check.outputs.is_prerelease }} - release_folder: ${{ steps.check.outputs.release_folder }} - docker_repos: ${{ steps.check.outputs.docker_repos }} - dry_run: ${{ steps.version.outputs.dry_run }} + version: ${{ steps.info.outputs.version }} + is_production: ${{ steps.info.outputs.is_production }} + is_prerelease: ${{ steps.info.outputs.is_prerelease }} + docker_repos: ${{ steps.info.outputs.docker_repos }} + dry_run: ${{ steps.info.outputs.dry_run }} steps: - - name: Checkout code - if: ${{ (github.event_name == 'workflow_dispatch' && inputs.dry_run && inputs.version_override == '') || github.ref_type == 'branch' }} - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + if: ${{ github.ref_type == 'branch' || (github.event_name == 'workflow_dispatch' && inputs.version_override == '') }} with: fetch-depth: 0 - - name: Extract version - id: version + - id: info run: | + next_patch() { + local tag=$(git describe --tags --abbrev=0 2>/dev/null || echo "v0.0.0") + local ver="${tag#v}"; IFS='.' read -r M m p <<< "${ver%%-*}" + echo "${M}.${m}.$((p + 1))-dryrun" + } + if [[ "${{ github.event_name }}" == "workflow_dispatch" ]]; then DRY_RUN="${{ inputs.dry_run }}" - if [[ -n "${{ inputs.version_override }}" ]]; then - VERSION="${{ inputs.version_override }}" - else - # Auto-detect: bump patch of latest tag and append -dryrun - LATEST_TAG=$(git describe --tags --abbrev=0 2>/dev/null || echo "v0.0.0") - LATEST_VERSION="${LATEST_TAG#v}" - IFS='.' read -r MAJOR MINOR PATCH <<< "${LATEST_VERSION%%-*}" - VERSION="${MAJOR}.${MINOR}.$((PATCH + 1))-dryrun" - fi + VERSION="${{ inputs.version_override }}" + [[ -z "$VERSION" ]] && VERSION=$(next_patch) elif [[ "${{ github.ref_type }}" == "branch" ]]; then - # Branch push (e.g. feat/release-pipeline**) — always a dry-run DRY_RUN=true - LATEST_TAG=$(git describe --tags --abbrev=0 2>/dev/null || echo "v0.0.0") - LATEST_VERSION="${LATEST_TAG#v}" - IFS='.' read -r MAJOR MINOR PATCH <<< "${LATEST_VERSION%%-*}" - VERSION="${MAJOR}.${MINOR}.$((PATCH + 1))-dryrun" + VERSION=$(next_patch) else - VERSION=${GITHUB_REF#refs/tags/v} + VERSION="${GITHUB_REF#refs/tags/v}" DRY_RUN=false fi - echo "version=$VERSION" >> $GITHUB_OUTPUT - echo "dry_run=$DRY_RUN" >> $GITHUB_OUTPUT - echo "Version: $VERSION Dry-run: $DRY_RUN" - - name: Check release type - id: check - run: | - VERSION="${{ steps.version.outputs.version }}" - - # Check if production release IS_PRODUCTION=false for TAG in ${PRODUCTION_RELEASE_TAGS//,/ }; do - if [[ "$VERSION" == "$TAG"* ]]; then - IS_PRODUCTION=true - break - fi + [[ "$VERSION" == "$TAG"* ]] && IS_PRODUCTION=true && break done - echo "is_production=$IS_PRODUCTION" >> $GITHUB_OUTPUT - # Check if prerelease (contains -, like alpha/beta/rc) - IS_PRERELEASE=false - if [[ "$VERSION" == *"-"* ]]; then - IS_PRERELEASE=true - fi - echo "is_prerelease=$IS_PRERELEASE" >> $GITHUB_OUTPUT - - # Determine release folder - if [[ "$IS_PRERELEASE" == "true" ]]; then - FOLDER="testing" - else - FOLDER="stable" - fi - echo "release_folder=$FOLDER" >> $GITHUB_OUTPUT + [[ "$VERSION" == *"-"* ]] && IS_PRERELEASE=true || IS_PRERELEASE=false - # Determine Docker repos if [[ "$IS_PRODUCTION" == "true" ]]; then REPOS=[\"$DOCKER_REPO_ROLLING\",\"$DOCKER_REPO_PRODUCTION\"] else REPOS=[\"$DOCKER_REPO_ROLLING\"] fi - echo "docker_repos=$REPOS" >> $GITHUB_OUTPUT - - echo "Release Type Summary:" - echo " Version: $VERSION" - echo " Production: $IS_PRODUCTION" - echo " Prerelease: $IS_PRERELEASE" - echo " Folder: $FOLDER" - echo " Docker Repos: $REPOS" - # ============================================================================ - # CODE GENERATION - # ============================================================================ + echo "version=$VERSION" >> $GITHUB_OUTPUT + echo "dry_run=$DRY_RUN" >> $GITHUB_OUTPUT + echo "is_production=$IS_PRODUCTION" >> $GITHUB_OUTPUT + echo "is_prerelease=$IS_PRERELEASE" >> $GITHUB_OUTPUT + echo "docker_repos=$REPOS" >> $GITHUB_OUTPUT generate-code: - name: Generate code runs-on: ubuntu-latest steps: - - name: Checkout code - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - - - name: Setup Go - uses: actions/setup-go@4b73464bb391d4059bd26b0524d20df3927bd417 # v6.3.0 + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + - uses: actions/setup-go@4b73464bb391d4059bd26b0524d20df3927bd417 # v6.3.0 with: go-version: ${{ env.GO_VERSION }} - - - name: Setup Node.js - uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v6.3.0 + - uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v6.3.0 with: node-version: ${{ env.NODE_VERSION }} - - - name: Install npm packages - run: npm install --silent -g yarn npx --force - - - name: Setup pnpm - uses: pnpm/action-setup@fc06bc1257f339d1d5d8b3a19a8cae5388b55320 # v4 + - run: npm install --silent -g yarn npx --force + - uses: pnpm/action-setup@fc06bc1257f339d1d5d8b3a19a8cae5388b55320 # v4 with: version: ${{ env.PNPM_VERSION }} - - - name: Generate Node.js code - run: | - pnpm config set store-dir ./.pnpm-store - make ci-node-generate + - run: pnpm config set store-dir ./.pnpm-store && make ci-node-generate env: CHROMEDRIVER_SKIP_DOWNLOAD: 'true' - - - name: Generate Go code - run: make ci-go-generate + - run: make ci-go-generate env: BUF_TOKEN: ${{ secrets.BUF_API_TOKEN }} - - - name: Upload generated code - uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4 + - uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4 with: name: generated-code path: | @@ -177,96 +107,61 @@ jobs: !.git retention-days: 1 - # ============================================================================ - # DOCKER BUILDS - # ============================================================================ - docker-build: - name: Build Docker Image (${{ matrix.arch }}-${{ matrix.repo }}) - runs-on: ${{ matrix.arch == 'amd64' && 'ubuntu-24.04' || matrix.arch == 'arm64' && 'ubuntu-24.04-arm' }} + name: docker-build (${{ matrix.arch }}, ${{ matrix.repo }}) + runs-on: ${{ matrix.arch == 'amd64' && 'ubuntu-24.04' || 'ubuntu-24.04-arm' }} if: ${{ needs.determine-release-type.outputs.dry_run != 'true' }} needs: [determine-release-type, generate-code] outputs: - digest-amd64-rolling: ${{ steps.write-digest.outputs.digest-amd64-rolling }} - digest-arm64-rolling: ${{ steps.write-digest.outputs.digest-arm64-rolling }} - digest-amd64: ${{ steps.write-digest.outputs.digest-amd64 }} - digest-arm64: ${{ steps.write-digest.outputs.digest-arm64 }} + digest-amd64-rolling: ${{ steps.build.outputs.digest-amd64-rolling }} + digest-arm64-rolling: ${{ steps.build.outputs.digest-arm64-rolling }} + digest-amd64: ${{ steps.build.outputs.digest-amd64 }} + digest-arm64: ${{ steps.build.outputs.digest-arm64 }} strategy: matrix: arch: [amd64, arm64] repo: ${{ fromJSON(needs.determine-release-type.outputs.docker_repos) }} steps: - - name: Checkout code - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - - - name: Download generated code - uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4 + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + - uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4 with: name: generated-code path: . - - - name: Set up Docker Buildx - uses: docker/setup-buildx-action@8d2750c68a42422c14e847fe6c8ac0403b4cbd6f # v3 - - - name: Login to DockerHub - uses: docker/login-action@c94ce9fb468520275223c153574b00df6fe4bcc9 # v3 - with: - username: ${{ secrets.DOCKER_USERNAME }} - password: ${{ secrets.DOCKER_PASSWORD }} - - - name: Setup Go - uses: actions/setup-go@4b73464bb391d4059bd26b0524d20df3927bd417 # v6.3.0 + - run: docker buildx create --use --name release-builder + - run: echo "${{ secrets.DOCKER_PASSWORD }}" | docker login -u "${{ secrets.DOCKER_USERNAME }}" --password-stdin + - uses: actions/setup-go@4b73464bb391d4059bd26b0524d20df3927bd417 # v6.3.0 with: go-version: ${{ env.GO_VERSION }} - - - name: Install additional packages - run: | - sudo apt update - sudo apt install -y libvips libvips-dev - - - name: Build binary - run: make -C ocis release-linux-docker-${{ matrix.arch }} + - run: sudo apt-get update -q && sudo apt-get install -qy libvips libvips-dev + - run: make -C ocis release-linux-docker-${{ matrix.arch }} env: CGO_ENABLED: 1 GOOS: linux ENABLE_VIPS: true - - - name: Extract metadata - id: meta - uses: docker/metadata-action@c299e40c65443455700f0fdfc63efafe5b349051 # v5 - with: - images: ${{ matrix.repo }} - tags: | - type=semver,pattern={{version}},suffix=-linux-${{ matrix.arch }} - type=semver,pattern={{major}}.{{minor}},suffix=-linux-${{ matrix.arch }} - type=semver,pattern={{major}},suffix=-linux-${{ matrix.arch }} - - - name: Build and push Docker image - id: build-and-push - uses: docker/build-push-action@10e90e3645eae34f1e60eeb005ba3a3d33f178e8 # v6 - with: - context: ocis - file: ocis/docker/Dockerfile.linux.${{ matrix.arch }} - platforms: linux/${{ matrix.arch }} - push: true - provenance: false - tags: ${{ steps.meta.outputs.tags }} - labels: ${{ steps.meta.outputs.labels }} - build-args: | - REVISION=${{ github.sha }} - VERSION=${{ needs.determine-release-type.outputs.version }} - - - name: Write Digest - id: write-digest + - id: build run: | - if [[ "${{ matrix.repo }}" == *"rolling"* ]]; then - echo "digest-${{ matrix.arch }}-rolling=${{ steps.build-and-push.outputs.digest }}" >> $GITHUB_OUTPUT - else - echo "digest-${{ matrix.arch }}=${{ steps.build-and-push.outputs.digest }}" >> $GITHUB_OUTPUT - fi + VERSION="${{ needs.determine-release-type.outputs.version }}" + REPO="${{ matrix.repo }}" + ARCH="${{ matrix.arch }}" + + docker buildx build \ + --platform "linux/${ARCH}" \ + --file "ocis/docker/Dockerfile.linux.${ARCH}" \ + --push --provenance=false \ + --build-arg "REVISION=${{ github.sha }}" \ + --build-arg "VERSION=${VERSION}" \ + -t "${REPO}:${VERSION}-linux-${ARCH}" \ + -t "${REPO}:$(echo "$VERSION" | cut -d. -f1-2)-linux-${ARCH}" \ + -t "${REPO}:$(echo "$VERSION" | cut -d. -f1)-linux-${ARCH}" \ + ocis + + DIGEST=$(docker buildx imagetools inspect "${REPO}:${VERSION}-linux-${ARCH}" --format '{{.Manifest.Digest}}') + [[ "${REPO}" == *"rolling"* ]] \ + && echo "digest-${ARCH}-rolling=${DIGEST}" >> $GITHUB_OUTPUT \ + || echo "digest-${ARCH}=${DIGEST}" >> $GITHUB_OUTPUT docker-scan: - name: Scan Docker Image (${{ matrix.arch }}-${{ matrix.repo }}) + name: docker-scan (${{ matrix.arch }}, ${{ matrix.repo }}) runs-on: ubuntu-latest if: ${{ needs.determine-release-type.outputs.dry_run != 'true' }} needs: [determine-release-type, docker-build] @@ -275,17 +170,13 @@ jobs: arch: [amd64] repo: ${{ fromJSON(needs.determine-release-type.outputs.docker_repos) }} steps: - - name: Run Trivy vulnerability scanner on Docker image - uses: aquasecurity/trivy-action@57a97c7e7821a5776cebc9bb87c984fa69cba8f1 # 0.35.0 - with: - image-ref: ${{ matrix.repo }}:${{ needs.determine-release-type.outputs.version }}-linux-${{ matrix.arch }} - scan-type: 'image' - format: 'table' - exit-code: '0' - severity: 'CRITICAL,HIGH' + - run: | + curl -sfL https://raw.githubusercontent.com/aquasecurity/trivy/main/contrib/install.sh | sh -s -- -b /usr/local/bin + trivy image --format table --exit-code 0 --severity CRITICAL,HIGH \ + "${{ matrix.repo }}:${{ needs.determine-release-type.outputs.version }}-linux-${{ matrix.arch }}" docker-manifest: - name: Create Docker Manifest (${{ matrix.repo }}) + name: docker-manifest (${{ matrix.repo }}) runs-on: ubuntu-latest if: ${{ needs.determine-release-type.outputs.dry_run != 'true' }} needs: [determine-release-type, docker-build] @@ -293,32 +184,22 @@ jobs: matrix: repo: ${{ fromJSON(needs.determine-release-type.outputs.docker_repos) }} steps: - - name: Login to DockerHub - uses: docker/login-action@c94ce9fb468520275223c153574b00df6fe4bcc9 # v3 - with: - username: ${{ secrets.DOCKER_USERNAME }} - password: ${{ secrets.DOCKER_PASSWORD }} - - - name: Create and push multiarch manifest (rolling) - uses: int128/docker-manifest-create-action@44422a4b046d55dc036df622039ed3aec43c613c # v2.17.0 - if: ${{ contains(matrix.repo, 'rolling') }} - with: - tags: ${{ matrix.repo }}:${{ needs.determine-release-type.outputs.version }} - sources: | - ${{ needs.docker-build.outputs.digest-amd64-rolling }} - ${{ needs.docker-build.outputs.digest-arm64-rolling }} - - - name: Create and push multiarch manifest - uses: int128/docker-manifest-create-action@44422a4b046d55dc036df622039ed3aec43c613c # v2.17.0 - if: ${{ ! contains(matrix.repo, 'rolling') }} - with: - tags: ${{ matrix.repo }}:${{ needs.determine-release-type.outputs.version }} - sources: | - ${{ needs.docker-build.outputs.digest-amd64 }} - ${{ needs.docker-build.outputs.digest-arm64 }} + - run: echo "${{ secrets.DOCKER_PASSWORD }}" | docker login -u "${{ secrets.DOCKER_USERNAME }}" --password-stdin + - if: ${{ contains(matrix.repo, 'rolling') }} + run: | + docker buildx imagetools create \ + -t "${{ matrix.repo }}:${{ needs.determine-release-type.outputs.version }}" \ + "${{ needs.docker-build.outputs.digest-amd64-rolling }}" \ + "${{ needs.docker-build.outputs.digest-arm64-rolling }}" + - if: ${{ !contains(matrix.repo, 'rolling') }} + run: | + docker buildx imagetools create \ + -t "${{ matrix.repo }}:${{ needs.determine-release-type.outputs.version }}" \ + "${{ needs.docker-build.outputs.digest-amd64 }}" \ + "${{ needs.docker-build.outputs.digest-arm64 }}" docker-readme: - name: Update Docker README + name: docker-readme (${{ matrix.repo }}) runs-on: ubuntu-latest if: ${{ needs.determine-release-type.outputs.dry_run != 'true' }} needs: [determine-release-type, docker-manifest] @@ -326,284 +207,155 @@ jobs: matrix: repo: ${{ fromJSON(needs.determine-release-type.outputs.docker_repos) }} steps: - - name: Checkout code - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - - - name: Update DockerHub README - uses: peter-evans/dockerhub-description@dc67fad7001ef9e8e3c124cb7a64e16d0a63d864 # v3 - with: - username: ${{ secrets.DOCKER_USERNAME }} - password: ${{ secrets.DOCKER_PASSWORD }} - repository: ${{ matrix.repo }} - short-description: Docker images for ownCloud Infinite Scale - - # ============================================================================ - # BINARY BUILDS - # ============================================================================ + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + - run: | + README=$(python3 -c "import sys,json; print(json.dumps(sys.stdin.read()))" < ocis/docker/README.md) + TOKEN=$(curl -sf -X POST -H 'Content-Type: application/json' \ + -d "{\"username\":\"${{ secrets.DOCKER_USERNAME }}\",\"password\":\"${{ secrets.DOCKER_PASSWORD }}\"}" \ + https://hub.docker.com/v2/users/login | python3 -c 'import sys,json; print(json.load(sys.stdin)["token"])') + curl -sf -X PATCH \ + -H "Authorization: JWT ${TOKEN}" -H "Content-Type: application/json" \ + -d "{\"full_description\": ${README}}" \ + "https://hub.docker.com/v2/repositories/${{ matrix.repo }}/" build-binaries: - name: Build Binaries (${{ matrix.os }}) + name: build-binaries (${{ matrix.os }}) runs-on: ubuntu-latest needs: [determine-release-type, generate-code] strategy: matrix: os: [linux, darwin] steps: - - name: Checkout code - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - - - name: Download generated code - uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4 + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + - uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4 with: name: generated-code path: . - - - name: Setup Go - uses: actions/setup-go@4b73464bb391d4059bd26b0524d20df3927bd417 # v6.3.0 + - uses: actions/setup-go@4b73464bb391d4059bd26b0524d20df3927bd417 # v6.3.0 with: go-version: ${{ env.GO_VERSION }} - - - name: Build binaries - run: make -C ocis release-${{ matrix.os }} - - - name: Finish build - run: | + - run: | + make -C ocis release-${{ matrix.os }} make -C ocis release-finish - if [ "${{ matrix.os }}" == "linux" ]; then + [[ "${{ matrix.os }}" == "linux" ]] && \ cp assets/End-User-License-Agreement-for-ownCloud-Infinite-Scale.pdf ocis/dist/release/ - fi - - - name: Upload binaries - uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4 + - uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4 with: name: binaries-${{ matrix.os }} path: ocis/dist/release/* retention-days: 1 - # ============================================================================ - # SECURITY SCAN - # ============================================================================ - security-scan-trivy: - name: Trivy Filesystem Scan runs-on: ubuntu-latest steps: - - name: Checkout code - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - - - name: Run Trivy vulnerability scanner - uses: aquasecurity/trivy-action@57a97c7e7821a5776cebc9bb87c984fa69cba8f1 # 0.35.0 - with: - scan-type: 'fs' - format: 'table' - exit-code: '0' - severity: 'CRITICAL,HIGH' - - # ============================================================================ - # LICENSE CHECK - # ============================================================================ + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + - run: | + curl -sfL https://raw.githubusercontent.com/aquasecurity/trivy/main/contrib/install.sh | sh -s -- -b /usr/local/bin + trivy fs --format table --exit-code 0 --severity CRITICAL,HIGH . license-check: - name: Check and Upload Licenses runs-on: ubuntu-latest needs: [determine-release-type, generate-code] steps: - - name: Checkout code - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - - - name: Download generated code - uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4 + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + - uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4 with: name: generated-code path: . - - - name: Setup Node.js - uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v6.3.0 + - uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v6.3.0 with: node-version: ${{ env.NODE_VERSION }} - - - name: Setup Go - uses: actions/setup-go@4b73464bb391d4059bd26b0524d20df3927bd417 # v6.3.0 + - uses: actions/setup-go@4b73464bb391d4059bd26b0524d20df3927bd417 # v6.3.0 with: go-version: ${{ env.GO_VERSION }} - - - name: Install pnpm - run: npm install --silent -g yarn npx "pnpm@$PNPM_VERSION" --force - - - name: Check Node.js licenses - run: make ci-node-check-licenses - - - name: Save Node.js licenses - run: make ci-node-save-licenses - - - name: Check Go licenses - run: make ci-go-check-licenses - - - name: Save Go licenses - run: make ci-go-save-licenses - - - name: Create tarball - run: | - cd third-party-licenses - tar -czf ../third-party-licenses.tar.gz * - - - name: Upload licenses artifact - uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4 + - run: npm install --silent -g yarn npx "pnpm@$PNPM_VERSION" --force + - run: make ci-node-check-licenses && make ci-node-save-licenses + - run: make ci-go-check-licenses && make ci-go-save-licenses + - run: tar -czf third-party-licenses.tar.gz -C third-party-licenses . + - uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4 with: name: third-party-licenses path: third-party-licenses.tar.gz retention-days: 1 - # ============================================================================ - # CHANGELOG GENERATION - # ============================================================================ - generate-changelog: - name: Generate Changelog runs-on: ubuntu-latest needs: [determine-release-type] steps: - - name: Checkout code - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: fetch-depth: 0 - - - name: Setup Go - uses: actions/setup-go@4b73464bb391d4059bd26b0524d20df3927bd417 # v6.3.0 + - uses: actions/setup-go@4b73464bb391d4059bd26b0524d20df3927bd417 # v6.3.0 with: go-version: ${{ env.GO_VERSION }} - - - name: Generate changelog - run: | - VERSION="${{ needs.determine-release-type.outputs.version }}" - # Remove pre-release suffix for changelog - CHANGELOG_VERSION=$(echo $VERSION | cut -d'-' -f1) - make changelog CHANGELOG_VERSION=$CHANGELOG_VERSION - - - name: Upload changelog - uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4 + - run: make changelog CHANGELOG_VERSION=$(echo "${{ needs.determine-release-type.outputs.version }}" | cut -d'-' -f1) + - uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4 with: name: changelog path: ocis/dist/CHANGELOG.md retention-days: 1 - # ============================================================================ - # GITHUB RELEASE - # ============================================================================ - create-github-release: - name: Create GitHub Release runs-on: ubuntu-latest - needs: - - determine-release-type - - build-binaries - - license-check - - generate-changelog + needs: [determine-release-type, build-binaries, license-check, generate-changelog] steps: - - name: Download Linux binaries - uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4 + - uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4 with: name: binaries-linux path: release-assets - - - name: Download Darwin binaries - uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4 + - uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4 with: name: binaries-darwin path: release-assets - - - name: Download licenses - uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4 + - uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4 with: name: third-party-licenses path: release-assets - - - name: Download changelog - uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4 + - uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4 with: name: changelog path: . - - - name: Create GitHub Release - if: ${{ needs.determine-release-type.outputs.dry_run != 'true' }} - uses: softprops/action-gh-release@153bb8e04406b158c6c84fc1615b65b24149a1fe # v2.6.1 - with: - name: ${{ needs.determine-release-type.outputs.version }} - body_path: CHANGELOG.md - files: release-assets/* - prerelease: ${{ needs.determine-release-type.outputs.is_prerelease == 'true' }} - draft: false + - if: ${{ needs.determine-release-type.outputs.dry_run != 'true' }} + run: | + [[ "${{ needs.determine-release-type.outputs.is_prerelease }}" == "true" ]] && PRERELEASE=--prerelease + gh release create "${{ needs.determine-release-type.outputs.version }}" \ + --title "${{ needs.determine-release-type.outputs.version }}" \ + --notes-file CHANGELOG.md \ + ${PRERELEASE:-} release-assets/* env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - - - name: Dry-run summary - if: ${{ needs.determine-release-type.outputs.dry_run == 'true' }} + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + - if: ${{ needs.determine-release-type.outputs.dry_run == 'true' }} run: | - echo "## DRY RUN — artifacts that would be uploaded to a GitHub Release:" find release-assets/ -type f | sort | while read f; do - size=$(stat -c%s "$f") - hash=$(sha256sum "$f" | awk '{print $1}') - printf " %-60s %s bytes sha256:%s\n" "$(basename $f)" "$size" "$hash" + printf " %-60s %s sha256:%s\n" "$(basename $f)" "$(stat -c%s $f) bytes" "$(sha256sum $f | awk '{print $1}')" done - # ============================================================================ - # NOTIFICATION - # ============================================================================ - notify: - name: Notify Matrix room runs-on: ubuntu-latest if: always() needs: - determine-release-type + - generate-code - docker-build - docker-scan - docker-manifest - docker-readme - - generate-code - build-binaries + - security-scan-trivy - license-check - generate-changelog - create-github-release - - security-scan-trivy steps: - - name: Set short git commit SHA - run: echo "SHORT_SHA=`echo ${{ github.sha }} | cut -c1-8`" >> $GITHUB_ENV - - - name: Decide whether the needed jobs succeeded or failed - id: check-state - continue-on-error: true - uses: re-actors/alls-green@05ac9388f0aebcb5727afa17fcccfecd6f8ec5fe # v1.2.2 - with: - # docker jobs are skipped on dry-run — treat skip as success - allowed-skips: docker-build, docker-scan, docker-manifest, docker-readme - jobs: ${{ toJSON(needs) }} - - - name: Set failure message - if: ${{ steps.check-state.outcome != 'success' }} - run: echo 'BUILD_STATUS=❌️ Failure' >> $GITHUB_ENV - - - name: Set success message - if: ${{ steps.check-state.outcome == 'success' }} - run: echo 'BUILD_STATUS=✅ Success' >> $GITHUB_ENV - - - name: Set build source default - run: echo 'BUILD_SOURCE=${{ github.ref_name }}' >> $GITHUB_ENV - - - name: Set build source cron/schedule - if: github.event_name == 'schedule' - run: echo 'BUILD_SOURCE=nightly-${{ github.ref_name }}' >> $GITHUB_ENV - - - name: Set build source tag - if: github.ref_type == 'tag' - run: echo 'BUILD_SOURCE=tag ${{ github.ref_name }}' >> $GITHUB_ENV - - - name: Send message to Matrix room - id: matrix-chat-message - uses: fadenb/matrix-chat-message@89baab2b9ea06ffdd5f5b1ca80e9f888c3d7c9d3 # v0.0.6 - with: - homeserver: ${{ secrets.MATRIX_HOMESERVER }} - token: ${{ secrets.MATRIX_TOKEN }} - channel: ${{ secrets.MATRIX_ROOMID }} - message: | - **${{ env.BUILD_STATUS }}** [${{ github.repository }}#${{ env.SHORT_SHA }}](${{ github.server_url}}/${{ github.repository }}/actions/runs/${{ github.run_id }}) (${{ env.BUILD_SOURCE }}) by **${{ github.triggering_actor }}** + - run: | + [[ "${{ contains(needs.*.result, 'failure') }}" == "true" ]] \ + && STATUS="FAILURE" || STATUS="SUCCESS" + [[ "${{ github.event_name }}" == "schedule" ]] \ + && SOURCE="nightly-${{ github.ref_name }}" \ + || SOURCE="${{ github.ref_type == 'tag' && format('tag {0}', github.ref_name) || github.ref_name }}" + SHA="${{ github.sha }}" + MSG="${STATUS} [${{ github.repository }}#${SHA:0:8}](${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}) (${SOURCE}) by **${{ github.triggering_actor }}**" + curl -sf -X PUT \ + -H "Authorization: Bearer ${{ secrets.MATRIX_TOKEN }}" \ + -H "Content-Type: application/json" \ + -d "{\"msgtype\":\"m.text\",\"body\":\"${MSG}\"}" \ + "${{ secrets.MATRIX_HOMESERVER }}/_matrix/client/r0/rooms/${{ secrets.MATRIX_ROOMID }}/send/m.room.message/$(date +%s)" From da9e97e2c7e05e4c1dc4589519b8c92c62542681 Mon Sep 17 00:00:00 2001 From: Michal Klos Date: Wed, 8 Apr 2026 16:42:15 +0200 Subject: [PATCH 06/25] feat: [OCISDEV-783] release pipeline, assert release --- scripts/assert-release.py | 195 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 195 insertions(+) create mode 100755 scripts/assert-release.py diff --git a/scripts/assert-release.py b/scripts/assert-release.py new file mode 100755 index 00000000000..09c3b6a496e --- /dev/null +++ b/scripts/assert-release.py @@ -0,0 +1,195 @@ +#!/usr/bin/env python3 +import argparse +import hashlib +import json +import os +import struct +import subprocess +import sys +import urllib.error +import urllib.request +from pathlib import Path + +BINARY_PLATFORMS = ["darwin-amd64", "darwin-arm64", "linux-386", "linux-amd64", "linux-arm", "linux-arm64"] +MACHO_MAGIC = b"\xcf\xfa\xed\xfe" +ELF_MAGIC = b"\x7fELF" +BINARY_REF = { + "linux-amd64": (ELF_MAGIC, 64, 0x3e), + "linux-arm64": (ELF_MAGIC, 64, 0xb7), + "linux-arm": (ELF_MAGIC, 32, 0x28), + "linux-386": (ELF_MAGIC, 32, 0x03), + "darwin-amd64": (MACHO_MAGIC, 64, 0x01000007), + "darwin-arm64": (MACHO_MAGIC, 64, 0x0100000c), +} +EULA = "End-User-License-Agreement-for-ownCloud-Infinite-Scale.pdf" +LICENSES = "third-party-licenses.tar.gz" +PROD_TAGS = ("5.0", "7", "8") + +passed = failed = 0 + +def ok(msg): + global passed; passed += 1; print(f"[PASS] {msg}") + +def fail(msg): + global failed; failed += 1; print(f"[FAIL] {msg}", file=sys.stderr) + +def expected_files(v): + return [f for p in BINARY_PLATFORMS for f in (f"ocis-{v}-{p}", f"ocis-{v}-{p}.sha256")] + [EULA, LICENSES] + +def is_production(v): + return any(v.startswith(t) for t in PROD_TAGS) + +def run(cmd): + return subprocess.run(cmd, capture_output=True, text=True) + +def gh_api(path, token): + req = urllib.request.Request( + f"https://api.github.com{path}", + headers={"Authorization": f"Bearer {token}", "Accept": "application/vnd.github+json"}, + ) + with urllib.request.urlopen(req) as r: + return json.load(r) + + +def check_local(directory, version): + expected = expected_files(version) + present = {f.name for f in directory.iterdir()} + missing = [f for f in expected if f not in present] + extra = present - set(expected) + if missing: fail(f"file set: missing {missing}") + else: ok(f"file set: {len(expected)} files present") + if extra: fail(f"file set: unexpected {extra}") + + for platform in BINARY_PLATFORMS: + bin_path = directory / f"ocis-{version}-{platform}" + sha_path = directory / f"ocis-{version}-{platform}.sha256" + + if bin_path.exists(): + magic, bits, machine = BINARY_REF[platform] + if bin_path.stat().st_size == 0: + fail(f"{bin_path.name}: empty file") + else: + h = bin_path.read_bytes()[:20] + if not h.startswith(magic): + fail(f"{bin_path.name}: wrong magic {h[:4].hex()}") + elif magic == ELF_MAGIC: + cls, mach = h[4], struct.unpack_from(" Date: Wed, 8 Apr 2026 17:18:35 +0200 Subject: [PATCH 07/25] feat: [OCISDEV-783] release pipeline, audit release --- .github/workflows/release.yml | 27 ++++++++++ .../{assert-release.py => audit-release.py} | 49 +++++++++++++++++-- 2 files changed, 71 insertions(+), 5 deletions(-) rename scripts/{assert-release.py => audit-release.py} (78%) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 3180d05d69f..698c94f3a23 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -330,6 +330,32 @@ jobs: printf " %-60s %s sha256:%s\n" "$(basename $f)" "$(stat -c%s $f) bytes" "$(sha256sum $f | awk '{print $1}')" done + audit-release: + runs-on: ubuntu-latest + needs: [determine-release-type, create-github-release] + steps: + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + - uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4 + with: + name: binaries-linux + path: release-assets + - uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4 + with: + name: binaries-darwin + path: release-assets + - uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4 + with: + name: third-party-licenses + path: release-assets + - run: | + EXTRA="" + [[ "${{ needs.determine-release-type.outputs.dry_run }}" != "true" ]] && \ + EXTRA="--github-release --docker" + python3 scripts/audit-release.py \ + --version "${{ needs.determine-release-type.outputs.version }}" \ + --dir release-assets/ \ + $EXTRA + notify: runs-on: ubuntu-latest if: always() @@ -345,6 +371,7 @@ jobs: - license-check - generate-changelog - create-github-release + - audit-release steps: - run: | [[ "${{ contains(needs.*.result, 'failure') }}" == "true" ]] \ diff --git a/scripts/assert-release.py b/scripts/audit-release.py similarity index 78% rename from scripts/assert-release.py rename to scripts/audit-release.py index 09c3b6a496e..24a87afe838 100755 --- a/scripts/assert-release.py +++ b/scripts/audit-release.py @@ -159,6 +159,34 @@ def check_docker(version): else: ok(f"{ref}: amd64+arm64 present") +def resolve_run_id(branch, token): + r = gh_api(f"/repos/owncloud/ocis/actions/workflows/release.yml/runs?branch={branch}&per_page=1", token) + runs = r.get("workflow_runs", []) + if not runs: + sys.exit(f"no runs found for branch '{branch}'") + run = runs[0] + print(f"run {run['id']} {run['status']} {run['conclusion'] or 'in_progress'} {run['html_url']}") + return str(run["id"]) + + +def check_run_artifacts(run_id): + token = os.environ.get("GH_TOKEN") or os.environ.get("GITHUB_TOKEN") + if not token: + fail("GH_TOKEN / GITHUB_TOKEN not set"); return + try: + r = gh_api(f"/repos/owncloud/ocis/actions/runs/{run_id}/artifacts", token) + except urllib.error.HTTPError as e: + fail(f"run {run_id}: {e}"); return + + by_name = {a["name"]: a for a in r.get("artifacts", [])} + for name in ("binaries-linux", "binaries-darwin", "third-party-licenses"): + a = by_name.get(name) + if not a: fail(f"{name}: missing"); continue + if a.get("expired"): fail(f"{name}: expired"); continue + if a["size_in_bytes"] == 0: fail(f"{name}: empty"); continue + ok(f"{name}: {a['size_in_bytes']:,} bytes") + + def check_git(version): tag = f"v{version}" r = run(["git", "tag", "-v", tag]) @@ -175,17 +203,28 @@ def check_git(version): def main(): p = argparse.ArgumentParser() - p.add_argument("--version", required=True) + p.add_argument("--version", required=False) + p.add_argument("--run", metavar="RUN_ID") + p.add_argument("--branch", metavar="BRANCH") p.add_argument("--dir", type=Path) p.add_argument("--github-release", action="store_true") p.add_argument("--docker", action="store_true") p.add_argument("--git", action="store_true") args = p.parse_args() - if args.dir: check_local(args.dir, args.version) - if args.github_release: check_github_release(args.version) - if args.docker: check_docker(args.version) - if args.git: check_git(args.version) + if not args.run and not args.branch and not args.version: + p.error("--version is required unless --run or --branch is used") + + if args.branch: + token = os.environ.get("GH_TOKEN") or os.environ.get("GITHUB_TOKEN") + if not token: sys.exit("GH_TOKEN / GITHUB_TOKEN not set") + args.run = resolve_run_id(args.branch, token) + + if args.run: check_run_artifacts(args.run) + if args.dir: check_local(args.dir, args.version) + if args.github_release: check_github_release(args.version) + if args.docker: check_docker(args.version) + if args.git: check_git(args.version) print(f"\n{passed + failed} checks: {passed} passed, {failed} failed") sys.exit(1 if failed else 0) From d01f447a9582201fcba4c30f601ad480b74d5c18 Mon Sep 17 00:00:00 2001 From: Michal Klos Date: Wed, 8 Apr 2026 17:30:25 +0200 Subject: [PATCH 08/25] feat: [OCISDEV-783] release pipeline, bianaries --- .github/workflows/release.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 698c94f3a23..2a4288bc954 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -235,7 +235,7 @@ jobs: with: go-version: ${{ env.GO_VERSION }} - run: | - make -C ocis release-${{ matrix.os }} + make -C ocis release-${{ matrix.os }} OUTPUT=${{ needs.determine-release-type.outputs.version }} make -C ocis release-finish [[ "${{ matrix.os }}" == "linux" ]] && \ cp assets/End-User-License-Agreement-for-ownCloud-Infinite-Scale.pdf ocis/dist/release/ From f9b69d02b73ea16bc10897fefc6030dd45784f85 Mon Sep 17 00:00:00 2001 From: Michal Klos Date: Wed, 8 Apr 2026 18:16:10 +0200 Subject: [PATCH 09/25] feat: [OCISDEV-783] release pipeline, bianaries --- .github/workflows/release.yml | 3 ++- scripts/audit-release.py | 3 --- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 2a4288bc954..47d88e6ca12 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -237,8 +237,9 @@ jobs: - run: | make -C ocis release-${{ matrix.os }} OUTPUT=${{ needs.determine-release-type.outputs.version }} make -C ocis release-finish - [[ "${{ matrix.os }}" == "linux" ]] && \ + if [[ "${{ matrix.os }}" == "linux" ]]; then cp assets/End-User-License-Agreement-for-ownCloud-Infinite-Scale.pdf ocis/dist/release/ + fi - uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4 with: name: binaries-${{ matrix.os }} diff --git a/scripts/audit-release.py b/scripts/audit-release.py index 24a87afe838..7790ff820e5 100755 --- a/scripts/audit-release.py +++ b/scripts/audit-release.py @@ -89,9 +89,6 @@ def check_local(directory, version): if not bin_path.exists(): fail(f"{sha_path.name}: binary missing") continue - size = sha_path.stat().st_size - if not (87 <= size <= 90): - fail(f"{sha_path.name}: size {size} (want 87-90)") parts = sha_path.read_text().strip().split(" ", 1) if len(parts) != 2: fail(f"{sha_path.name}: bad format") From 72718f2e806cc8cfbf36a3346366b5844ba8183e Mon Sep 17 00:00:00 2001 From: Michal Klos Date: Thu, 9 Apr 2026 12:05:41 +0200 Subject: [PATCH 10/25] feat: [OCISDEV-783] release pipeline, dev.1 --- .github/workflows/release.yml | 40 ++++++++--------------------------- scripts/audit-release.py | 4 ++++ 2 files changed, 13 insertions(+), 31 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 47d88e6ca12..83301da92eb 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -8,10 +8,6 @@ on: - 'feat/release-pipeline**' workflow_dispatch: inputs: - dry_run: - description: 'Skip Docker push and GitHub Release creation' - type: boolean - default: true version_override: description: 'Version override (leave empty to auto-detect from latest tag)' type: string @@ -29,11 +25,10 @@ jobs: determine-release-type: runs-on: ubuntu-latest outputs: - version: ${{ steps.info.outputs.version }} + version: ${{ steps.info.outputs.version }} is_production: ${{ steps.info.outputs.is_production }} is_prerelease: ${{ steps.info.outputs.is_prerelease }} docker_repos: ${{ steps.info.outputs.docker_repos }} - dry_run: ${{ steps.info.outputs.dry_run }} steps: - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 if: ${{ github.ref_type == 'branch' || (github.event_name == 'workflow_dispatch' && inputs.version_override == '') }} @@ -42,22 +37,19 @@ jobs: - id: info run: | - next_patch() { + next_dev() { local tag=$(git describe --tags --abbrev=0 2>/dev/null || echo "v0.0.0") local ver="${tag#v}"; IFS='.' read -r M m p <<< "${ver%%-*}" - echo "${M}.${m}.$((p + 1))-dryrun" + echo "${M}.${m}.$((p + 1))-dev.1" } if [[ "${{ github.event_name }}" == "workflow_dispatch" ]]; then - DRY_RUN="${{ inputs.dry_run }}" VERSION="${{ inputs.version_override }}" - [[ -z "$VERSION" ]] && VERSION=$(next_patch) + [[ -z "$VERSION" ]] && VERSION=$(next_dev) elif [[ "${{ github.ref_type }}" == "branch" ]]; then - DRY_RUN=true - VERSION=$(next_patch) + VERSION=$(next_dev) else VERSION="${GITHUB_REF#refs/tags/v}" - DRY_RUN=false fi IS_PRODUCTION=false @@ -73,11 +65,10 @@ jobs: REPOS=[\"$DOCKER_REPO_ROLLING\"] fi - echo "version=$VERSION" >> $GITHUB_OUTPUT - echo "dry_run=$DRY_RUN" >> $GITHUB_OUTPUT + echo "version=$VERSION" >> $GITHUB_OUTPUT echo "is_production=$IS_PRODUCTION" >> $GITHUB_OUTPUT echo "is_prerelease=$IS_PRERELEASE" >> $GITHUB_OUTPUT - echo "docker_repos=$REPOS" >> $GITHUB_OUTPUT + echo "docker_repos=$REPOS" >> $GITHUB_OUTPUT generate-code: runs-on: ubuntu-latest @@ -110,7 +101,6 @@ jobs: docker-build: name: docker-build (${{ matrix.arch }}, ${{ matrix.repo }}) runs-on: ${{ matrix.arch == 'amd64' && 'ubuntu-24.04' || 'ubuntu-24.04-arm' }} - if: ${{ needs.determine-release-type.outputs.dry_run != 'true' }} needs: [determine-release-type, generate-code] outputs: digest-amd64-rolling: ${{ steps.build.outputs.digest-amd64-rolling }} @@ -163,7 +153,6 @@ jobs: docker-scan: name: docker-scan (${{ matrix.arch }}, ${{ matrix.repo }}) runs-on: ubuntu-latest - if: ${{ needs.determine-release-type.outputs.dry_run != 'true' }} needs: [determine-release-type, docker-build] strategy: matrix: @@ -178,7 +167,6 @@ jobs: docker-manifest: name: docker-manifest (${{ matrix.repo }}) runs-on: ubuntu-latest - if: ${{ needs.determine-release-type.outputs.dry_run != 'true' }} needs: [determine-release-type, docker-build] strategy: matrix: @@ -201,7 +189,6 @@ jobs: docker-readme: name: docker-readme (${{ matrix.repo }}) runs-on: ubuntu-latest - if: ${{ needs.determine-release-type.outputs.dry_run != 'true' }} needs: [determine-release-type, docker-manifest] strategy: matrix: @@ -316,8 +303,7 @@ jobs: with: name: changelog path: . - - if: ${{ needs.determine-release-type.outputs.dry_run != 'true' }} - run: | + - run: | [[ "${{ needs.determine-release-type.outputs.is_prerelease }}" == "true" ]] && PRERELEASE=--prerelease gh release create "${{ needs.determine-release-type.outputs.version }}" \ --title "${{ needs.determine-release-type.outputs.version }}" \ @@ -325,11 +311,6 @@ jobs: ${PRERELEASE:-} release-assets/* env: GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} - - if: ${{ needs.determine-release-type.outputs.dry_run == 'true' }} - run: | - find release-assets/ -type f | sort | while read f; do - printf " %-60s %s sha256:%s\n" "$(basename $f)" "$(stat -c%s $f) bytes" "$(sha256sum $f | awk '{print $1}')" - done audit-release: runs-on: ubuntu-latest @@ -349,13 +330,10 @@ jobs: name: third-party-licenses path: release-assets - run: | - EXTRA="" - [[ "${{ needs.determine-release-type.outputs.dry_run }}" != "true" ]] && \ - EXTRA="--github-release --docker" python3 scripts/audit-release.py \ --version "${{ needs.determine-release-type.outputs.version }}" \ --dir release-assets/ \ - $EXTRA + --github-release --docker notify: runs-on: ubuntu-latest diff --git a/scripts/audit-release.py b/scripts/audit-release.py index 7790ff820e5..a83f264da4e 100755 --- a/scripts/audit-release.py +++ b/scripts/audit-release.py @@ -217,6 +217,10 @@ def main(): if not token: sys.exit("GH_TOKEN / GITHUB_TOKEN not set") args.run = resolve_run_id(args.branch, token) + needs_version = args.dir or args.github_release or args.docker or args.git + if needs_version and not args.version: + p.error("--version is required with --dir / --github-release / --docker / --git") + if args.run: check_run_artifacts(args.run) if args.dir: check_local(args.dir, args.version) if args.github_release: check_github_release(args.version) From 8d96316e1911bc33a4e76facf6ead2d7cfec47ee Mon Sep 17 00:00:00 2001 From: Michal Klos Date: Thu, 9 Apr 2026 12:45:18 +0200 Subject: [PATCH 11/25] feat: [OCISDEV-783] release pipeline, dev.1 --- .github/workflows/release.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 83301da92eb..6c0546a9844 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -59,7 +59,7 @@ jobs: [[ "$VERSION" == *"-"* ]] && IS_PRERELEASE=true || IS_PRERELEASE=false - if [[ "$IS_PRODUCTION" == "true" ]]; then + if [[ "$IS_PRODUCTION" == "true" && "$IS_PRERELEASE" == "false" ]]; then REPOS=[\"$DOCKER_REPO_ROLLING\",\"$DOCKER_REPO_PRODUCTION\"] else REPOS=[\"$DOCKER_REPO_ROLLING\"] From ee1b2f9782d167178357b8cb0142542eb9cc5921 Mon Sep 17 00:00:00 2001 From: Michal Klos Date: Thu, 9 Apr 2026 14:14:46 +0200 Subject: [PATCH 12/25] feat: [OCISDEV-783] release pipeline, dev.1 --- .github/workflows/release.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 6c0546a9844..191eaa3df54 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -305,7 +305,7 @@ jobs: path: . - run: | [[ "${{ needs.determine-release-type.outputs.is_prerelease }}" == "true" ]] && PRERELEASE=--prerelease - gh release create "${{ needs.determine-release-type.outputs.version }}" \ + gh release create -R "${{ github.repository }}" "${{ needs.determine-release-type.outputs.version }}" \ --title "${{ needs.determine-release-type.outputs.version }}" \ --notes-file CHANGELOG.md \ ${PRERELEASE:-} release-assets/* From e79a61665fea689c90f7ad46a02d649640488473 Mon Sep 17 00:00:00 2001 From: Michal Klos Date: Thu, 9 Apr 2026 15:51:36 +0200 Subject: [PATCH 13/25] feat: [OCISDEV-783] release pipeline, dev.1 --- .github/workflows/release.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 191eaa3df54..9bc25f177e7 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -34,6 +34,7 @@ jobs: if: ${{ github.ref_type == 'branch' || (github.event_name == 'workflow_dispatch' && inputs.version_override == '') }} with: fetch-depth: 0 + fetch-tags: true - id: info run: | From 557b5a741481e648ac7d73b2f0d06aafb13c19ec Mon Sep 17 00:00:00 2001 From: Michal Klos Date: Thu, 9 Apr 2026 16:07:56 +0200 Subject: [PATCH 14/25] feat: [OCISDEV-783] release pipeline, dev.1 --- .github/workflows/release.yml | 106 ++++++++++++++++++---------------- 1 file changed, 56 insertions(+), 50 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 9bc25f177e7..92d693674e2 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -104,10 +104,10 @@ jobs: runs-on: ${{ matrix.arch == 'amd64' && 'ubuntu-24.04' || 'ubuntu-24.04-arm' }} needs: [determine-release-type, generate-code] outputs: - digest-amd64-rolling: ${{ steps.build.outputs.digest-amd64-rolling }} - digest-arm64-rolling: ${{ steps.build.outputs.digest-arm64-rolling }} - digest-amd64: ${{ steps.build.outputs.digest-amd64 }} - digest-arm64: ${{ steps.build.outputs.digest-arm64 }} + digest-amd64-rolling: ${{ steps.digest.outputs.digest-amd64-rolling }} + digest-arm64-rolling: ${{ steps.digest.outputs.digest-arm64-rolling }} + digest-amd64: ${{ steps.digest.outputs.digest-amd64 }} + digest-arm64: ${{ steps.digest.outputs.digest-arm64 }} strategy: matrix: arch: [amd64, arm64] @@ -118,8 +118,11 @@ jobs: with: name: generated-code path: . - - run: docker buildx create --use --name release-builder - - run: echo "${{ secrets.DOCKER_PASSWORD }}" | docker login -u "${{ secrets.DOCKER_USERNAME }}" --password-stdin + - uses: docker/setup-buildx-action@4d04d5d9486b7bd6fa91e7baf45bbb4f8b9deedd # v4.0.0 + - uses: docker/login-action@4907a6ddec9925e35a0a9e82d7399ccc52663121 # v4.1.0 + with: + username: ${{ vars.DOCKERHUB_USERNAME }} + password: ${{ secrets.DOCKERHUB_TOKEN }} - uses: actions/setup-go@4b73464bb391d4059bd26b0524d20df3927bd417 # v6.3.0 with: go-version: ${{ env.GO_VERSION }} @@ -130,26 +133,25 @@ jobs: GOOS: linux ENABLE_VIPS: true - id: build + uses: docker/build-push-action@d08e5c354a6adb9ed34480a06d141179aa583294 # v7.0.0 + with: + context: ocis + file: ocis/docker/Dockerfile.linux.${{ matrix.arch }} + platforms: linux/${{ matrix.arch }} + push: true + provenance: false + build-args: | + REVISION=${{ github.sha }} + VERSION=${{ needs.determine-release-type.outputs.version }} + tags: | + ${{ matrix.repo }}:${{ needs.determine-release-type.outputs.version }}-linux-${{ matrix.arch }} + ${{ matrix.repo }}:${{ join(slice(split(needs.determine-release-type.outputs.version, '.'), 0, 2), '.') }}-linux-${{ matrix.arch }} + ${{ matrix.repo }}:${{ split(needs.determine-release-type.outputs.version, '.')[0] }}-linux-${{ matrix.arch }} + - id: digest run: | - VERSION="${{ needs.determine-release-type.outputs.version }}" - REPO="${{ matrix.repo }}" - ARCH="${{ matrix.arch }}" - - docker buildx build \ - --platform "linux/${ARCH}" \ - --file "ocis/docker/Dockerfile.linux.${ARCH}" \ - --push --provenance=false \ - --build-arg "REVISION=${{ github.sha }}" \ - --build-arg "VERSION=${VERSION}" \ - -t "${REPO}:${VERSION}-linux-${ARCH}" \ - -t "${REPO}:$(echo "$VERSION" | cut -d. -f1-2)-linux-${ARCH}" \ - -t "${REPO}:$(echo "$VERSION" | cut -d. -f1)-linux-${ARCH}" \ - ocis - - DIGEST=$(docker buildx imagetools inspect "${REPO}:${VERSION}-linux-${ARCH}" --format '{{.Manifest.Digest}}') - [[ "${REPO}" == *"rolling"* ]] \ - && echo "digest-${ARCH}-rolling=${DIGEST}" >> $GITHUB_OUTPUT \ - || echo "digest-${ARCH}=${DIGEST}" >> $GITHUB_OUTPUT + [[ "${{ matrix.repo }}" == *"rolling"* ]] \ + && echo "digest-${{ matrix.arch }}-rolling=${{ steps.build.outputs.digest }}" >> $GITHUB_OUTPUT \ + || echo "digest-${{ matrix.arch }}=${{ steps.build.outputs.digest }}" >> $GITHUB_OUTPUT docker-scan: name: docker-scan (${{ matrix.arch }}, ${{ matrix.repo }}) @@ -160,10 +162,12 @@ jobs: arch: [amd64] repo: ${{ fromJSON(needs.determine-release-type.outputs.docker_repos) }} steps: - - run: | - curl -sfL https://raw.githubusercontent.com/aquasecurity/trivy/main/contrib/install.sh | sh -s -- -b /usr/local/bin - trivy image --format table --exit-code 0 --severity CRITICAL,HIGH \ - "${{ matrix.repo }}:${{ needs.determine-release-type.outputs.version }}-linux-${{ matrix.arch }}" + - uses: aquasecurity/trivy-action@57a97c7e7821a5776cebc9bb87c984fa69cba8f1 # v0.35.0 + with: + image-ref: ${{ matrix.repo }}:${{ needs.determine-release-type.outputs.version }}-linux-${{ matrix.arch }} + format: table + exit-code: 0 + severity: CRITICAL,HIGH docker-manifest: name: docker-manifest (${{ matrix.repo }}) @@ -173,7 +177,10 @@ jobs: matrix: repo: ${{ fromJSON(needs.determine-release-type.outputs.docker_repos) }} steps: - - run: echo "${{ secrets.DOCKER_PASSWORD }}" | docker login -u "${{ secrets.DOCKER_USERNAME }}" --password-stdin + - uses: docker/login-action@4907a6ddec9925e35a0a9e82d7399ccc52663121 # v4.1.0 + with: + username: ${{ vars.DOCKERHUB_USERNAME }} + password: ${{ secrets.DOCKERHUB_TOKEN }} - if: ${{ contains(matrix.repo, 'rolling') }} run: | docker buildx imagetools create \ @@ -196,15 +203,12 @@ jobs: repo: ${{ fromJSON(needs.determine-release-type.outputs.docker_repos) }} steps: - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - - run: | - README=$(python3 -c "import sys,json; print(json.dumps(sys.stdin.read()))" < ocis/docker/README.md) - TOKEN=$(curl -sf -X POST -H 'Content-Type: application/json' \ - -d "{\"username\":\"${{ secrets.DOCKER_USERNAME }}\",\"password\":\"${{ secrets.DOCKER_PASSWORD }}\"}" \ - https://hub.docker.com/v2/users/login | python3 -c 'import sys,json; print(json.load(sys.stdin)["token"])') - curl -sf -X PATCH \ - -H "Authorization: JWT ${TOKEN}" -H "Content-Type: application/json" \ - -d "{\"full_description\": ${README}}" \ - "https://hub.docker.com/v2/repositories/${{ matrix.repo }}/" + - uses: peter-evans/dockerhub-description@1b9a80c056b620d92cedb9d9b5a223409c68ddfa # v5.0.0 + with: + username: ${{ vars.DOCKERHUB_USERNAME }} + password: ${{ secrets.DOCKERHUB_TOKEN }} + repository: ${{ matrix.repo }} + readme-filepath: ocis/docker/README.md build-binaries: name: build-binaries (${{ matrix.os }}) @@ -238,9 +242,12 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - - run: | - curl -sfL https://raw.githubusercontent.com/aquasecurity/trivy/main/contrib/install.sh | sh -s -- -b /usr/local/bin - trivy fs --format table --exit-code 0 --severity CRITICAL,HIGH . + - uses: aquasecurity/trivy-action@57a97c7e7821a5776cebc9bb87c984fa69cba8f1 # v0.35.0 + with: + scan-type: fs + format: table + exit-code: 0 + severity: CRITICAL,HIGH license-check: runs-on: ubuntu-latest @@ -304,14 +311,13 @@ jobs: with: name: changelog path: . - - run: | - [[ "${{ needs.determine-release-type.outputs.is_prerelease }}" == "true" ]] && PRERELEASE=--prerelease - gh release create -R "${{ github.repository }}" "${{ needs.determine-release-type.outputs.version }}" \ - --title "${{ needs.determine-release-type.outputs.version }}" \ - --notes-file CHANGELOG.md \ - ${PRERELEASE:-} release-assets/* - env: - GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + - uses: softprops/action-gh-release@153bb8e04406b158c6c84fc1615b65b24149a1fe # v2.6.1 + with: + tag_name: ${{ needs.determine-release-type.outputs.version }} + name: ${{ needs.determine-release-type.outputs.version }} + body_path: CHANGELOG.md + prerelease: ${{ needs.determine-release-type.outputs.is_prerelease == 'true' }} + files: release-assets/* audit-release: runs-on: ubuntu-latest From 2e429ad87933c436f3f77a01a8d887d230ba3a04 Mon Sep 17 00:00:00 2001 From: Michal Klos Date: Thu, 9 Apr 2026 16:14:48 +0200 Subject: [PATCH 15/25] feat: [OCISDEV-783] release pipeline, dev.1 --- .github/workflows/release.yml | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 92d693674e2..517b4ed944f 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -132,6 +132,17 @@ jobs: CGO_ENABLED: 1 GOOS: linux ENABLE_VIPS: true + - id: tags + run: | + VERSION="${{ needs.determine-release-type.outputs.version }}" + REPO="${{ matrix.repo }}" + ARCH="${{ matrix.arch }}" + MAJOR_MINOR=$(echo "$VERSION" | cut -d. -f1-2) + MAJOR=$(echo "$VERSION" | cut -d. -f1) + printf "tags<> $GITHUB_OUTPUT - id: build uses: docker/build-push-action@d08e5c354a6adb9ed34480a06d141179aa583294 # v7.0.0 with: @@ -143,10 +154,7 @@ jobs: build-args: | REVISION=${{ github.sha }} VERSION=${{ needs.determine-release-type.outputs.version }} - tags: | - ${{ matrix.repo }}:${{ needs.determine-release-type.outputs.version }}-linux-${{ matrix.arch }} - ${{ matrix.repo }}:${{ join(slice(split(needs.determine-release-type.outputs.version, '.'), 0, 2), '.') }}-linux-${{ matrix.arch }} - ${{ matrix.repo }}:${{ split(needs.determine-release-type.outputs.version, '.')[0] }}-linux-${{ matrix.arch }} + tags: ${{ steps.tags.outputs.tags }} - id: digest run: | [[ "${{ matrix.repo }}" == *"rolling"* ]] \ From 6b58891e0b8733fa4a198b4b1fb5b59bfba27829 Mon Sep 17 00:00:00 2001 From: Michal Klos Date: Thu, 9 Apr 2026 20:30:13 +0200 Subject: [PATCH 16/25] feat: [OCISDEV-783] release pipeline, dev.1 --- .github/workflows/release.yml | 85 +++++++++++++++++++---------------- 1 file changed, 47 insertions(+), 38 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 517b4ed944f..5fe243471fe 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -118,11 +118,8 @@ jobs: with: name: generated-code path: . - - uses: docker/setup-buildx-action@4d04d5d9486b7bd6fa91e7baf45bbb4f8b9deedd # v4.0.0 - - uses: docker/login-action@4907a6ddec9925e35a0a9e82d7399ccc52663121 # v4.1.0 - with: - username: ${{ vars.DOCKERHUB_USERNAME }} - password: ${{ secrets.DOCKERHUB_TOKEN }} + - run: docker buildx create --use # replaces docker/setup-buildx-action — not on org allowlist + - run: echo "${{ secrets.DOCKERHUB_TOKEN }}" | docker login -u "${{ vars.DOCKERHUB_USERNAME }}" --password-stdin # replaces docker/login-action — not on org allowlist - uses: actions/setup-go@4b73464bb391d4059bd26b0524d20df3927bd417 # v6.3.0 with: go-version: ${{ env.GO_VERSION }} @@ -144,17 +141,23 @@ jobs: "${REPO}:${MAJOR_MINOR}-linux-${ARCH}" \ "${REPO}:${MAJOR}-linux-${ARCH}" >> $GITHUB_OUTPUT - id: build - uses: docker/build-push-action@d08e5c354a6adb9ed34480a06d141179aa583294 # v7.0.0 - with: - context: ocis - file: ocis/docker/Dockerfile.linux.${{ matrix.arch }} - platforms: linux/${{ matrix.arch }} - push: true - provenance: false - build-args: | - REVISION=${{ github.sha }} - VERSION=${{ needs.determine-release-type.outputs.version }} - tags: ${{ steps.tags.outputs.tags }} + # replaces docker/build-push-action — not on org allowlist; digest extracted via --metadata-file + run: | + TAGS="" + while IFS= read -r tag; do + [[ -n "$tag" ]] && TAGS="$TAGS --tag $tag" + done <<< "${{ steps.tags.outputs.tags }}" + docker buildx build \ + --platform linux/${{ matrix.arch }} \ + --push \ + --provenance=false \ + --build-arg REVISION=${{ github.sha }} \ + --build-arg VERSION=${{ needs.determine-release-type.outputs.version }} \ + --file ocis/docker/Dockerfile.linux.${{ matrix.arch }} \ + --metadata-file /tmp/build-metadata.json \ + $TAGS \ + ocis + echo "digest=$(jq -r '."containerimage.digest"' /tmp/build-metadata.json)" >> $GITHUB_OUTPUT - id: digest run: | [[ "${{ matrix.repo }}" == *"rolling"* ]] \ @@ -170,12 +173,14 @@ jobs: arch: [amd64] repo: ${{ fromJSON(needs.determine-release-type.outputs.docker_repos) }} steps: - - uses: aquasecurity/trivy-action@57a97c7e7821a5776cebc9bb87c984fa69cba8f1 # v0.35.0 - with: - image-ref: ${{ matrix.repo }}:${{ needs.determine-release-type.outputs.version }}-linux-${{ matrix.arch }} - format: table - exit-code: 0 - severity: CRITICAL,HIGH + - # replaces aquasecurity/trivy-action — not on org allowlist + run: | + curl -sfL https://raw.githubusercontent.com/aquasecurity/trivy/main/contrib/install.sh | sh -s -- -b /usr/local/bin + trivy image \ + --format table \ + --exit-code 0 \ + --severity CRITICAL,HIGH \ + "${{ matrix.repo }}:${{ needs.determine-release-type.outputs.version }}-linux-${{ matrix.arch }}" docker-manifest: name: docker-manifest (${{ matrix.repo }}) @@ -185,10 +190,7 @@ jobs: matrix: repo: ${{ fromJSON(needs.determine-release-type.outputs.docker_repos) }} steps: - - uses: docker/login-action@4907a6ddec9925e35a0a9e82d7399ccc52663121 # v4.1.0 - with: - username: ${{ vars.DOCKERHUB_USERNAME }} - password: ${{ secrets.DOCKERHUB_TOKEN }} + - run: echo "${{ secrets.DOCKERHUB_TOKEN }}" | docker login -u "${{ vars.DOCKERHUB_USERNAME }}" --password-stdin # replaces docker/login-action — not on org allowlist - if: ${{ contains(matrix.repo, 'rolling') }} run: | docker buildx imagetools create \ @@ -211,12 +213,17 @@ jobs: repo: ${{ fromJSON(needs.determine-release-type.outputs.docker_repos) }} steps: - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - - uses: peter-evans/dockerhub-description@1b9a80c056b620d92cedb9d9b5a223409c68ddfa # v5.0.0 - with: - username: ${{ vars.DOCKERHUB_USERNAME }} - password: ${{ secrets.DOCKERHUB_TOKEN }} - repository: ${{ matrix.repo }} - readme-filepath: ocis/docker/README.md + - # replaces peter-evans/dockerhub-description — not on org allowlist; uses DockerHub API v2 directly + run: | + TOKEN=$(curl -sf -X POST \ + -H "Content-Type: application/json" \ + -d "{\"username\":\"${{ vars.DOCKERHUB_USERNAME }}\",\"password\":\"${{ secrets.DOCKERHUB_TOKEN }}\"}" \ + "https://hub.docker.com/v2/users/login" | jq -r '.token') + curl -sf -X PATCH \ + -H "Authorization: Bearer $TOKEN" \ + -H "Content-Type: application/json" \ + --data-binary "{\"full_description\":$(python3 -c 'import json,sys; print(json.dumps(open("ocis/docker/README.md").read()))')}" \ + "https://hub.docker.com/v2/repositories/${{ matrix.repo }}/" build-binaries: name: build-binaries (${{ matrix.os }}) @@ -250,12 +257,14 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - - uses: aquasecurity/trivy-action@57a97c7e7821a5776cebc9bb87c984fa69cba8f1 # v0.35.0 - with: - scan-type: fs - format: table - exit-code: 0 - severity: CRITICAL,HIGH + - # replaces aquasecurity/trivy-action — not on org allowlist + run: | + curl -sfL https://raw.githubusercontent.com/aquasecurity/trivy/main/contrib/install.sh | sh -s -- -b /usr/local/bin + trivy fs \ + --format table \ + --exit-code 0 \ + --severity CRITICAL,HIGH \ + . license-check: runs-on: ubuntu-latest From ee4eac969c7abbeba0a566d4c5c40ea6690abc85 Mon Sep 17 00:00:00 2001 From: Michal Klos Date: Thu, 9 Apr 2026 22:23:41 +0200 Subject: [PATCH 17/25] feat: [OCISDEV-783] release pipeline, dev.1 --- .github/workflows/release.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 5fe243471fe..d1ceba64a76 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -39,7 +39,7 @@ jobs: - id: info run: | next_dev() { - local tag=$(git describe --tags --abbrev=0 2>/dev/null || echo "v0.0.0") + local tag=$(git tag --sort=-version:refname | grep -m1 '^v' || echo "v0.0.0") local ver="${tag#v}"; IFS='.' read -r M m p <<< "${ver%%-*}" echo "${M}.${m}.$((p + 1))-dev.1" } From 371a7fb44106c410dc5ca9f44daa3072362eba68 Mon Sep 17 00:00:00 2001 From: Michal Klos Date: Thu, 9 Apr 2026 23:06:22 +0200 Subject: [PATCH 18/25] feat: [OCISDEV-783] release pipeline, dev.1 --- .github/workflows/release.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index d1ceba64a76..39279602d07 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -222,7 +222,7 @@ jobs: curl -sf -X PATCH \ -H "Authorization: Bearer $TOKEN" \ -H "Content-Type: application/json" \ - --data-binary "{\"full_description\":$(python3 -c 'import json,sys; print(json.dumps(open("ocis/docker/README.md").read()))')}" \ + --data-binary "{\"full_description\":$(python3 -c 'import json,sys; print(json.dumps(open("ocis/README.md").read()))')}" \ "https://hub.docker.com/v2/repositories/${{ matrix.repo }}/" build-binaries: From 8bfe3bc909ca7440af6264302207edf00368bec7 Mon Sep 17 00:00:00 2001 From: Michal Klos Date: Thu, 9 Apr 2026 23:52:21 +0200 Subject: [PATCH 19/25] feat: [OCISDEV-783] release pipeline, dev.1 --- .github/workflows/release.yml | 2 ++ scripts/audit-release.py | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 39279602d07..2c56db2cd2c 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -358,6 +358,8 @@ jobs: --version "${{ needs.determine-release-type.outputs.version }}" \ --dir release-assets/ \ --github-release --docker + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} notify: runs-on: ubuntu-latest diff --git a/scripts/audit-release.py b/scripts/audit-release.py index a83f264da4e..38f7d7e7970 100755 --- a/scripts/audit-release.py +++ b/scripts/audit-release.py @@ -37,7 +37,7 @@ def expected_files(v): return [f for p in BINARY_PLATFORMS for f in (f"ocis-{v}-{p}", f"ocis-{v}-{p}.sha256")] + [EULA, LICENSES] def is_production(v): - return any(v.startswith(t) for t in PROD_TAGS) + return any(v.startswith(t) for t in PROD_TAGS) and "-" not in v def run(cmd): return subprocess.run(cmd, capture_output=True, text=True) From 209cf7562e78703d79438f3f613e6c0bf5f76e37 Mon Sep 17 00:00:00 2001 From: Michal Klos Date: Fri, 10 Apr 2026 00:11:27 +0200 Subject: [PATCH 20/25] feat: [OCISDEV-783] release pipeline, dev.1 --- .github/workflows/release.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 2c56db2cd2c..0ba343cba8e 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -330,15 +330,15 @@ jobs: path: . - uses: softprops/action-gh-release@153bb8e04406b158c6c84fc1615b65b24149a1fe # v2.6.1 with: - tag_name: ${{ needs.determine-release-type.outputs.version }} - name: ${{ needs.determine-release-type.outputs.version }} + tag_name: v${{ needs.determine-release-type.outputs.version }} + name: v${{ needs.determine-release-type.outputs.version }} body_path: CHANGELOG.md prerelease: ${{ needs.determine-release-type.outputs.is_prerelease == 'true' }} files: release-assets/* audit-release: runs-on: ubuntu-latest - needs: [determine-release-type, create-github-release] + needs: [determine-release-type, create-github-release, docker-manifest] steps: - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4 From 8ac3e471d12c950d6aebc975aa2da57d290b0714 Mon Sep 17 00:00:00 2001 From: Michal Klos Date: Fri, 10 Apr 2026 00:33:02 +0200 Subject: [PATCH 21/25] feat: [OCISDEV-783] release pipeline, dev.1 --- .github/workflows/release.yml | 13 ++++++++++++- scripts/audit-release.py | 2 +- 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 0ba343cba8e..9060f6f8254 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -338,7 +338,18 @@ jobs: audit-release: runs-on: ubuntu-latest - needs: [determine-release-type, create-github-release, docker-manifest] + needs: + - determine-release-type + - generate-code + - docker-build + - docker-scan + - docker-manifest + - docker-readme + - build-binaries + - security-scan-trivy + - license-check + - generate-changelog + - create-github-release steps: - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4 diff --git a/scripts/audit-release.py b/scripts/audit-release.py index 38f7d7e7970..025c59998a2 100755 --- a/scripts/audit-release.py +++ b/scripts/audit-release.py @@ -128,7 +128,7 @@ def check_github_release(version): checks = [ (r.get("tag_name") == f"v{version}", f"tag_name: {r.get('tag_name')}"), - (r.get("name") == version, f"name: {r.get('name')}"), + (r.get("name") == f"v{version}", f"name: {r.get('name')}"), (not r.get("draft"), "draft: false"), (r.get("prerelease") == ("-" in version), f"prerelease: {r.get('prerelease')}"), ] From 6ad36b6ebcd2502684fd06ee90cf8a6ec0181ef7 Mon Sep 17 00:00:00 2001 From: Michal Klos Date: Fri, 10 Apr 2026 00:48:07 +0200 Subject: [PATCH 22/25] feat: [OCISDEV-783] release pipeline, dev.1 --- .github/workflows/release.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 9060f6f8254..fca5c43c1a6 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -397,6 +397,7 @@ jobs: || SOURCE="${{ github.ref_type == 'tag' && format('tag {0}', github.ref_name) || github.ref_name }}" SHA="${{ github.sha }}" MSG="${STATUS} [${{ github.repository }}#${SHA:0:8}](${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}) (${SOURCE}) by **${{ github.triggering_actor }}**" + [[ -z "${{ secrets.MATRIX_HOMESERVER }}" ]] && { echo "MATRIX_HOMESERVER not set, skipping notification"; exit 0; } curl -sf -X PUT \ -H "Authorization: Bearer ${{ secrets.MATRIX_TOKEN }}" \ -H "Content-Type: application/json" \ From 6f6c4926e83f0fd6d548f8aceceb3f8f6051a685 Mon Sep 17 00:00:00 2001 From: Michal Klos Date: Fri, 10 Apr 2026 01:02:18 +0200 Subject: [PATCH 23/25] feat: [OCISDEV-783] release pipeline, dev.1 --- .github/workflows/release.yml | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index fca5c43c1a6..4dbeacdfc6f 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -301,7 +301,13 @@ jobs: - uses: actions/setup-go@4b73464bb391d4059bd26b0524d20df3927bd417 # v6.3.0 with: go-version: ${{ env.GO_VERSION }} - - run: make changelog CHANGELOG_VERSION=$(echo "${{ needs.determine-release-type.outputs.version }}" | cut -d'-' -f1) + - run: | + make changelog CHANGELOG_VERSION=$(echo "${{ needs.determine-release-type.outputs.version }}" | cut -d'-' -f1) + # calens produces empty output when no versioned changelog directory exists (e.g. dev builds). + # Fall back to a pointer to the unreleased entries. + if [[ $(wc -l < ocis/dist/CHANGELOG.md) -lt 5 ]]; then + echo "Development release — no release notes yet. See [unreleased changes](https://github.com/owncloud/ocis/tree/master/changelog/unreleased/)." > ocis/dist/CHANGELOG.md + fi - uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4 with: name: changelog From 2aeb7920a640a9bf2d763bc657101f530ba373a4 Mon Sep 17 00:00:00 2001 From: Michal Klos Date: Fri, 10 Apr 2026 10:42:14 +0200 Subject: [PATCH 24/25] feat: [OCISDEV-783] release pipeline, dev.1 --- .github/workflows/release.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 4dbeacdfc6f..65c46e98b9d 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -48,7 +48,7 @@ jobs: VERSION="${{ inputs.version_override }}" [[ -z "$VERSION" ]] && VERSION=$(next_dev) elif [[ "${{ github.ref_type }}" == "branch" ]]; then - VERSION=$(next_dev) + VERSION="8.0.2-dev.1" else VERSION="${GITHUB_REF#refs/tags/v}" fi From 1fe039546ea99bae7611a1644e6454c2a88b556a Mon Sep 17 00:00:00 2001 From: Michal Klos Date: Fri, 10 Apr 2026 11:29:52 +0200 Subject: [PATCH 25/25] feat: [OCISDEV-783] release pipeline, trivy scan --- .github/workflows/release.yml | 34 ++++++++++++++++++---------------- 1 file changed, 18 insertions(+), 16 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 65c46e98b9d..12b6d1d1e06 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -173,14 +173,18 @@ jobs: arch: [amd64] repo: ${{ fromJSON(needs.determine-release-type.outputs.docker_repos) }} steps: - - # replaces aquasecurity/trivy-action — not on org allowlist - run: | - curl -sfL https://raw.githubusercontent.com/aquasecurity/trivy/main/contrib/install.sh | sh -s -- -b /usr/local/bin - trivy image \ - --format table \ - --exit-code 0 \ - --severity CRITICAL,HIGH \ - "${{ matrix.repo }}:${{ needs.determine-release-type.outputs.version }}-linux-${{ matrix.arch }}" + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + - uses: aquasecurity/trivy-action@57a97c7e7821a5776cebc9bb87c984fa69cba8f1 # v0.35.0 + with: + image-ref: ${{ matrix.repo }}:${{ needs.determine-release-type.outputs.version }}-linux-${{ matrix.arch }} + format: table + exit-code: 1 + severity: HIGH,CRITICAL + ignore-unfixed: true + skip-files: /usr/bin/gomplate,/usr/bin/wait-for + hide-progress: true + env: + TRIVY_IGNOREFILE: .trivyignore docker-manifest: name: docker-manifest (${{ matrix.repo }}) @@ -257,14 +261,12 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - - # replaces aquasecurity/trivy-action — not on org allowlist - run: | - curl -sfL https://raw.githubusercontent.com/aquasecurity/trivy/main/contrib/install.sh | sh -s -- -b /usr/local/bin - trivy fs \ - --format table \ - --exit-code 0 \ - --severity CRITICAL,HIGH \ - . + - uses: aquasecurity/trivy-action@57a97c7e7821a5776cebc9bb87c984fa69cba8f1 # v0.35.0 + with: + scan-type: fs + format: table + exit-code: 0 + severity: CRITICAL,HIGH license-check: runs-on: ubuntu-latest