-
Notifications
You must be signed in to change notification settings - Fork 13.9k
ci: publish PR UI previews to ghcr.io for Rocket.Chat Desktop #42364
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
730ba04
abe885e
0c6a3cf
3797795
760b6b6
329a420
266fbca
e38ea69
eb79e9c
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||
|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,196 @@ | ||||||||
| name: UI Preview | ||||||||
|
|
||||||||
| # Builds the standalone web client for a PR (or develop) and publishes it to ghcr.io, where Rocket.Chat Desktop | ||||||||
| # pulls it anonymously (`rocketchat://ui-preview?pr=<number>`). A PR's preview is removed with its label or on close. | ||||||||
| on: | ||||||||
| push: | ||||||||
| branches: [develop] | ||||||||
| paths: | ||||||||
| - 'apps/meteor/client/**' | ||||||||
| - 'apps/meteor/app/**' | ||||||||
| - 'apps/meteor/ee/client/**' | ||||||||
| - 'apps/meteor/public/**' | ||||||||
| - 'apps/meteor/vite/**' | ||||||||
| - 'packages/**' | ||||||||
| - 'ee/packages/**' | ||||||||
| - 'yarn.lock' | ||||||||
| # No path filter: it would also gate `unlabeled`/`closed`, leaving a preview behind. The `preview` label gates builds. | ||||||||
| pull_request: | ||||||||
| types: [opened, synchronize, reopened, labeled, unlabeled, closed] | ||||||||
|
|
||||||||
| concurrency: | ||||||||
| # Adding or removing any other label must not cancel a preview build in progress. | ||||||||
| group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}${{ (github.event.action == 'labeled' || github.event.action == 'unlabeled') && github.event.label.name != 'preview' && format('-{0}', github.run_id) || '' }} | ||||||||
| cancel-in-progress: true | ||||||||
|
|
||||||||
| env: | ||||||||
| TOOL_NODE_FLAGS: ${{ vars.TOOL_NODE_FLAGS }} | ||||||||
| IMAGE: ghcr.io/rocketchat/rocket.chat-web | ||||||||
|
|
||||||||
| permissions: {} | ||||||||
|
|
||||||||
| jobs: | ||||||||
| build: | ||||||||
| name: Build UI preview | ||||||||
| # Opt-in through the `preview` label. Publishing needs CR_PAT, which fork and Dependabot PRs do not receive. | ||||||||
| if: >- | ||||||||
| github.event_name == 'push' || ( | ||||||||
| contains(github.event.pull_request.labels.*.name, 'preview') && | ||||||||
| github.event.action != 'unlabeled' && github.event.action != 'closed' && | ||||||||
| (github.event.action != 'labeled' || github.event.label.name == 'preview') && | ||||||||
| github.event.pull_request.head.repo.full_name == github.repository && | ||||||||
| github.actor != 'dependabot[bot]' | ||||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. P2: Prompt for AI agents
Suggested change
|
||||||||
| ) | ||||||||
| runs-on: ubuntu-24.04-arm | ||||||||
| permissions: | ||||||||
| contents: read | ||||||||
|
|
||||||||
| steps: | ||||||||
| - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 | ||||||||
|
|
||||||||
| - name: Setup NodeJS | ||||||||
| uses: ./.github/actions/setup-node | ||||||||
| with: | ||||||||
| cache-modules: true | ||||||||
| install: true | ||||||||
|
|
||||||||
| - uses: rharkor/caching-for-turbo@2238fae6eb9a9936f92356f54cb3660200d105e7 # v2.5.1 | ||||||||
|
|
||||||||
| # Same package set `yarn dev:next` builds against a remote server. | ||||||||
| - name: Build packages the client reads from dist | ||||||||
| run: | | ||||||||
| mapfile -t filters < <(node --input-type=module -e " | ||||||||
| import { distOnlyWorkspacePackages, publicAssetWorkspacePackages } from './apps/meteor/vite/workspacePackages.mjs'; | ||||||||
| console.log([...distOnlyWorkspacePackages, ...publicAssetWorkspacePackages].map((name) => '--filter=' + name + '...').join('\n')); | ||||||||
| ") | ||||||||
| yarn turbo run build "${filters[@]}" | ||||||||
|
|
||||||||
| - name: Build standalone client | ||||||||
| run: yarn workspace @rocket.chat/meteor build:vite | ||||||||
|
|
||||||||
| - name: Package bundle | ||||||||
| run: | | ||||||||
| mkdir -p ui-preview | ||||||||
| # The rest of dist/ is public/, which the Rocket.Chat server already serves. | ||||||||
| tar --format=ustar -czf ui-preview/ui-preview.tar.gz -C apps/meteor/vite/dist index.html bundle | ||||||||
| du -h ui-preview/ui-preview.tar.gz | ||||||||
|
|
||||||||
| - uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2 | ||||||||
| with: | ||||||||
| name: ui-preview | ||||||||
| path: ui-preview | ||||||||
| retention-days: 3 | ||||||||
|
|
||||||||
| # Kept apart from the build so the job holding CR_PAT never runs the PR's code. | ||||||||
| publish: | ||||||||
| name: Publish UI preview | ||||||||
| needs: build | ||||||||
| runs-on: ubuntu-24.04-arm | ||||||||
| permissions: | ||||||||
| pull-requests: write | ||||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. P1: Prompt for AI agents
Suggested change
|
||||||||
|
|
||||||||
| steps: | ||||||||
| - uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 | ||||||||
| with: | ||||||||
| name: ui-preview | ||||||||
| path: ui-preview | ||||||||
|
|
||||||||
| - uses: oras-project/setup-oras@1d808f7d7f6995cc68b7bf507bfe5c5446e1dc9d # v2.0.1 | ||||||||
|
|
||||||||
| - name: Push to ghcr.io | ||||||||
| env: | ||||||||
| CR_USER: ${{ secrets.CR_USER }} | ||||||||
| CR_PAT: ${{ secrets.CR_PAT }} | ||||||||
| NUMBER: ${{ github.event.pull_request.number }} | ||||||||
| HEAD_SHA: ${{ github.event.pull_request.head.sha || github.sha }} | ||||||||
| REPO: ${{ github.repository }} | ||||||||
| run: | | ||||||||
| # `pr-<n>-<sha>` keeps every build of a PR findable after `pr-<n>` moves on, so cleanup can remove them all. | ||||||||
| if [ -n "$NUMBER" ]; then tags="pr-$NUMBER,pr-$NUMBER-$HEAD_SHA,$HEAD_SHA"; else tags=develop; fi | ||||||||
| echo "$CR_PAT" | oras login ghcr.io -u "$CR_USER" --password-stdin | ||||||||
| cd ui-preview | ||||||||
| oras push "$IMAGE:$tags" \ | ||||||||
| --artifact-type application/vnd.rocketchat.ui-preview.v1 \ | ||||||||
| --annotation "org.opencontainers.image.source=https://github.com/$REPO" \ | ||||||||
| --annotation "org.opencontainers.image.revision=$HEAD_SHA" \ | ||||||||
| ui-preview.tar.gz:application/vnd.oci.image.layer.v1.tar+gzip | ||||||||
|
|
||||||||
| - name: Delete superseded develop builds | ||||||||
| if: github.event_name == 'push' | ||||||||
| env: | ||||||||
| GH_TOKEN: ${{ secrets.CR_PAT }} | ||||||||
| PACKAGE: /orgs/${{ github.repository_owner }}/packages/container/rocket.chat-web/versions | ||||||||
| run: | | ||||||||
| # List every page before deleting, or deletions shift the pages still to be read. | ||||||||
| ids=$(gh api --paginate "$PACKAGE" -q '.[] | select(.metadata.container.tags == []) | .id') | ||||||||
| printf '%s' "$ids" | xargs -r -I{} gh api -X DELETE "$PACKAGE/{}" | ||||||||
|
|
||||||||
| - name: Comment on PR | ||||||||
| if: github.event_name == 'pull_request' | ||||||||
| env: | ||||||||
| GH_TOKEN: ${{ github.token }} | ||||||||
| REPO: ${{ github.repository }} | ||||||||
| NUMBER: ${{ github.event.pull_request.number }} | ||||||||
| HEAD_SHA: ${{ github.event.pull_request.head.sha }} | ||||||||
| run: | | ||||||||
| marker='<!-- ui-preview -->' | ||||||||
| body="$marker | ||||||||
| ### 🖥️ UI preview | ||||||||
|
|
||||||||
| Built from \`${HEAD_SHA:0:7}\` and published to \`$IMAGE:pr-$NUMBER\`. | ||||||||
|
|
||||||||
| In Rocket.Chat Desktop with **Developer Mode** on, open one of these links to load this PR's UI into the workspace in focus: | ||||||||
|
|
||||||||
| | | | | ||||||||
| |---|---| | ||||||||
| | Latest build of this PR | \`rocketchat://ui-preview?pr=$NUMBER\` | | ||||||||
| | This exact build | \`rocketchat://ui-preview?pr=$NUMBER&sha=$HEAD_SHA\` | | ||||||||
|
|
||||||||
| To pick the workspace, add \`&host=https://your.server\`. Use **View > Restore server UI**, or restart the app, to go back." | ||||||||
|
|
||||||||
| comment_id=$(gh api "repos/$REPO/issues/$NUMBER/comments" --paginate -q ".[] | select(.body | startswith(\"$marker\")) | .id" | head -n1) | ||||||||
| if [ -n "$comment_id" ]; then | ||||||||
| gh api -X PATCH "repos/$REPO/issues/comments/$comment_id" -f body="$body" | ||||||||
| else | ||||||||
| gh api "repos/$REPO/issues/$NUMBER/comments" -f body="$body" | ||||||||
| fi | ||||||||
|
|
||||||||
| remove: | ||||||||
| name: Remove UI preview | ||||||||
| if: >- | ||||||||
| github.event_name == 'pull_request' && | ||||||||
| github.event.pull_request.head.repo.full_name == github.repository && ( | ||||||||
| (github.event.action == 'unlabeled' && github.event.label.name == 'preview') || | ||||||||
| (github.event.action == 'closed' && contains(github.event.pull_request.labels.*.name, 'preview')) | ||||||||
| ) | ||||||||
| runs-on: ubuntu-24.04-arm | ||||||||
| permissions: | ||||||||
| pull-requests: write | ||||||||
|
|
||||||||
| steps: | ||||||||
| - name: Delete from ghcr.io | ||||||||
| env: | ||||||||
| GH_TOKEN: ${{ secrets.CR_PAT }} | ||||||||
| PACKAGE: /orgs/${{ github.repository_owner }}/packages/container/rocket.chat-web/versions | ||||||||
| NUMBER: ${{ github.event.pull_request.number }} | ||||||||
| run: | | ||||||||
| ids=$(gh api --paginate "$PACKAGE" \ | ||||||||
| -q ".[] | select(any(.metadata.container.tags[]; . == \"pr-$NUMBER\" or startswith(\"pr-$NUMBER-\"))) | .id") | ||||||||
| printf '%s' "$ids" | xargs -r -I{} gh api -X DELETE "$PACKAGE/{}" | ||||||||
|
|
||||||||
| - name: Update PR comment | ||||||||
| env: | ||||||||
| GH_TOKEN: ${{ github.token }} | ||||||||
| REPO: ${{ github.repository }} | ||||||||
| NUMBER: ${{ github.event.pull_request.number }} | ||||||||
| run: | | ||||||||
| marker='<!-- ui-preview -->' | ||||||||
| body="$marker | ||||||||
| ### 🖥️ UI preview | ||||||||
|
|
||||||||
| Removed from \`$IMAGE\`. Add the \`preview\` label again to publish a new one." | ||||||||
|
|
||||||||
| comment_id=$(gh api "repos/$REPO/issues/$NUMBER/comments" --paginate -q ".[] | select(.body | startswith(\"$marker\")) | .id" | head -n1) | ||||||||
| if [ -n "$comment_id" ]; then | ||||||||
| gh api -X PATCH "repos/$REPO/issues/comments/$comment_id" -f body="$body" | ||||||||
| fi | ||||||||
Uh oh!
There was an error while loading. Please reload this page.