Skip to content

feat: add shared Product Pulse composite action [ED-24831]#42

Merged
Ntnelbaba merged 8 commits into
mainfrom
feat/ED-24831-add-product-pulse-action
Jul 14, 2026
Merged

feat: add shared Product Pulse composite action [ED-24831]#42
Ntnelbaba merged 8 commits into
mainfrom
feat/ED-24831-add-product-pulse-action

Conversation

@annab1

@annab1 annab1 commented Jul 12, 2026

Copy link
Copy Markdown
Contributor

Summary

  • Adds actions/product-pulse, a composite action that centralizes the AI-driven product pulse workflow (Cursor Agent generation + Slack notification) previously duplicated in elementor and elementor-pro
  • The generic prompt (goal, decision criteria, type classification, writing style, output format, examples) was ~85% byte-identical between the two repos' product-pulse-prompt.md files, so it now lives here in prompt-template.md
  • Callers just pass a product-name (e.g. "Elementor" or "Elementor Pro") plus Cursor/Slack credentials; render-prompt.py substitutes it into the shared template. No per-file-path product-area detection — every pulse from a given repo is tagged with that repo's product name
  • Includes fixes already reviewed on the elementor-pro port: safe printf '%s' handling for %-containing diffs, and passing the (up to 500KB) prompt via file instead of a CLI argument to avoid ARG_MAX issues
  • Adds change-type-aware Slack header (feature/fix/improvement/internal) and a PR + Jira link footer

Follow-up

Test plan

  • Merge this PR before merging the elementor-pro/elementor follow-ups (their workflows reference @main)
  • Confirm a merged feature/fix PR in either repo still posts to Slack with the right product name and type-based header
  • Confirm a chore-only PR still skips without posting

Jira

ED-24831

Made with Cursor

✨ PR Description

1. Problem & Context

Introduces a reusable Product Pulse composite action (ED-24831) to share PR-to-Slack notification logic across Elementor repos. Uses Cursor Agent AI to classify merged PRs as product-facing and generates user-friendly pulse updates.

2. What Changed (Where)

File Change
actions/product-pulse/action.yml New composite action: fetches PR data, invokes Cursor Agent, parses JSON output, posts to Slack with rich formatting
actions/product-pulse/scripts/extract-pulse-json.py Utility to extract valid JSON object from AI output noise
actions/product-pulse/scripts/render-prompt.py Template renderer substituting product name into shared prompt
actions/product-pulse/prompt-template.md Shared decision criteria + writing style guide for AI (skip logic, classification types, examples)
actions/product-pulse/README.md Usage docs and input spec
actions/setup-elementor-env/main.ts Changed validate plugin is-active to activate plugin — proactive instead of reactive
.github/workflows/test-actions.yml Bumped WP from 6.6 → 7.0.1

3. How It Works

Workflow: checkout → fetch PR+diff → install Cursor CLI → render prompt with product name → invoke Cursor Agent with 5min timeout → extract JSON (skip/title/description/type/reason) → parse Slack context (Loom, Jira URLs) → post formatted block message or error notification on failure. Handles parse failures gracefully by trying raw output, then Python extractor, then exit with error.

4. Risks

AI output parsing fragile if Cursor Agent returns wrapped JSON or malformed structure—mitigated by extract-pulse-json.py fallback and timeout handling. Slack integration silent-fails with continue-on-error: true, masking delivery issues. No rate limiting on Slack API calls.

Generated by LinearB AI and added by gitStream.
AI-generated content may contain inaccuracies. Please verify before using.
💡 Tip: You can customize your AI Description using Guidelines Learn how

Centralizes the product-pulse logic (Cursor Agent generation, JSON
parsing, Slack notification) so elementor and elementor-pro can share
one implementation instead of maintaining duplicate ~300-line workflows.
Callers keep their own repo-specific product-area prompt and pass it
in via the prompt-file input.

Ref: ED-24831
Co-authored-by: Cursor <cursoragent@cursor.com>
Comment thread actions/product-pulse/action.yml Fixed
Comment thread actions/product-pulse/action.yml Fixed
Comment thread actions/product-pulse/action.yml Fixed
Comment thread actions/product-pulse/action.yml Fixed
Comment thread actions/product-pulse/action.yml Fixed
Comment thread actions/product-pulse/action.yml Fixed
Comment thread actions/product-pulse/action.yml Fixed
Comment thread actions/product-pulse/action.yml Fixed
Comment thread actions/product-pulse/action.yml Fixed
Comment thread actions/product-pulse/action.yml Fixed
Move ${{ }} expressions (inputs.pr-number, github.action_path,
steps.update.outputs.*, github.event.pull_request.html_url) out of
inline run: script bodies and into env: blocks, addressing CodeQL
code-injection findings in the product-pulse action.

Ref: ED-24831
Co-authored-by: Cursor <cursoragent@cursor.com>
Moves the ~85% of the prompt that was byte-identical between
elementor and elementor-pro (goal, decision criteria, type
classification, writing style, output format, examples, edge
cases) into prompt-template.md, owned by this action.

Callers now only supply a small product-areas-file with the three
things that genuinely differ per repo: PRODUCT_NAME, the
PRODUCT_AREAS file-path mapping, and the PRODUCT_ENUM list. A new
render-prompt.py substitutes these into the shared template before
it's handed to Cursor Agent. Replaces the prompt-file/default-product
inputs accordingly.

Ref: ED-24831
Co-authored-by: Cursor <cursoragent@cursor.com>
…name

Per-repo file-path -> product-area mapping was more granularity than
needed for a Slack pulse feed. The product field is now always the
calling repo's name (e.g. "Elementor" or "Elementor Pro"), passed as
a plain product-name input instead of a product-areas-file.

