diff --git a/.github/workflows/cla.yaml b/.github/workflows/cla.yaml index 2c7cc9d553..ec376e98b5 100644 --- a/.github/workflows/cla.yaml +++ b/.github/workflows/cla.yaml @@ -8,7 +8,7 @@ on: jobs: cla-workflow: - uses: pimcore/workflows-collection-public/.github/workflows/reusable-cla-check.yaml@v1.3.0 + uses: pimcore/workflows-collection-public/.github/workflows/reusable-cla-check.yaml@main if: (github.event.comment.body == 'recheck' || github.event.comment.body == 'I have read the CLA Document and I hereby sign the CLA') || github.event_name == 'pull_request_target' secrets: CLA_ACTION_ACCESS_TOKEN: ${{ secrets.CLA_ACTION_ACCESS_TOKEN }} diff --git a/.github/workflows/copilot-setup-steps.yml b/.github/workflows/copilot-setup-steps.yml new file mode 100644 index 0000000000..2f1229587a --- /dev/null +++ b/.github/workflows/copilot-setup-steps.yml @@ -0,0 +1,51 @@ +name: "Copilot Setup Steps" + +# Automatically run the setup steps when they are changed to allow for easy validation, and +# allow manual testing through the repository's "Actions" tab +on: + workflow_dispatch: + push: + paths: + - .github/workflows/copilot-setup-steps.yml + pull_request: + paths: + - .github/workflows/copilot-setup-steps.yml + +jobs: + # The job MUST be called `copilot-setup-steps` or it will not be picked up by Copilot. + # The steps MUST be defined inline here: the Copilot coding agent only reads `steps` + # (plus permissions/runs-on/services/snapshot/timeout-minutes) from this job, so a + # reusable-workflow `uses:` call would be ignored by Copilot. + copilot-setup-steps: + runs-on: ubuntu-latest + + permissions: + contents: read + + steps: + - name: Checkout code + uses: actions/checkout@v7 + + - name: "Install PHP" + uses: "shivammathur/setup-php@v2" + with: + php-version: "8.4" + + - name: "Configure private pimcore package repository" + run: | + composer config repositories.private-packagist '{"type": "composer", "url": "https://repo.pimcore.com/github-actions/", "canonical": true}' + + - name: "Install dependencies with Composer" + uses: "ramsey/composer-install@v3" + # Pass the private-Packagist token via a step-scoped env var instead of + # writing it to Composer's global auth.json. A global credential would + # persist on the runner filesystem and remain readable by the Copilot + # coding agent after setup; COMPOSER_AUTH lives only for this step. + env: + COMPOSER_AUTH: '{"http-basic":{"repo.pimcore.com":{"username":"github-actions","password":"${{ secrets.COMPOSER_PIMCORE_REPO_PACKAGIST_TOKEN }}"}}}' + with: + composer-options: "--no-scripts --ignore-platform-reqs" + + - name: Restore composer.json + if: ${{ always() }} + run: git restore composer.json diff --git a/.github/workflows/docs.yaml.bak b/.github/workflows/docs.yaml.bak deleted file mode 100644 index 1443c5d5a3..0000000000 --- a/.github/workflows/docs.yaml.bak +++ /dev/null @@ -1,76 +0,0 @@ -Original docs workflow disabled in favor of new-docs.yml -This file is kept only for reference. The active workflow is .github/workflows/new-docs.yml -Backup of the original content: .github/workflows/docs.yaml.bak - - -name: "Documentation" - -on: - pull_request_target: - branches: - - "[0-9]+.[0-9]+" - - "[0-9]+.x" - paths: - - 'doc/**' - - '.github/workflows/docs.yaml' - - 'README.md' - push: - branches: - - "[0-9]+.[0-9]+" - - "[0-9]+.x" - - "*_actions" - paths: - - 'doc/**' - - '.github/workflows/docs.yaml' - - 'README.md' - -permissions: - contents: read - -jobs: - docs: - name: "Generate docs Pimcore Docs Generator" - runs-on: "ubuntu-latest" - steps: - - name: "Checkout code" - uses: "actions/checkout@v4" - with: - ref: ${{ github.event.pull_request.head.ref }} - repository: ${{ github.event.pull_request.head.repo.full_name }} - - - name: "Checkout Docs Generator" - uses: "actions/checkout@v4" - with: - repository: "pimcore/docs-generator" - ref: "main" - path: "./docs-generator" - token: ${{ secrets.DOCS_GENERATOR_ACCESS_TOKEN }} - - - name: "Install Node" - uses: actions/setup-node@v4 - with: - node-version: 22.x - registry-url: 'https://registry.npmjs.org' - - - name: Prepare Docs - working-directory: "./docs-generator" - run: | - mkdir docs - copy docs to working directory - cp -r ../doc ./docs/ - - copy readme to working directory - cp -r ../README.md ./docs/ - - copy index page - cp bin/resources/00_index_empty.md ./docs/00_index.md - - use special docusaurus config (to exclude search plugin) and check for broken links - mv docusaurus.config.js.repos-tests docusaurus.config.js - - - name: Build Docs - working-directory: "./docs-generator" - run: | - npm install - npm run build - diff --git a/.github/workflows/new-docs.yml b/.github/workflows/docs.yml similarity index 100% rename from .github/workflows/new-docs.yml rename to .github/workflows/docs.yml diff --git a/.github/workflows/frontend-build-pr.yaml b/.github/workflows/frontend-build-pr.yaml deleted file mode 100644 index 402789f1b4..0000000000 --- a/.github/workflows/frontend-build-pr.yaml +++ /dev/null @@ -1,39 +0,0 @@ -name: "Frontend Build (PR and Feature Branches)" - -on: - push: - branches: - - "[0-9]+.[0-9]+" - - "feature-*" - - "nightly" - # TEMP (remove before merge): regenerate build-dist/build-.zip on every push to - # this PR branch — pull_request_target uses the base workflow, which has no packaging. - - "feature/frontend-build-archive" - pull_request_target: - branches: - - "[0-9]+.[0-9]+" - - "[0-9]+.x" - - "*_actions" - - "feature-*" - - "nightly" - workflow_dispatch: - -env: - BRANCH_NAME: ${{ github.head_ref || github.ref_name }} - -# The push and pull_request_target triggers both fire for pushes to a feature -# branch with an open PR, producing two concurrent runs that race to push -# auto-commits to the same branch (non-fast-forward "fetch first" failures). -# Grouping them serializes per branch; cancel-in-progress drops the stale run. -concurrency: - group: ${{ github.workflow }}-${{ github.event.pull_request.head.repo.full_name || github.repository }}-${{ github.head_ref || github.ref_name }} - cancel-in-progress: true - -permissions: - contents: read - -jobs: - build: - permissions: - contents: write - uses: ./.github/workflows/shared-frontend-build.yaml diff --git a/.github/workflows/frontend-publish-unified.yaml b/.github/workflows/frontend-publish-unified.yaml index 92ccfd1c5b..36f2c8ea35 100644 --- a/.github/workflows/frontend-publish-unified.yaml +++ b/.github/workflows/frontend-publish-unified.yaml @@ -4,116 +4,132 @@ on: push: branches: - "[0-9]+.x" + - "[0-9]+.[0-9]+" tags: - "v*" workflow_dispatch: -env: - BRANCH_NAME: ${{ github.head_ref || github.ref_name }} - TARGET_RELEASE: 1.0.0 +concurrency: + group: frontend-publish-${{ github.ref }} + cancel-in-progress: false permissions: - id-token: write # Required for OIDC contents: read -jobs: - canary-build: - if: github.event_name != 'push' || !startsWith(github.ref, 'refs/tags/') - permissions: - contents: write - uses: ./.github/workflows/shared-frontend-build.yaml +env: + # Canary base used when a version line has no published release yet + # (matches the reference implementation, data-hub#1119). + FALLBACK_TARGET_RELEASE: "2025.4.0" - canary-generate-version: - if: github.event_name != 'push' || !startsWith(github.ref, 'refs/tags/') - needs: canary-build +jobs: + gate: runs-on: ubuntu-latest outputs: - generated_version: ${{ steps.gen.outputs.version }} + publish: ${{ steps.check.outputs.publish }} + target-release: ${{ steps.target.outputs.target-release }} + canary-tag: ${{ steps.target.outputs.canary-tag }} steps: - name: Checkout repository - uses: actions/checkout@v4 + uses: actions/checkout@v7 - - name: Generate Canary Version - id: gen - shell: bash - run: | - # Get the base version (e.g., "1.2.3") from package.json - BASE_VERSION=${{ env.TARGET_RELEASE }} - # Remove any pre-release suffix if present - BASE_VERSION=${BASE_VERSION%%-*} - # Create a timestamp (YYYYMMDD--HHMMSS) - TIMESTAMP=$(date +'%Y%m%d-%H%M%S') - # Get a short commit hash (7 characters) - GIT_HASH=$(git rev-parse --short=7 HEAD) - NEW_VERSION="${BASE_VERSION}-canary.${TIMESTAMP}-${GIT_HASH}" - echo "Computed version: ${NEW_VERSION}" - echo "version=${NEW_VERSION}" >> "$GITHUB_OUTPUT" - - canary-publish: - if: github.event_name != 'push' || !startsWith(github.ref, 'refs/tags/') - needs: canary-generate-version - permissions: - id-token: write # Required for OIDC - contents: read - uses: ./.github/workflows/shared-npm-publish.yaml - with: - version: "${{ needs.canary-generate-version.outputs.generated_version }}" - tag: "canary" + - name: Set up Node.js + uses: actions/setup-node@v7 + with: + node-version: "24" - release-determine-version: - if: github.event_name == 'push' && startsWith(github.ref, 'refs/tags/') - runs-on: ubuntu-latest - outputs: - version: ${{ steps.extract_version.outputs.version }} - npm_tag: ${{ steps.extract_npm.outputs.npm_tag }} - steps: - - name: Checkout repository - uses: actions/checkout@v4 - - - name: Extract version from tag - id: extract_version + - name: Check for frontend changes + id: check shell: bash + env: + BEFORE: ${{ github.event.before }} run: | - # In a push event on a tag, github.ref_name contains the tag name (e.g. "v1.2.3") - TAG_NAME="${GITHUB_REF_NAME}" - echo "Detected tag: ${TAG_NAME}" - # Remove the leading "v" using Bash parameter expansion - VERSION="${TAG_NAME#v}" - echo "Computed version: ${VERSION}" - echo "version=${VERSION}" >> "$GITHUB_OUTPUT" + publish=false + if [[ "${GITHUB_REF}" == refs/tags/* ]]; then + publish=true + elif [[ ! "${GITHUB_REF_NAME}" =~ ^[0-9]+\.(x|[0-9]+)$ ]]; then + # Canaries only from version branches (e.g. 2026.x, 2026.2, 2.4) + publish=false + elif [[ "${GITHUB_EVENT_NAME}" == "workflow_dispatch" ]]; then + publish=true + elif [[ -z "${BEFORE}" || "${BEFORE}" =~ ^0+$ ]]; then + # New branch: no base to diff against — publish rather than miss one + publish=true + elif ! git fetch --quiet --no-tags --depth=1 origin "${BEFORE}"; then + # Base commit unavailable (e.g. after a force push) — publish rather than miss one + publish=true + elif CHANGED="$(git diff --name-only "${BEFORE}" "${GITHUB_SHA}" -- assets)"; then + if [[ -n "${CHANGED}" ]]; then + publish=true + fi + else + # Diff failed — publish rather than miss one + publish=true + fi + echo "Frontend changed / must publish: ${publish}" + echo "publish=${publish}" >> "$GITHUB_OUTPUT" - - name: Extract npm tag - id: extract_npm + - name: Determine canary target release and tag + id: target + if: steps.check.outputs.publish == 'true' shell: bash run: | - # Retrieve the version from the previous step - VERSION="${{ steps.extract_version.outputs.version }}" - echo "Using version: ${VERSION}" - - # Determine the npm tag: - # If the version contains a hyphen, assume there is a pre-release identifier. - if [[ "$VERSION" == *"-"* ]]; then - # Extract text after the first hyphen - pre_release="${VERSION#*-}" - # Extract only the leading contiguous alphabetical string - npm_tag="$(echo "$pre_release" | grep -oE '^[A-Za-z]+' | tr '[:upper:]' '[:lower:]')" - - # Fallback: if nothing is extracted, default to latest. - if [ -z "$npm_tag" ]; then - npm_tag="latest" - fi + # Tag runs: the reusable workflow derives the release version from the + # tag itself, so target-release is unused here — emit a non-empty + # placeholder so the publish job still runs. canary-tag is irrelevant + # for tag/release publishes. + if [[ "${GITHUB_REF}" == refs/tags/* ]]; then + echo "target-release=tag" >> "$GITHUB_OUTPUT" + echo "canary-tag=canary" >> "$GITHUB_OUTPUT" + exit 0 + fi + + BRANCH="${GITHUB_REF_NAME}" + # Per-branch canary dist-tag so every live version branch publishes its + # own canary (canary-2026.x, canary-2026.2, canary-2.4, …). + echo "canary-tag=canary-${BRANCH}" >> "$GITHUB_OUTPUT" + + # Canary base = next release of this branch's line; the branch name + # (e.g. "2026.x", "2026.2") is itself a valid semver range. + PKG_NAME="$(node -p "require('./assets/package.json').name" 2>/dev/null || true)" + LINE_LATEST="$([ -n "${PKG_NAME}" ] && npm view "${PKG_NAME}@${BRANCH}" version --json 2>/dev/null | node -p '(v=>{if(Array.isArray(v))v=v[v.length-1];return typeof v==="string"?v:""})(JSON.parse(require("fs").readFileSync(0,"utf8")))' 2>/dev/null || true)" + if [[ "${LINE_LATEST}" =~ ^([0-9]+)\.([0-9]+)\.([0-9]+)$ ]]; then + # Line already has published releases: base the canary on the next one. + if [[ "${BRANCH}" == *.x ]]; then + TARGET="${BASH_REMATCH[1]}.$(( BASH_REMATCH[2] + 1 )).0" + else + TARGET="${BASH_REMATCH[1]}.${BASH_REMATCH[2]}.$(( BASH_REMATCH[3] + 1 ))" + fi else - npm_tag="latest" + # No release published on this line yet: fall back to the configured + # base so a brand-new version branch still publishes canaries + # (matches the reference implementation, data-hub#1119). + TARGET="${FALLBACK_TARGET_RELEASE}" fi - echo "Computed npm tag: ${npm_tag}" - - # Export the npm tag as an output for downstream steps - echo "npm_tag=${npm_tag}" >> "$GITHUB_OUTPUT" + echo "Canary target release for ${BRANCH}: ${TARGET}" + echo "target-release=${TARGET}" >> "$GITHUB_OUTPUT" - publish-release: - if: github.event_name == 'push' && startsWith(github.ref, 'refs/tags/') - needs: release-determine-version - uses: ./.github/workflows/shared-npm-publish.yaml + publish: + needs: gate + if: needs.gate.outputs.publish == 'true' && needs.gate.outputs.target-release != '' + permissions: + id-token: write # Required for OIDC trusted publishing + contents: write + uses: pimcore/workflows-collection-public/.github/workflows/reusable-frontend-publish-unified.yaml@main with: - version: "${{ needs.release-determine-version.outputs.version }}" - tag: "${{ needs.release-determine-version.outputs.npm_tag }}" + target-release: ${{ needs.gate.outputs.target-release }} + canary-tag: ${{ needs.gate.outputs.canary-tag }} + working-directory: ./assets + node-version: "24" + build-script: ci-build + build-output-path: ./build-dist/ + # studio-ui runs tests as part of the publish gate; the API client is + # already committed by the build workflow, so no need to regenerate here. + test: true + api-client: false + # Publishing must not push commits back to the branch. + commit-lint-output: false + commit-build-output: false + pre-publish-script: ci-prepublish + # OIDC trusted publishing (no NPM_TOKEN). npm is pinned to 11 because + # npm@12 fails at publish time with a broken sigstore dependency. + npm-cli-version: "11" diff --git a/.github/workflows/new-php-cs-fixer.yaml b/.github/workflows/php-cs-fixer.yaml similarity index 100% rename from .github/workflows/new-php-cs-fixer.yaml rename to .github/workflows/php-cs-fixer.yaml diff --git a/.github/workflows/php-cs-fixer.yaml.bak b/.github/workflows/php-cs-fixer.yaml.bak deleted file mode 100644 index 75edebc638..0000000000 --- a/.github/workflows/php-cs-fixer.yaml.bak +++ /dev/null @@ -1,35 +0,0 @@ -name: "PHP-CS-Fixer" - -on: - pull_request_target: - branches: - - "[0-9]+.[0-9]+" - - "[0-9]+.x" - - "feature-*" - push: - branches: - - "[0-9]+.[0-9]+" - - "[0-9]+.x" - - "*_actions" - - "feature-*" - -permissions: - contents: read - -jobs: - php-cs-fixer: - permissions: - contents: write # for stefanzweifel/git-auto-commit-action to push code in repo - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v4 - with: - ref: ${{ github.event.pull_request.head.ref }} - repository: ${{ github.event.pull_request.head.repo.full_name }} - - - name: PHP-CS-Fixer - uses: docker://oskarstark/php-cs-fixer-ga:latest - - - uses: stefanzweifel/git-auto-commit-action@v5 - with: - commit_message: Apply php-cs-fixer changes \ No newline at end of file diff --git a/.github/workflows/new-poeditor-export.yaml b/.github/workflows/poeditor-export.yaml similarity index 100% rename from .github/workflows/new-poeditor-export.yaml rename to .github/workflows/poeditor-export.yaml diff --git a/.github/workflows/poeditor-export.yaml.bak b/.github/workflows/poeditor-export.yaml.bak deleted file mode 100644 index ecf9cb0a64..0000000000 --- a/.github/workflows/poeditor-export.yaml.bak +++ /dev/null @@ -1,22 +0,0 @@ -name: "Trigger POEditor Translations Export" - -on: - workflow_dispatch: - push: - branches: - - "[0-9]+.x" - paths: - - 'translations/admin.en.yaml' - -permissions: - contents: read - -jobs: - poeditor: - runs-on: ubuntu-latest - steps: - - name: Trigger workflow in pimcore/poeditor-export-action - env: - GH_TOKEN: ${{ secrets.POEDITOR_ACTION_TRIGGER_TOKEN }} - run: | - gh workflow run -R pimcore/poeditor-export-action poeditor-export.yaml \ No newline at end of file diff --git a/.github/workflows/pr-guardrails.yml b/.github/workflows/pr-guardrails.yml new file mode 100644 index 0000000000..ad315d6912 --- /dev/null +++ b/.github/workflows/pr-guardrails.yml @@ -0,0 +1,30 @@ +name: PR Guardrails + +# Thin, generic trigger. All guardrail logic lives in the central collection +# pimcore/workflows-collection-public. This file names no guardrails and no +# secrets (secrets: inherit), so it is identical across every repo and never +# needs editing when a guardrail or token is added/removed there. + +on: + pull_request_target: + types: [opened, reopened, ready_for_review, converted_to_draft, edited, synchronize] + check_suite: + types: [completed] + +concurrency: + # One lock per PR. On pull_request_target → PR number. On check_suite there is + # no PR number, so use the PR from the check_suite payload (present for + # same-repo PRs) to share the same lock; fall back to the commit SHA for fork + # PRs, then to run_id so the key is never empty. + # A guardrail can convert the PR to draft, which fires converted_to_draft; + # give that its own group so it does not cancel the run still acting on the PR. + group: pr-guardrails-${{ github.event.action == 'converted_to_draft' && 'retract-' || '' }}${{ github.event.pull_request.number || github.event.check_suite.pull_requests[0].number || github.event.check_suite.head_sha || github.run_id }} + cancel-in-progress: true + +jobs: + guardrails: + uses: pimcore/workflows-collection-public/.github/workflows/parent-pr-guardrails.yml@main + secrets: + MEMBERSHIP_GUARD_TOKEN: ${{ secrets.MEMBERSHIP_GUARD_TOKEN }} + ISSUE_LINK_GUARD_TOKEN: ${{ secrets.ISSUE_LINK_GUARD_TOKEN }} + CI_GUARD_TOKEN: ${{ secrets.CI_GUARD_TOKEN }} diff --git a/.github/workflows/pr-policy.yml b/.github/workflows/pr-policy.yml new file mode 100644 index 0000000000..650e41664b --- /dev/null +++ b/.github/workflows/pr-policy.yml @@ -0,0 +1,42 @@ +name: PR Policy + +# Enforces PR requirements before merge. Make the "Milestone assigned" check required +# (repo ruleset / branch protection) so it actually blocks merging. + +on: + pull_request: + types: + - opened + - reopened + - synchronize + - ready_for_review + - milestoned + - demilestoned + +permissions: + contents: read + +jobs: + milestone: + name: Milestone assigned + if: github.event.pull_request.draft == false + runs-on: ubuntu-latest + + steps: + - name: Check milestone + env: + MILESTONE: ${{ github.event.pull_request.milestone.title }} + AUTHOR: ${{ github.event.pull_request.user.login }} + run: | + # Automated sync PRs (repo-file-sync-action) never carry a milestone. + if [ "$AUTHOR" = "pimcore-deployments" ]; then + echo "Skipping milestone check for automated PR by $AUTHOR" + exit 0 + fi + + if [ -z "$MILESTONE" ]; then + echo "::error::A milestone must be assigned before this pull request can be merged." + exit 1 + fi + + echo "Milestone assigned: $MILESTONE" diff --git a/.github/workflows/shared-frontend-build.yaml b/.github/workflows/shared-frontend-build.yaml deleted file mode 100644 index 4aba6d2f8c..0000000000 --- a/.github/workflows/shared-frontend-build.yaml +++ /dev/null @@ -1,212 +0,0 @@ -name: shared-frontend-build - -on: - workflow_call: - -env: - BRANCH_NAME: ${{ github.head_ref || github.ref_name }} - -permissions: - contents: read - -jobs: - install: - runs-on: ubuntu-latest - - steps: - - name: Checkout code - uses: actions/checkout@v4 - with: - ref: ${{ env.BRANCH_NAME }} - repository: ${{ github.event.pull_request.head.repo.full_name }} - - - name: Set up Node.js - uses: actions/setup-node@v4 - with: - node-version: 24 - - - name: Cache npm dependencies - uses: actions/cache@v4 - with: - path: ./assets/node_modules - key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }} - restore-keys: | - ${{ runner.os }}-node- - - - name: Install dependencies - working-directory: ./assets - run: npm ci - - api-client-build: - needs: install - runs-on: ubuntu-latest - - permissions: - contents: write - - steps: - - name: Checkout code - uses: actions/checkout@v4 - with: - ref: ${{ env.BRANCH_NAME }} - repository: ${{ github.event.pull_request.head.repo.full_name }} - - - name: Set up Node.js - uses: actions/setup-node@v4 - with: - node-version: 24 - - - name: Cache npm dependencies - uses: actions/cache@v4 - with: - path: ./assets/node_modules - key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }} - restore-keys: | - ${{ runner.os }}-node- - - - name: Run api client build - working-directory: ./assets - run: npm run build-api-client - - - uses: stefanzweifel/git-auto-commit-action@v5 - with: - commit_message: Apply latest automatic api client updates - - lint: - needs: api-client-build - runs-on: ubuntu-latest - - permissions: - contents: write - - steps: - - name: Checkout code - uses: actions/checkout@v4 - with: - ref: ${{ env.BRANCH_NAME }} - repository: ${{ github.event.pull_request.head.repo.full_name }} - - - name: Set up Node.js - uses: actions/setup-node@v4 - with: - node-version: 24 - - - name: Cache npm dependencies - uses: actions/cache@v4 - with: - path: ./assets/node_modules - key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }} - restore-keys: | - ${{ runner.os }}-node- - - - name: Run code linting - working-directory: ./assets - run: npm run lint-fix - - - uses: stefanzweifel/git-auto-commit-action@v5 - with: - commit_message: Apply eslint-fixer changes - - check-types: - needs: api-client-build - runs-on: ubuntu-latest - - permissions: - contents: write - - steps: - - name: Checkout code - uses: actions/checkout@v4 - with: - ref: ${{ env.BRANCH_NAME }} - repository: ${{ github.event.pull_request.head.repo.full_name }} - - - name: Set up Node.js - uses: actions/setup-node@v4 - with: - node-version: 24 - - - name: Cache npm dependencies - uses: actions/cache@v4 - with: - path: ./assets/node_modules - key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }} - restore-keys: | - ${{ runner.os }}-node- - - - name: Run type checks - working-directory: ./assets - run: npm run check-types - - build: - needs: - - lint - - check-types - runs-on: ubuntu-latest - - permissions: - contents: write - - steps: - - name: Checkout code - uses: actions/checkout@v4 - with: - ref: ${{ env.BRANCH_NAME }} - repository: ${{ github.event.pull_request.head.repo.full_name }} - - name: Set up Node.js - uses: actions/setup-node@v4 - with: - node-version: 24 - - - name: Cache npm dependencies - uses: actions/cache@v4 - with: - path: ./assets/node_modules - key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }} - restore-keys: | - ${{ runner.os }}-node- - - - name: Run production build - working-directory: ./assets - run: npm run build-app - - - name: Run rsbuild plugins build - working-directory: ./assets - run: npm run build-rsbuild-plugins - - - name: Package frontend build into archive - working-directory: ./assets - run: npm run package-build - - - uses: stefanzweifel/git-auto-commit-action@v5 - with: - file_pattern: './build-dist/' - commit_message: Automatic frontend build - - test: - needs: build - runs-on: ubuntu-latest - - steps: - - name: Checkout code - uses: actions/checkout@v4 - with: - ref: ${{ env.BRANCH_NAME }} - repository: ${{ github.event.pull_request.head.repo.full_name }} - - - name: Set up Node.js - uses: actions/setup-node@v4 - with: - node-version: 24 - - - name: Cache npm dependencies - uses: actions/cache@v4 - with: - path: ./assets/node_modules - key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }} - restore-keys: | - ${{ runner.os }}-node- - - - name: Run tests - working-directory: ./assets - run: npm run test diff --git a/.github/workflows/shared-npm-publish.yaml b/.github/workflows/shared-npm-publish.yaml deleted file mode 100644 index 0cab409b06..0000000000 --- a/.github/workflows/shared-npm-publish.yaml +++ /dev/null @@ -1,91 +0,0 @@ -name: shared-npm-publish - -on: - workflow_call: - inputs: - version: - description: "The new version to set (e.g., 1.2.3)" - required: true - type: string - tag: - description: "The npm tag to use when publishing (default: latest)" - required: false - type: string - default: "latest" - -env: - BRANCH_NAME: ${{ github.head_ref || github.ref_name }} - -jobs: - install: - runs-on: ubuntu-latest - steps: - - name: Checkout code - uses: actions/checkout@v4 - with: - ref: ${{ env.BRANCH_NAME }} - repository: ${{ github.event.pull_request.head.repo.full_name }} - - - name: Set up Node.js - uses: actions/setup-node@v4 - with: - node-version: '24' - registry-url: 'https://registry.npmjs.org' - - - name: Cache npm dependencies - uses: actions/cache@v4 - with: - path: ./assets/node_modules - key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }} - restore-keys: | - ${{ runner.os }}-node- - - - name: Install dependencies - working-directory: ./assets - run: npm ci - - publish: - runs-on: ubuntu-latest - needs: install - permissions: - id-token: write # Required for OIDC - contents: read - steps: - - name: Checkout code - uses: actions/checkout@v4 - with: - ref: ${{ env.BRANCH_NAME }} - repository: ${{ github.event.pull_request.head.repo.full_name }} - - - name: Cache npm dependencies - uses: actions/cache@v4 - with: - path: ./assets/node_modules - key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }} - restore-keys: | - ${{ runner.os }}-node- - - - name: Run build types - working-directory: ./assets - run: npm run generate-types - - - name: Run rsbuild plugins build - working-directory: ./assets - run: npm run build-rsbuild-plugins - - - name: Setup Node.js - uses: actions/setup-node@v4 - with: - node-version: '24' - registry-url: 'https://registry.npmjs.org' - - - name: Set package version - working-directory: ./assets - run: npm version ${{ inputs.version }} --no-git-tag-version --allow-same-version - - - name: Publish package to npm with OIDC - working-directory: ./assets - # Pin to npm 11: npm@12 (currently `npm@latest`) fails at publish time with - # "Cannot find module 'sigstore'" (broken sigstore dep in libnpmpublish/provenance). - # Revisit once npm upstream resolves the sigstore packaging issue. - run: npx npm@11 publish --tag ${{ inputs.tag }} --access public diff --git a/.github/workflows/new-static-analysis.yaml b/.github/workflows/static-analysis.yaml similarity index 97% rename from .github/workflows/new-static-analysis.yaml rename to .github/workflows/static-analysis.yaml index 4aaca14e4e..5dc52a1b7d 100644 --- a/.github/workflows/new-static-analysis.yaml +++ b/.github/workflows/static-analysis.yaml @@ -40,10 +40,10 @@ jobs: private_repo: ${{ env.PRIVATE_REPO }} steps: - name: Checkout code - uses: actions/checkout@v4 + uses: actions/checkout@v7 - name: Checkout reusable workflow repo - uses: actions/checkout@v4 + uses: actions/checkout@v7 with: repository: pimcore/workflows-collection-public ref: main diff --git a/.github/workflows/static-analysis.yaml.bak b/.github/workflows/static-analysis.yaml.bak deleted file mode 100644 index 2abbb09378..0000000000 --- a/.github/workflows/static-analysis.yaml.bak +++ /dev/null @@ -1,68 +0,0 @@ -name: "Static Analysis" - -on: - schedule: - - cron: '0 3 * * 1,3,5' - pull_request: - branches: - - "[0-9]+.[0-9]+" - - "[0-9]+.x" - - "feature-*" - paths-ignore: - #- 'doc/**' - - 'public/**' - push: - branches: - - "[0-9]+.[0-9]+" - - "[0-9]+.x" - - "*_actions" - -jobs: - static-analysis-phpstan: - name: "Static Analysis with PHPStan" - runs-on: "ubuntu-latest" - strategy: - matrix: - include: - - { php-version: "8.4", dependencies: "highest", experimental: false } - - { php-version: "8.4", dependencies: "highest", pimcore_version: "12.x-dev as 12.99.9", experimental: true } - steps: - - name: "Checkout code" - uses: "actions/checkout@v4" - - - name: "Install PHP" - uses: "shivammathur/setup-php@v2" - with: - coverage: "none" - php-version: "${{ matrix.php-version }}" - - - name: "Setup Pimcore environment" - run: | - .github/ci/scripts/setup-pimcore-environment.sh - - - name: "Update Pimcore version" - env: - PIMCORE_VERSION: "${{ matrix.pimcore_version }}" - run: | - if [ ! -z "$PIMCORE_VERSION" ]; then - composer require --no-update pimcore/pimcore:"${PIMCORE_VERSION}" - fi - - - name: "Install dependencies with Composer" - uses: "ramsey/composer-install@v3" - with: - dependency-versions: "${{ matrix.dependencies }}" - - - name: "Run a static analysis with phpstan/phpstan" - run: "vendor/bin/phpstan analyse --memory-limit=-1" - - - name: "Generate baseline file" - if: ${{ failure() }} - run: "vendor/bin/phpstan analyse --memory-limit=-1 --generate-baseline" - - - name: "Upload baseline file" - if: ${{ failure() }} - uses: actions/upload-artifact@v4 - with: - name: phpstan-baseline.neon - path: phpstan-baseline.neon diff --git a/.github/workflows/studio-frontend-build.yaml b/.github/workflows/studio-frontend-build.yaml new file mode 100644 index 0000000000..b526e878fd --- /dev/null +++ b/.github/workflows/studio-frontend-build.yaml @@ -0,0 +1,32 @@ +name: "Studio Frontend Build" + +on: + push: + paths: + - "assets/**" + pull_request: + paths: + - "assets/**" + workflow_dispatch: + +# Builds cancel superseded runs per branch; the reusable workflow serializes its +# own write (commit) jobs. +concurrency: + group: studio-frontend-build-${{ github.head_ref || github.ref_name }} + cancel-in-progress: true + +permissions: + contents: write + +jobs: + studio-frontend-build: + permissions: + contents: write + uses: pimcore/workflows-collection-public/.github/workflows/reusable-studio-frontend-build.yaml@main + with: + working-directory: ./assets + node-version: "24" + build-script: ci-build + build-output-path: ./build-dist/ + api-client: true + test: true diff --git a/assets/package.json b/assets/package.json index da2d057099..4325df5e02 100644 --- a/assets/package.json +++ b/assets/package.json @@ -18,6 +18,8 @@ "build": "rsbuild build", "build-sdk": "rsbuild build --config rsbuild.sdk.config.ts", "build-app": "npm run build-sdk && npm run build", + "ci-build": "npm run build-app && npm run build-rsbuild-plugins && npm run package-build", + "ci-prepublish": "npm run generate-types && npm run build-rsbuild-plugins", "package-build": "node ./bundler/package-build.cjs", "build-rsbuild-plugins": "rsbuild build --config rsbuild.plugins.config.ts", "build-storybook": "storybook build --output-dir ./storybook-static",