Commit Graph

17 Commits

Author SHA1 Message Date
Félix Malfait 2662fda647 ci(preview-env): run preview environments on free ci-public Actions (#22245)
## Why

PR preview environments were broken. The dispatch half (this repo) was
fine, but the receiving `preview-env.yaml` in **ci-privileged** failed
on every run — and ci-privileged is a **private** repo, so its 5h
keepalive job bills paid Actions minutes anyway.

The intended design (started but never wired up) runs the preview env on
the **public** `twentyhq/ci-public` repo, where Actions minutes are
free, and keeps no privileged token on the runner that executes
PR-controlled code. This finishes that migration.

## What this PR does

Repoints `preview-env-dispatch.yaml` to dispatch `preview-env.yaml` on
**ci-public** instead of ci-privileged. The dispatcher app token is
simply retargeted (still `actions:write` only, via `workflow_dispatch`).

## Companion PRs (must land together)

- **twentyhq/ci-public** — converts `preview-env.yaml` to
`workflow_dispatch`; dispatches the tunnel URL back to ci-privileged for
the PR comment before any PR code runs.
- **twentyhq/ci-privileged** — adds `preview-env-comment.yaml` (posts
the PR comment with the App key) and deletes the now-dead
`preview-env.yaml`.

## Manual prerequisites (cannot be done in a PR)

- Install/authorize the `TWENTY_WORKFLOW_DISPATCHER` GitHub App on
**ci-public** with `actions:write`.
- On **ci-public**: add `vars.DOCKERHUB_RO_USERNAME`,
`secrets.DOCKERHUB_RO_TOKEN`, and `secrets.CI_PRIVILEGED_DISPATCH_TOKEN`
(fine-grained PAT, `actions:write` on ci-privileged only).

## Suggested merge order

1. ci-privileged (receiver must exist on `main` before ci-public
dispatches to it)
2. ci-public (workflow must exist on `main` before this repo dispatches
to it)
3. this PR

## Test plan

- [ ] Open an internal PR touching `packages/twenty-docker/**`; confirm
`Preview Environment Dispatch` runs and triggers `Preview Environment`
on ci-public.
- [ ] Confirm the trycloudflare URL sticky comment lands on the PR
(posted by ci-privileged's `preview-env-comment`).
- [ ] Confirm a `preview-app` label on an external contributor PR
triggers the same flow.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

---
_Generated by [Claude
Code](https://claude.ai/code/session_01VqZBvafHqdCGtHZUT216C5)_

<!-- This is an auto-generated description by cubic. -->
<a
href="https://cubic.dev/pr/twentyhq/twenty/pull/22245?utm_source=github"
target="_blank" rel="noopener noreferrer"
data-no-image-dialog="true"><picture><source
media="(prefers-color-scheme: dark)"
srcset="https://www.cubic.dev/buttons/review-in-cubic-dark.svg"><source
media="(prefers-color-scheme: light)"
srcset="https://www.cubic.dev/buttons/review-in-cubic-light.svg"><img
alt="Review in cubic"
src="https://www.cubic.dev/buttons/review-in-cubic-dark.svg"></picture></a>
<!-- End of auto-generated description by cubic. -->
2026-06-27 11:14:58 +02:00
Paul Rastoin d5c7b735d2 ci: migrate cross-repo dispatch senders to workflow_dispatch (actions:write) (#21648)
# Introduction
Getting rid of the fine grained PAT used to dispatch to internal
repositories.
Repo dispatch requires the contents write permissions which is too wide
for such use
Refactored all senders and target to pass through a workflow dispatch
instead
Creating a centralize app that forges a token with actions: write only
provided permissions to mitigate any token exfiltrations
2026-06-16 15:18:43 +02:00
Charles Bochet 2f4ebf8160 Move preview environment workflow to ci-privileged (#20872)
## Summary

Slims `preview-env-dispatch.yaml` to a single dispatch and deletes
`preview-env-keepalive.yaml`. The actual preview-env work moves to
**twentyhq/ci-privileged#22** (must merge as a pair).

## Why

Context: PR #20867 was a credential-exfil attempt against our workflows.
GitHub's default fork-PR-no-secrets policy + our existing gates
(`author_association` checks, `pull_request_target` checking out base,
`enableScripts: false`) neutralized the actual attack — but the audit
surfaced one workflow that *would* have given a malicious external PR
access to a real secret if a maintainer had applied the `preview-app`
label: `preview-env-keepalive.yaml`.

That workflow checked out the PR head SHA, did `docker login` with
`DOCKERHUB_PASSWORD`, then ran the PR's `docker-compose.yml`. A
malicious compose could have mounted `~/.docker/config.json` and
exfiltrated the Dockerhub credential.

After this PR, that workflow lives in `twentyhq/ci-privileged` instead,
paired with a rename of the credential to `DOCKERHUB_RO_TOKEN`
(Dockerhub PAT with `Public Repo Read-only` scope). A read-only PAT has
no exfiltration value — it's equivalent to anonymous Dockerhub access
plus rate-limit headroom — so the credential lives safely on the runner
without further hygiene tricks.

## What this PR does

- **Modifies** `.github/workflows/preview-env-dispatch.yaml`:
- Single dispatch to `twentyhq/ci-privileged` (was: self-dispatch to
twenty for the env + a separate dispatch to ci-privileged for the PR
comment).
  - `permissions: {}` (was: `contents: write`).
  - Drops `preview-env-keepalive.yaml` from the path-trigger list.
- **Deletes** `.github/workflows/preview-env-keepalive.yaml`. The
207-line workflow now lives in
`twentyhq/ci-privileged/.github/workflows/preview-env.yaml`.

Net `twenty` repo change: **-204 lines / +3 lines**.

## Companion PR

twentyhq/ci-privileged#22 — adds the new `preview-env.yaml`, deletes the
now-redundant `post-preview-comment.yaml`.

## Secrets fallout in this repo

After this PR, `DOCKERHUB_PASSWORD` in `twentyhq/twenty` secrets is only
used by `ci-test-docker-compose.yaml`, where:
- It evaluates to empty for fork PRs (GitHub default — secrets aren't
passed to fork-PR workflows).
- It's only needed for internal / merge_queue runs, for Dockerhub
rate-limit headroom on base-image pulls.

Recommend (separate change): also convert the twenty-side
`DOCKERHUB_PASSWORD` to a `Public Repo Read-only` Dockerhub PAT, and
rename it to `DOCKERHUB_RO_TOKEN` for consistency with ci-privileged.
The workflow change for `ci-test-docker-compose.yaml` would just be a
rename — login flow is identical for password vs. PAT.

## Test plan

- [ ] Merge twentyhq/ci-privileged#22 first (so the dispatched event has
a handler)
- [ ] Open an internal PR touching `packages/twenty-docker/**`, confirm
`Preview Environment Dispatch` runs and ci-privileged's `Preview
Environment` workflow runs the docker compose + posts the URL
- [ ] On an external contributor PR, apply the `preview-app` label,
confirm the same flow
- [ ] Confirm closing the PR doesn't break (no cleanup workflow was
changed)
2026-05-23 11:37:37 +00:00
Félix Malfait c002bc52bd fix(ci): repair preview-environment dispatch (use PAT, not GITHUB_TOKEN) (#20773)
## What
One-line token swap on the same-repo dispatch step in
[`preview-env-dispatch.yaml`](.github/workflows/preview-env-dispatch.yaml#L40):
`secrets.GITHUB_TOKEN` → `secrets.CI_PRIVILEGED_DISPATCH_TOKEN`.

## Why
Regression from [#20476](https://github.com/twentyhq/twenty/pull/20476)
("security: harden CI against supply-chain attacks"), merged 2026-05-12.
That PR replaced

```yaml
uses: peter-evans/repository-dispatch@v2
with:
  token: ${{ secrets.GITHUB_TOKEN }}
  ...
```

with a raw `gh api` call but kept `GITHUB_TOKEN`:

```yaml
env:
  GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
  gh api repos/"$REPOSITORY"/dispatches -f event_type=preview-environment ...
```

The auto-provisioned `GITHUB_TOKEN` can't fire `repository_dispatch` via
`gh api` even when the workflow declares `permissions: contents: write`.
The action used a different code path that worked; the CLI requires a
token with `repo` scope. So every dispatch from this workflow has
returned `403 Resource not accessible by integration` since that PR
merged — except for runs the `author_association` / `preview-app` label
gate skips entirely (which then show "success" because no jobs ran).

Recent failed example:
https://github.com/twentyhq/twenty/actions/runs/26162974597/job/76959379235?pr=20769

## The fix
`secrets.CI_PRIVILEGED_DISPATCH_TOKEN` already exists in repo secrets
and is **already used** by the immediately-following cross-repo dispatch
step in the same file. Using it for the same-repo dispatch too matches
the surrounding code and is consistent with the original hardening
intent (use a scoped PAT, not the auto-provisioned token).

## Test plan
- [ ] Merge this PR
- [ ] Next PR open / sync / reopen on a member's branch → check that
`Preview Environment Dispatch` succeeds (no 403)
- [ ] Confirm `Preview Environment Keep Alive` workflow gets triggered
(the downstream effect of the dispatch)
- [ ] Confirm the tunnel URL sticky comment lands on the PR

Discovered while testing an unrelated PR
([#20762](https://github.com/twentyhq/twenty/pull/20762)). Independent
fix.
2026-05-20 14:57:57 +02:00
neo773 565995e715 security: harden CI against supply-chain attacks (#20476)
- Pin all third-party actions to SHA
- Gate claude.yml triggers to internal authors with Harden-Runner egress
audit
- Ignore fork-PR lifecycle scripts
- Narrow cross-repo dispatch payloads
- Add 7d npm release-age gate
- Add CODEOWNERS on .github/** and .yarnrc.yml

---------

Co-authored-by: prastoin <paul@twenty.com>
2026-05-12 12:20:29 +00:00
Charles Bochet d48c58640c Migrate CI runners from Depot back to GitHub-hosted runners (#18347)
## Summary
- Replaces all `depot-ubuntu-24.04` runners with `ubuntu-latest`
- Replaces all `depot-ubuntu-24.04-8` runners with
`ubuntu-latest-8-cores`
- Updates storybook build cache keys in ci-front.yaml to reflect the
runner name change

Reverts the temporary Depot migration introduced in #18163 / #18179
across all 23 workflow files.
2026-03-03 14:14:27 +01:00
Félix Malfait 2a5b2746c9 Fix preview-env-dispatch: repository_dispatch requires contents:write
The `repository_dispatch` API endpoint requires `contents: write`
permission on the GITHUB_TOKEN, not `actions: write`. Our security
hardening PR inadvertently changed this to `contents: read`, breaking
the self-dispatch to the keepalive workflow.

Made-with: Cursor
2026-03-02 11:25:14 +01:00
Félix Malfait 0223975bbd Harden GitHub Actions: fix injections, isolate privileged operations to ci-privileged repo (#18318)
## Summary

- Fix expression injection vulnerabilities in composite actions
(`restore-cache`, `nx-affected`) and workflow files (`claude.yml`)
- Reduce overly broad permissions in `ci-utils.yaml` (Danger.js) and
`ci-breaking-changes.yaml`
- Restructure `preview-env-dispatch.yaml`: auto-trigger for members,
opt-in for contributor PRs via `preview-app` label (safe because
keepalive has no write tokens)
- Isolate all write-access operations (PR comments, cross-repo posting)
to a new dedicated
[`twentyhq/ci-privileged`](https://github.com/twentyhq/ci-privileged)
repo via `repository_dispatch`, so that workflows in twenty that execute
contributor code never have write tokens
- Create `post-ci-comments.yaml` (`workflow_run` bridge) to dispatch
breaking changes results to ci-privileged, solving the [fork PR comment
issue](https://github.com/twentyhq/twenty/pull/13713#issuecomment-3168999083)
- Delete 5 unused secrets and broken `i18n-qa-report` workflow
- Remove `TWENTY_DISPATCH_TOKEN` from twenty (moved to ci-privileged as
`CORE_TEAM_ISSUES_COMMENT_TOKEN`)
- Use `toJSON()` for all `client-payload` values to prevent JSON
injection

## Security model after this PR

| Workflow | Executes fork code? | Write tokens available? |
|----------|---------------------|------------------------|
| preview-env-keepalive | Yes | None (contents: read only) |
| preview-env-dispatch | No (base branch) | CI_PRIVILEGED_DISPATCH_TOKEN
only |
| ci-breaking-changes | Yes | None (contents: read only) |
| post-ci-comments (workflow_run) | No (default branch) |
CI_PRIVILEGED_DISPATCH_TOKEN only |
| claude.yml | No (base branch) | CI_PRIVILEGED_DISPATCH_TOKEN,
CLAUDE_CODE_OAUTH_TOKEN |
| ci-utils (Danger.js) | No (base branch) | GITHUB_TOKEN (scoped) |

All actual write tokens (`TWENTY_PR_COMMENT_TOKEN`,
`CORE_TEAM_ISSUES_COMMENT_TOKEN`) live in `twentyhq/ci-privileged` with
strict CODEOWNERS review and branch protection.

## Test plan

- [ ] Verify preview environment comments still appear on member PRs
- [ ] Verify adding `preview-app` label triggers preview for contributor
PRs
- [ ] Verify breaking changes reports still post on PRs (including fork
PRs)
- [ ] Verify Claude cross-repo responses still post on core-team-issues
- [ ] Confirm ci-privileged branch protection is enforced
2026-03-02 10:57:14 +01:00
Charles Bochet 129d1ede86 Change runners temp (#18163)
Temporarily moving all ubuntu-latest 1 core to depot except ci-website
2026-02-23 10:53:31 +01:00
Antoine Moreaux 93d55d1bc2 chore(workflows): update permissions across GitHub Actions workflows … (#14919)
…for consistency
2025-10-06 17:36:41 +02:00
Félix Malfait 51f7f55b9d Fix condition for preview apps (#11933)
Followup after https://github.com/twentyhq/twenty/pull/11869

We do want to launch previews on every PR. The label is just there to
force a re-launch
2025-05-07 21:27:53 +02:00
Paul Rastoin c9eff401df Preview env dispatch using -paths syntax (#11869)
# Introduction
Using changed-files from a forked repo with `pull_request_target`
results in invalid checkout issue
Used the native paths GitHub Actions syntax to handle workflow
triggering

[Paths
syntax](https://docs.github.com/en/actions/writing-workflows/workflow-syntax-for-github-actions#onpushpull_requestpull_request_targetpathspaths-ignore)
2025-05-05 14:30:16 +02:00
Paul Rastoin ea0f45e782 Scope permissions to dispatch reusable workflow invokation (#11843)
# Introduction

Fixes `preview-dispatch` for external contributors such as this run 
FAILING =
https://github.com/twentyhq/twenty/actions/runs/14796579485/job/41545030774
NOW SUCCEEDING =
https://github.com/twentyhq/twenty/actions/runs/14797811684?pr=11827
2025-05-02 17:32:49 +02:00
Félix Malfait e55ff5ac4a Change workflow dispatch permissions (#11812)
It seems that content: write is needed so that external contributors can
dispatch workflows
2025-04-30 13:06:57 +02:00
Félix Malfait 6343eaeb4f Change workflow preview env to pull_request_target (#11810)
It didn't work with external contributors
2025-04-30 12:31:56 +02:00
Félix Malfait 535a8d4410 Fix workflow preview environment repository dispatch (#11739)
This is hard to test without merging PRs unfortunately

Goal of this PR is to replace the action I had introduced since there
was already a similar one in the codebase
2025-04-25 15:52:12 +02:00
Félix Malfait 3fc498dba7 Attempt to add preview environments (#11734)
Just doing a quick test
2025-04-25 15:42:40 +02:00