This removes the whole Product Area Detection section from the shared
prompt, drops the AI's product classification (and its validation),
and lets callers drop their per-repo areas file entirely.

Ref: ED-24831
Co-authored-by: Cursor <cursoragent@cursor.com>
annab1 added a commit to elementor/elementor that referenced this pull request Jul 13, 2026
The shared action (elementor/elementor-editor-github-actions#42) no
longer detects a per-file product area - it just tags every pulse
with the calling repo's product name. Passes 'Elementor' directly
instead of maintaining a product-pulse-areas.md mapping file.

Ref: ED-24831
Co-authored-by: Cursor <cursoragent@cursor.com>
Adds a "Get build artifact link" step that looks up the most recent
successful run of the caller repo's Build workflow (build.yml) for
the PR's head SHA, resolves its uploaded artifact, and appends a
"Build Artifact" link to the Slack notification footer alongside the
PR # and Jira ticket links. Skips gracefully if no matching run or
artifact is found.

Ref: ED-24831
Co-authored-by: Cursor <cursoragent@cursor.com>
Ntnelbaba
Ntnelbaba previously approved these changes Jul 14, 2026
@annab1 annab1 changed the title feat: Add shared Product Pulse composite action [ED-24831] eat: Add shared Product Pulse composite action [ED-24831] Jul 14, 2026
@annab1 annab1 changed the title eat: Add shared Product Pulse composite action [ED-24831] Feat: Add shared Product Pulse composite action [ED-24831] Jul 14, 2026
@annab1 annab1 changed the title Feat: Add shared Product Pulse composite action [ED-24831] feat: add shared Product Pulse composite action [ED-24831] Jul 14, 2026
Ref: ED-24831
Co-authored-by: Cursor <cursoragent@cursor.com>
annab1 and others added 2 commits July 14, 2026 16:35
…ng it

wp-env installs the Elementor plugin but does not reliably auto-activate
it, causing the Performance flow CI job to fail intermittently at the
"Validating elementor being activated" step. Actively activate the
plugin (idempotent) instead of just checking its state.

Cherry-picked from ED-24451 (5444eeb).

Co-authored-by: Cursor <cursoragent@cursor.com>
Elementor's latest release requires WordPress 6.8+ ("Current WordPress
version (6.6) does not meet minimum requirements for Elementor"), so the
Performance flow job's plugin activation was silently failing even
though wp-env reported the plugin as active. Pin to the current stable
core (7.0.1) instead of the outdated 6.6.

Co-authored-by: Cursor <cursoragent@cursor.com>

@Ntnelbaba Ntnelbaba left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The bundled JS can be removed by moving to latest node version, but this is not critical ATM

@Ntnelbaba
Ntnelbaba merged commit 882cb43 into main Jul 14, 2026
16 checks passed
@Ntnelbaba
Ntnelbaba deleted the feat/ED-24831-add-product-pulse-action branch July 14, 2026 14:17
annab1 added a commit to elementor/elementor that referenced this pull request Jul 15, 2026
…s [ED-24831] (#36486)

## Summary
- Replaces this repo's inline product-pulse workflow (merged in #36412,
still on the unpatched version) with a thin caller of
`elementor/elementor-editor-github-actions/actions/product-pulse` — see
[elementor/elementor-editor-github-actions#42](elementor/elementor-editor-github-actions#42)
- The generic prompt (goal, decision criteria, type classification,
writing style, output format, examples) now lives in that action's
shared `prompt-template.md`, since it was ~85% byte-identical to
elementor-pro's copy
- Passes `product-name: 'Elementor'` directly — no per-file-path
product-area mapping; every pulse from this repo is simply tagged
"Elementor"
- Removes `.github/extract-pulse-json.py` (now lives in the shared
action's `scripts/`)
- Companion PR in elementor-pro:
[elementor/elementor-pro#7275](elementor/elementor-pro#7275)

## Test plan
- [ ] Merge a chore-only PR after this lands and confirm no Slack pulse
is posted
- [ ] Merge a feature/fix PR and confirm the Slack pulse fires tagged
"Elementor" with the correct type-based header
- [ ] Verify `elementor/elementor-editor-github-actions#42` is merged
before merging this PR (the `@main` ref must resolve)

<!--start_gitstream_placeholder-->
### ✨ PR Description
## 1. Problem & Context
Extracting product pulse logic into a shared reusable GitHub Action
(ED-24831) reduces duplication and maintenance burden across Elementor
repositories.

## 2. What Changed (Where)
* `.github/workflows/product-pulse.yml`: Replaced 270+ lines of inline
bash/script logic with single composable action call; added `actions:
read` permission
* `.github/extract-pulse-json.py`: Removed (logic now encapsulated in
shared action)

## 3. How It Works
Workflow now delegates entire pipeline to
`elementor/elementor-editor-github-actions/actions/product-pulse@main`
via single step, passing PR metadata and secrets as inputs. Shared
action owns PR fetching, Cursor API calls, JSON parsing, and Slack
notifications.

## 4. Risks
Action availability: shared action repo must stay stable/accessible.
Credential management: ensure `elementor-editor-github-actions` repo has
equivalent secret handling. No rollback plan if shared action
breaks—mitigate with pinning to specific commit hash instead of `@main`.

_Generated by LinearB AI and added by gitStream._
<sub>AI-generated content may contain inaccuracies. Please verify before
using.
💡 **Tip:** You can customize your AI Description using **Guidelines**
[Learn
how](https://docs.gitstream.cm/automation-actions/#describe-changes)</sub>
<!--end_gitstream_placeholder-->

---------

Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Netanel Baba <50736016+Ntnelbaba@users.noreply.github.com>
Co-authored-by: ElementorBot <48412871+elementorbot@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants