Spaces:
Build error
Build error
| name: Visual Regression Dispatch | |
| # Dispatches visual regression processing to ci-privileged after CI completes. | |
| # Runs in the context of the base repo (not the fork) so it has access to secrets, | |
| # making it work for external contributor PRs. | |
| # | |
| # All paths trigger the same ci-privileged workflow (post-visual-regression-comment.yaml) | |
| # via workflow_dispatch, passing the project as an input. ci-privileged routes to the | |
| # correct Argos project based on it. | |
| on: | |
| workflow_run: | |
| workflows: ['CI UI', 'CI Front'] | |
| types: [completed] | |
| permissions: | |
| actions: read | |
| contents: read | |
| pull-requests: read | |
| jobs: | |
| resolve-context: | |
| if: github.event.workflow_run.conclusion == 'success' | |
| runs-on: ubuntu-latest | |
| timeout-minutes: 5 | |
| outputs: | |
| workflow_name: ${{ steps.context.outputs.workflow_name }} | |
| project: ${{ steps.context.outputs.project }} | |
| artifact_name: ${{ steps.context.outputs.artifact_name }} | |
| has_artifact: ${{ steps.check-artifact.outputs.exists }} | |
| is_pr: ${{ steps.pr-info.outputs.has_pr }} | |
| pr_number: ${{ steps.pr-info.outputs.pr_number }} | |
| merge_base_sha: ${{ steps.merge-base.outputs.sha }} | |
| parent_commits: ${{ steps.merge-base.outputs.parent_commits }} | |
| steps: | |
| - name: Resolve workflow context | |
| id: context | |
| uses: actions/github-script@f28e40c7f34bde8b3046d885e986cb6290c5673b # v7.1.0 | |
| with: | |
| script: | | |
| const name = context.payload.workflow_run.name; | |
| const projectByWorkflow = { | |
| 'CI UI': 'twenty-ui', | |
| 'CI Front': 'twenty-front', | |
| }; | |
| const project = projectByWorkflow[name] ?? 'twenty-front'; | |
| const artifactName = `argos-screenshots-${project}`; | |
| core.setOutput('workflow_name', name); | |
| core.setOutput('project', project); | |
| core.setOutput('artifact_name', artifactName); | |
| core.info(`Workflow: ${name}, project: ${project}, artifact: ${artifactName}`); | |
| - name: Check if screenshots artifact exists | |
| id: check-artifact | |
| uses: actions/github-script@f28e40c7f34bde8b3046d885e986cb6290c5673b # v7.1.0 | |
| with: | |
| script: | | |
| const artifactName = '${{ steps.context.outputs.artifact_name }}'; | |
| const runId = context.payload.workflow_run.id; | |
| const { data: artifacts } = await github.rest.actions.listWorkflowRunArtifacts({ | |
| owner: context.repo.owner, | |
| repo: context.repo.repo, | |
| run_id: runId, | |
| }); | |
| const found = artifacts.artifacts.some(a => a.name === artifactName); | |
| core.setOutput('exists', found ? 'true' : 'false'); | |
| if (!found) { | |
| core.info(`Artifact "${artifactName}" not found in run ${runId} — skipping`); | |
| } | |
| - name: Get PR number | |
| if: >- | |
| steps.check-artifact.outputs.exists == 'true' && | |
| github.event.workflow_run.event == 'pull_request' | |
| id: pr-info | |
| uses: actions/github-script@f28e40c7f34bde8b3046d885e986cb6290c5673b # v7.1.0 | |
| with: | |
| script: | | |
| const headBranch = context.payload.workflow_run.head_branch; | |
| const headRepo = context.payload.workflow_run.head_repository; | |
| let pullRequests = context.payload.workflow_run.pull_requests; | |
| let prNumber; | |
| if (pullRequests && pullRequests.length > 0) { | |
| prNumber = pullRequests[0].number; | |
| } else { | |
| const headLabel = `${headRepo.owner.login}:${headBranch}`; | |
| core.info(`Searching for PR by head label: ${headLabel}`); | |
| const { data: prs } = await github.rest.pulls.list({ | |
| owner: context.repo.owner, | |
| repo: context.repo.repo, | |
| state: 'open', | |
| head: headLabel, | |
| per_page: 1, | |
| }); | |
| if (prs.length > 0) { | |
| prNumber = prs[0].number; | |
| } | |
| } | |
| if (!prNumber) { | |
| core.info('No pull request found — skipping'); | |
| core.setOutput('has_pr', 'false'); | |
| return; | |
| } | |
| core.setOutput('pr_number', prNumber); | |
| core.setOutput('has_pr', 'true'); | |
| core.info(`PR #${prNumber}`); | |
| - name: Compute merge-base for Argos reference | |
| if: steps.check-artifact.outputs.exists == 'true' && steps.pr-info.outputs.has_pr == 'true' | |
| id: merge-base | |
| uses: actions/github-script@f28e40c7f34bde8b3046d885e986cb6290c5673b # v7.1.0 | |
| with: | |
| script: | | |
| const headSha = context.payload.workflow_run.head_sha; | |
| try { | |
| const { data: comparison } = await github.rest.repos.compareCommitsWithBasehead({ | |
| owner: context.repo.owner, | |
| repo: context.repo.repo, | |
| basehead: `main...${headSha}`, | |
| }); | |
| const mergeBaseSha = comparison.merge_base_commit?.sha; | |
| if (mergeBaseSha) { | |
| core.setOutput('sha', mergeBaseSha); | |
| core.info(`Merge base: ${mergeBaseSha}`); | |
| const { data: commits } = await github.rest.repos.listCommits({ | |
| owner: context.repo.owner, | |
| repo: context.repo.repo, | |
| sha: mergeBaseSha, | |
| per_page: 100, | |
| }); | |
| const parentCommits = commits.map((commit) => commit.sha); | |
| core.setOutput('parent_commits', parentCommits.join(' ')); | |
| core.info(`Parent commits: ${parentCommits.length}`); | |
| } else { | |
| core.info('Could not determine merge base — will skip reference_commit'); | |
| core.setOutput('sha', ''); | |
| core.setOutput('parent_commits', ''); | |
| } | |
| } catch (error) { | |
| core.warning(`Failed to compute merge base: ${error instanceof Error ? error.message : String(error)}`); | |
| core.setOutput('sha', ''); | |
| core.setOutput('parent_commits', ''); | |
| } | |
| # ── Dispatch: pixel diff for the triggering workflow's project (PRs + main) ── | |
| dispatch-pixel-diff: | |
| needs: resolve-context | |
| if: needs.resolve-context.outputs.has_artifact == 'true' | |
| runs-on: ubuntu-latest | |
| timeout-minutes: 5 | |
| steps: | |
| - name: Mint ci-privileged dispatch token | |
| id: app-token | |
| uses: actions/create-github-app-token@bcd2ba49218906704ab6c1aa796996da409d3eb1 # v3.2.0 | |
| with: | |
| client-id: ${{ vars.TWENTY_WORKFLOW_DISPATCHER_CLIENT_ID }} | |
| private-key: ${{ secrets.TWENTY_WORKFLOW_DISPATCHER_PRIVATE_KEY }} | |
| owner: twentyhq | |
| repositories: ci-privileged | |
| permission-actions: write | |
| - name: Dispatch to ci-privileged | |
| env: | |
| GH_TOKEN: ${{ steps.app-token.outputs.token }} | |
| PROJECT: ${{ needs.resolve-context.outputs.project }} | |
| PR_NUMBER: ${{ needs.resolve-context.outputs.pr_number }} | |
| WORKFLOW_RUN_ID: ${{ github.event.workflow_run.id }} | |
| REPOSITORY: ${{ github.repository }} | |
| BRANCH: ${{ github.event.workflow_run.head_branch }} | |
| COMMIT: ${{ github.event.workflow_run.head_sha }} | |
| REFERENCE_COMMIT: ${{ needs.resolve-context.outputs.merge_base_sha }} | |
| PARENT_COMMITS: ${{ needs.resolve-context.outputs.parent_commits }} | |
| ARTIFACT_NAME: ${{ needs.resolve-context.outputs.artifact_name }} | |
| run: | | |
| ARGS=( | |
| -f project="$PROJECT" | |
| -f artifact_name="$ARTIFACT_NAME" | |
| -f run_id="$WORKFLOW_RUN_ID" | |
| -f repo="$REPOSITORY" | |
| -f branch="$BRANCH" | |
| -f commit="$COMMIT" | |
| ) | |
| if [ -n "$PR_NUMBER" ]; then | |
| ARGS+=(-f pr_number="$PR_NUMBER") | |
| fi | |
| if [ -n "$REFERENCE_COMMIT" ]; then | |
| ARGS+=(-f reference_commit="$REFERENCE_COMMIT") | |
| fi | |
| if [ -n "$PARENT_COMMITS" ]; then | |
| ARGS+=(-f parent_commits="$PARENT_COMMITS") | |
| fi | |
| gh workflow run post-visual-regression-comment.yaml --repo twentyhq/ci-privileged --ref main "${ARGS[@]}" | |