Skip to content

FLEXY-6498 Dual Webpack (4 & 5) Support - #1164

Open
shyamasish-twilio wants to merge 52 commits into
mainfrom
FLEXY-6498
Open

shyamasish-twilio wants to merge 52 commits into
mainfrom
FLEXY-6498

Conversation

@shyamasish-twilio

@shyamasish-twilio shyamasish-twilio commented Sep 23, 2026 •

Copy link
Copy Markdown
Collaborator

Adds a parallel webpack 5 build/dev-server pipeline (@twilio/flex-plugin-webpack5) alongside the existing webpack 4 pipeline (@twilio/flex-plugin-webpack), selectable via a new --wp5 flag on build/start. Webpack 4 remains the default; nothing changes for existing plugins that don't pass the flag.

New package: @twilio/flex-plugin-webpack5

A new package mirroring flex-plugin-webpack's structure, built on webpack 5 (aliased as webpack5 in package.json so both majors coexist in one node_modules tree). Includes:

  • webpack.config.ts / webpack.dev.ts — static (shell) / JavaScript (plugin) / complete configurations, using fork-ts-checker-webpack-plugin@9 (upgraded from the v4 API used by webpack 4) with project-aware TypeScript resolution — prefers the target plugin's own installed TypeScript over the tool's bundled copy.
  • compiler.ts, devServer/{ipcServer,pluginServer,webpackDevServer}.ts — dev-server orchestration, IPC coordination between the "start flex" (host shell) and "start plugin" (JS bundle) sub-processes, mirroring webpack 4's architecture.
  • clientVariables.ts, prints/*, plugins/DelayRenderStaticPlugin.ts — supporting utilities.
  • Full test suite (40 tests, ipcServer, pluginServer, webpack.config, clientVariables).

CLI / orchestration changes

  • plugin-flex/src/commands/flex/plugins/{build,start}.ts: new --wp5 boolean flag. start.ts now correctly propagates --wp5 to every spawned start sub-process — previously only the "flex" host shell received it, so the actual plugin bundle silently always built on webpack 4 regardless of the flag.
  • flex-plugin-scripts/src/scripts/{build,start}.ts: branch on --wp5 to run the webpack5 build/dev-server path (_runWebpack5, _startDevServerWp5) instead of the webpack 4 path.
  • flex-plugin-scripts/src/config/index.ts: new getConfigurationForWp5(), parallel to the existing getConfiguration(), resolving webpack/dev-server/jest configs from the wp5 package.
  • Sourcemap file-count fix: webpack 5's Stats schema nests a chunk's sourcemap inside that asset's own related array instead of listing it as an independent top-level asset (unlike webpack 4). Added _flattenAssetsWp5() in build.ts so the printed build summary correctly counts .map files.

E2E test coverage

Added a parallel Node 24 / webpack5 e2e suite alongside the existing Node 22/webpack4 one, without altering the latter's behavior:

  • flex-plugin-e2e-tests: scenario.wp5 (driven by WP5 env var) threads --wp5 through every build/start CLI invocation in the test steps.
  • ~reusable_e2e_all_OS.yaml / ~reusable_e2e_by_OS.yaml: new optional NODE_VERSION/WP5 inputs, defaulted to current behavior (additive only).
  • New e2e_scheduled_wp5.yaml (nightly) and pr_e2e_wp5.yaml (PR label-triggered), mirroring the existing scheduled/PR workflows on Node 24 with --wp5.

Requires manual setup outside this PR

pr_e2e_wp5.yaml references new repo/org GitHub Actions variables (E2E_WP5_LABEL, PUBLISH_AND_E2E_WP5_LABEL) and corresponding PR labels — these need to be created in repo settings before that workflow can trigger.

Test plan

  • npm run build at root — webpack 4 and webpack 5 paths both compile
  • twilio flex:plugins:build (default, webpack 4) — unchanged behavior
  • twilio flex:plugins:build --wp5 — builds via webpack 5, .js/.js.map both emitted and counted
  • twilio flex:plugins:start --wp5 — both "flex" and "plugin" sub-processes run on webpack 5
  • flex-plugin-webpack5 unit tests: 40/40 passing
  • Fresh npm install from clean node_modules succeeds without --force/--legacy-peer-deps
  • New e2e workflows validated (YAML syntax checked; live run pending label/var setup)

Contributing to Twilio

All third-party contributors acknowledge that any contributions they provide will be made under the same open-source license that the open-source project is provided under.

  • I acknowledge that all my contributions will be made under the project's license.

shyamasish-twilio and others added 6 commits June 11, 2025 14:53
# Conflicts:
#	lerna.json
#	package-lock.json
#	packages/flex-plugin-scripts/package.json
…2 suite

Adds a parallel e2e track (nightly scheduled + PR label-triggered) that
runs on Node 24 and builds/starts plugins with --wp5, without changing
the behavior of the existing Node 22/webpack4 suite.

- Thread scenario.wp5 (from WP5 env var) through build/start test steps
  to append --wp5 to the CLI invocations
- Add optional NODE_VERSION/WP5 inputs to the reusable e2e workflows,
  defaulting to current behavior so existing callers are unaffected
- Add e2e_scheduled_wp5.yaml (nightly) and pr_e2e_wp5.yaml (PR label)
  mirroring the existing scheduled/PR workflows

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
…lyTyped patch releases

An unbounded "@types/node": "*" wildcard pulled in by jest-circus can
resolve to a newest-on-registry @types/node patch release containing
TS-syntax that pre-TS5 compilers can't parse (e.g. ffi.d.ts's "const
type parameters"), crashing type-checking in scaffolded plugins.

- Pin an exact, verified-compatible @types/node version as a dependency
  (not devDependency, since only dependencies reach consumers) in
  flex-plugin-test, so its own nested copy stabilizes
- Disable TypeScript's automatic @types/* acquisition
  ("types": []) in the create-flex-plugin TS templates, since
  scaffolded plugins run in the browser and never reference Node
  globals - this narrows exposure to the wider class of unrelated
  @types/* packages breaking production type-checking

Note: this does not fully eliminate the crash for an already-scaffolded
project, since explicit `/// <reference types="node" />` directives in
other dependencies' bundled .d.ts files still resolve whichever
@types/node ends up hoisted to the project's own root node_modules,
which this change does not control.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Comment thread .github/workflows/pr_e2e_wp5.yaml Outdated
if: always()
runs-on: ubuntu-22.04
steps:
- uses: actions-ecosystem/action-remove-labels@v1

@semgrep-code-twilio semgrep-code-twilio Bot Sep 23, 2026 •

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

An action sourced from a third-party repository on GitHub is not pinned to a full length commit SHA. Pinning an action to a full length commit SHA is currently the only way to use an action as an immutable release. Pinning to a particular SHA helps mitigate the risk of a bad actor adding a backdoor to the action's repository, as they would need to generate a SHA-1 collision for a valid Git object payload.

🍰 Fixed in commit f3e2b54 🍰

Comment thread .github/workflows/pr_e2e_wp5.yaml Outdated
if: always()
runs-on: ubuntu-22.04
steps:
- uses: actions-ecosystem/action-remove-labels@v1

@semgrep-code-twilio semgrep-code-twilio Bot Sep 23, 2026 •

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

GitHub Actions step uses a mutable tag or branch reference. Tags and branch names can be silently repointed by the action owner, enabling supply-chain attacks — as seen in the trivy-action and kics-github-action compromises. Pin the reference to a full 40-character commit SHA instead, e.g. uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608.

🚀 Fixed in commit f3e2b54 🚀

Comment thread .github/workflows/pr_e2e_wp5.yaml Outdated
version: ${{ steps.alphaVersion.outputs.version }}
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v3

@semgrep-code-twilio semgrep-code-twilio Bot Sep 23, 2026 •

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

GitHub Actions step uses a mutable tag or branch reference. Tags and branch names can be silently repointed by the action owner, enabling supply-chain attacks — as seen in the trivy-action and kics-github-action compromises. Pin the reference to a full 40-character commit SHA instead, e.g. uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608.

⭐ Fixed in commit f3e2b54 ⭐

Comment thread .github/workflows/pr_e2e_wp5.yaml Outdated
branch: ${{ steps.extractBranch.outputs.branch }}
version: ${{ steps.alphaVersion.outputs.version }}
steps:
- uses: actions/checkout@v4

@semgrep-code-twilio semgrep-code-twilio Bot Sep 23, 2026 •

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

GitHub Actions step uses a mutable tag or branch reference. Tags and branch names can be silently repointed by the action owner, enabling supply-chain attacks — as seen in the trivy-action and kics-github-action compromises. Pin the reference to a full 40-character commit SHA instead, e.g. uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608.

🧁 Fixed in commit f3e2b54 🧁

shyamasish-twilio and others added 5 commits September 23, 2026 09:56
…allow-list policy

The org now enforces that workflow actions be pinned to a full-length
commit SHA (flex-monorepo's publish.yml, the only surviving GH Actions
workflow there post-enforcement, already does this). Every action
reference across the workflows was still using a floating version tag
(@V3, @v4, etc.), causing every PR-triggered workflow - including
pr_workflow.yaml, unrelated to this branch's other changes - to fail
at startup with "action not allowed".

- actions/checkout and actions/setup-node pinned to the exact SHAs
  flex-monorepo's publish.yml already uses successfully under this
  same policy (setup-node bumped v3 -> v6 to match, since only that
  SHA is confirmed to pass)
- actions/upload-artifact, actions/create-github-app-token pinned to
  current tag SHAs (GitHub-authored, same trust class as checkout/
  setup-node)
- codecov/codecov-action, rtCamp/action-slack-notify,
  actions-ecosystem/action-remove-labels pinned to current tag SHAs,
  but these are third-party and not confirmed on the org's allow-list -
  may still need an org admin to add them explicitly

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
The previously-pinned v3 SHA is a third-party action not on the org's
allow-list by name/version, so pinning alone didn't unblock it (unlike
actions/checkout and actions/setup-node, which are GitHub-authored and
passed once pinned). 0cfda1dd0a4ad9efc75517f399d859cd1ea4ced1 (v4.0.2)
is confirmed allow-listed.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
codecov/codecov-action is a third-party action not covered by any of
the org's GitHub Actions allow-list patterns, by name or SHA - pinning
to a specific commit (even a supposedly-approved one) still fails with
the same "action not allowed" error. Since there's no repo-level fix
for this (it requires an org admin to explicitly allow-list the
action), removing the step is the only way to unblock the check right
now. Coverage reporting can be re-added once codecov-action is
allow-listed.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
flex-monorepo's publish.yml (the only surviving GH Actions workflow
there post org-enforcement) runs on ubuntu-x64 rather than
ubuntu-22.04/ubuntu-latest. Align every Linux job across all workflows
to the same label for consistency; windows-latest/macos-latest in the
e2e OS matrix are unchanged since they're not Ubuntu runners.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
… runner labels

Root cause of the npm ci ETIMEDOUT failures: the org locked down direct/
implicit network access to the npm Artifactory proxy that npm ci relied
on, as part of the same enforcement wave that introduced the Actions
allow-list. Reaching it now requires exchanging the job's GitHub OIDC
token for a short-lived Artifactory access token first.

Ported and completed the pattern from the (unfinished) lockdown-migration
branch:
- Added .github/actions/artifactory-oidc, a composite action that
  exchanges the OIDC token for an Artifactory token and configures npm
  via ~/.npmrc. lockdown-migration authored this action but never
  actually wired it into any workflow step - added the missing
  `uses: ./.github/actions/artifactory-oidc` step before every npm ci,
  and the `permissions: id-token: write` each job needs to request the
  token.
- Adopted their runner-label split: `ubuntu-x64` for jobs that install
  and publish (pr_workflow.yaml build-and-test, both publish reusable
  workflows), `ubuntu-latest-large`/`macos-latest-large`/
  `windows-latest-large` for the e2e matrix and lightweight/skip jobs.
- Replaced rtCamp/action-slack-notify and actions-ecosystem/action-
  remove-labels with a plain curl POST / `gh pr edit --remove-label`,
  matching lockdown-migration - both are third-party actions outside
  the org's allow-list (same failure class as codecov-action, which
  stayed blocked even when pinned to a specific commit SHA).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Comment on lines +60 to +76
run: |
curl -X POST "${{ secrets.SLACK_WEB_HOOK }}" \
-H 'Content-Type: application/json' \
-d "{
\"username\": \"Github Actions\",
\"icon_emoji\": \":ship:\",
\"attachments\": [{
\"color\": \"${{ job.status == 'success' && 'good' || 'danger' }}\",
\"title\": \"Flex Plugins CLI\",
\"text\": \"🎉 Released a new version with *tag* \\\`${{ inputs.TAG }}\\\` and *version* \\\`${{ inputs.VERSION }}\\\`\",
\"actions\": [{
\"type\": \"button\",
\"text\": \"View Action\",
\"url\": \"${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}\"
}]
}]
}"

@semgrep-code-twilio semgrep-code-twilio Bot Sep 23, 2026 •

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🟠 High severity issue identified in your code:

Using variable interpolation ${{...}} with github context data in a run: step could allow an attacker to inject their own code into the runner. This would allow them to steal secrets and code. github context data can have arbitrary user input and should be treated as untrusted. Instead, use an intermediate environment variable with env: to store the data and use the environment variable in the run: script. Be sure to use double-quotes the environment variable, like this: "$ENVVAR".

🧼 Removed in commit c26f4f3 🧼

Comment on lines +200 to +223
run: |
STATUS_COLOR="good"
if [ "${{ needs.node.result }}" = "failure" ]; then
STATUS_COLOR="danger"
elif [ "${{ needs.node.result }}" = "cancelled" ]; then
STATUS_COLOR="warning"
fi

curl -X POST "${{ secrets.SLACK_WEB_HOOK }}" \
-H 'Content-Type: application/json' \
-d "{
\"username\": \"Github Actions\",
\"icon_emoji\": \":ship:\",
\"attachments\": [{
\"color\": \"${STATUS_COLOR}\",
\"title\": \"${{ inputs.SLACK_TITLE }} - ${{ inputs.OS }} - ${{ inputs.NODE_VERSION }}\",
\"text\": \"${{ github.repository }}/${{ github.ref }} - ${{ inputs.SLACK_MESSAGE }} ${{ needs.node.result }} for ${{ inputs.OS }}.\",
\"actions\": [{
\"type\": \"button\",
\"text\": \"View Action\",
\"url\": \"${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}\"
}]
}]
}"

@semgrep-code-twilio semgrep-code-twilio Bot Sep 23, 2026 •

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🟠 High severity issue identified in your code:

Using variable interpolation ${{...}} with github context data in a run: step could allow an attacker to inject their own code into the runner. This would allow them to steal secrets and code. github context data can have arbitrary user input and should be treated as untrusted. Instead, use an intermediate environment variable with env: to store the data and use the environment variable in the run: script. Be sure to use double-quotes the environment variable, like this: "$ENVVAR".

🎈 Fixed in commit c26f4f3 🎈

shyamasish-twilio and others added 5 commits September 24, 2026 01:37
…ne gate

The branch lockfile had 512 entries resolved to
npmjs.artifacts.twilio.com (picked up from a local registry config while
regenerating), which external consumers cannot install from. Rewrote them
to registry.npmjs.org; tarball paths and integrity hashes are unchanged.

CI still authenticates with Artifactory via the artifactory-oidc action,
which redirects npm through ~/.npmrc at build time only. Committed files
must always point at the public registry (ADR 1634 Rule 3b), matching the
lockfile-hygiene pattern in twilio-agent-connect-typescript:
- .github/scripts/lockfile-hygiene.sh fails if any tracked lockfile or
  .npmrc names a Twilio Artifactory host.
- .github/workflows/lockfile_hygiene.yaml runs that scan plus a clean-room
  npm ci against registry.npmjs.org only. No paths-ignore, so
  lockfile-only changes are still checked.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… probe ejs/rfc6902

With Artifactory OIDC auth working, npm ci now reaches twilio.jfrog.io but
JFrog curation (security-block-critical-cve-cvss-9-to-10) returns 403 for
several transitive packages. The retry loop swallowed the failure, so the
step passed and lint later ran a global lerna v10 against a missing
node_modules ("useWorkspaces option has been removed").

- Retry loops in pr_workflow and the e2e/publish reusable workflows now
  exit 1 after the third failed npm ci instead of silently continuing.
- Add npm overrides moving blocked packages to fixed versions:
  axios 0.31.1 (under @twilio/flex-ui, twilio-taskrouter, twilio; root
  axios 1.x unchanged), flatted 3.4.x, form-data 3.0.x under jsdom,
  handlebars 4.7.9, immutable 4.3.x, ip 2.0.1, lodash-es 4.18.x,
  lodash.template 4.18.x, proxy-addr 2.0.8. Bump flex-plugin-e2e-tests
  axios to ^0.31.1. Lockfile regenerated; all resolved URLs point at
  registry.npmjs.org.
- TEMPORARY: probe step reporting which ejs and rfc6902 versions curation
  allows. ejs (no upstream fix for CVE-2023-29827) and rfc6902 (fix only
  in 5.x) are still blocked and need a version decision or exception.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The earlier probe showed JFrog curation only allows ejs@6.0.1 and
rfc6902@5.x. Both are API-compatible with how they are used here
(@oclif/core and @nrwl/devkit only call ejs.render; twilio-chat only uses
applyPatch/createPatch/createTests), so override them. ejs 6 also drops
jake/filelist/async from the tree.

axios@0.31.1 (suggested by curation as the fix) is itself blocked, so the
suggested fix versions are not reliable. Replace the ejs/rfc6902-only
probe with a TEMPORARY script that scans every tarball in the lockfile
against the curated registry and probes candidate versions for each
overridden package, so all remaining blocks show up in one run.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The curation probe showed every axios 0.27.x-0.34.x (including the
suggested 0.31.1) is blocked; 0.26.1 is the only allowed 0.x release.
Pin the nested 0.x copies (@twilio/flex-ui, twilio-taskrouter, twilio)
and flex-plugin-e2e-tests' direct dependency to 0.26.1. Root axios 1.20.0
is allowed and unchanged. All other overridden packages were already on
allowed versions.

Type the style loaders and JS plugins arrays in the webpack5 config.
Under tsconfig.test.json (noImplicitAny: false) the untyped [] literals
were inferred as never[], failing webpack.config.test.ts in the full
test run and stopping bin/test.js before the remaining packages ran.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ipts coverage

With npm ci now passing, test:ci ran coverage thresholds for the first
time on this branch and flex-plugin-scripts failed them (statements/lines
91.83% < 94%, functions 91.76% < 92%): the webpack 5 paths added for
dual-webpack support had no tests.

- build.test.ts: --wp5 routing, _flattenAssetsWp5, _handlerWp5
  (error, compile errors, success), and _runWebpack/_runWebpack5 with a
  mocked webpack.
- start.test.ts: --wp5 routing in start (incl. process error handlers),
  _startDevServerWp5 (plugin server, IPC server/client, compiler
  callbacks, crash emit), _onServerCrashWp5,
  _getPluginsConfigurationWp5, _requirePackages.

flex-plugin-scripts is now at 96.48% statements/lines and 98.82%
functions; build.ts and start.ts are at 100% line coverage.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@shyamasish-twilio shyamasish-twilio added the run-e2e Trigger the mandatory E2E tests for Pull request label Sep 23, 2026
…probe

- artifactory-oidc: write always-auth=true to ~/.npmrc. The e2e tests
  run `twilio plugins:install`, which installs through the yarn 1 bundled
  in twilio-cli. Yarn 1 only sends the _authToken when always-auth is
  set, so Artifactory returned 401 and yarn reported every package as
  "Couldn't find package ... on the npm registry". npm already sent the
  token and is unaffected.
- Switch the macOS e2e runner label from macos-latest-large (never
  picked up; jobs queued until the 24h timeout) to macos-latest in the
  PR e2e matrix, nightly workflows, skip_e2e, and the reusable workflow's
  OS checks.
- Remove the temporary curation probe step and script; the full
  lockfile scan reported 0 blocked tarballs and build/test are green.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@shyamasish-twilio shyamasish-twilio added run-e2e Trigger the mandatory E2E tests for Pull request and removed run-e2e Trigger the mandatory E2E tests for Pull request labels Sep 23, 2026
`twilio plugins:install @twilio-labs/plugin-flex` installs with yarn into
the Twilio CLI data directory, resolving against that directory's own
package.json, so the repo's npm overrides do not apply. The published
plugin pulls ejs@^3 (via @twilio/cli-core -> @oclif/core@1) and
Artifactory curation blocks every ejs below 6.0.1, failing step001 with
a 403 on ejs-3.1.10.tgz.

- Pin the CLI data directory via TWILIO_DATA_DIR in the shared spawn env
  so every twilio invocation uses the same plugins directory (the spawn
  helper builds a minimal env and does not forward process.env).
- step001 seeds that directory's package.json with
  "resolutions": { "ejs": "^6.0.1" } before plugins:install;
  @oclif/plugin-plugins preserves extra fields when it saves.

Verified locally: plugins:install of plugin-flex@7.1.2 resolves
ejs@^3.1.6 to 6.0.1, and `twilio flex:plugins --help` still renders.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@shyamasish-twilio shyamasish-twilio added run-e2e Trigger the mandatory E2E tests for Pull request and removed run-e2e Trigger the mandatory E2E tests for Pull request labels Sep 23, 2026
…ted plugins

After pinning ejs, `twilio plugins:install` now fails on a different
curation block (undici-5.29.0, via @twilio/cli-core -> @actions/core ->
@actions/http-client). To stop discovering one blocked package per run,
add a TEMPORARY Linux-only probe step to the reusable e2e workflow that
checks every package version the e2e installs outside this repo's
lockfile against the curated registry:

- curation-targets.json: 1974 name@version entries generated locally
  from `twilio plugins:install @twilio-labs/plugin-flex@7.1.2` (with the
  ejs resolution) plus `npm i` in JS and TS plugins created by
  `twilio flex:plugins:create` with @twilio/flex-ui@latest.
- curation-probe.js: reports each blocked version with its source and
  probes the newest same-major and higher-major releases as candidates.

Remove both files and the step once the e2e installs pass.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
shyamasish-twilio and others added 3 commits September 30, 2026 23:32
Brings the branch up to date with main, which has moved on considerably:
the publish workflow consolidation and OIDC trusted publishing (#1167), the
dispatchable publish.yml and e2e.yml, the curated Artifactory install on the
PR pipeline, and the 7.1.3 version bump and changelog.

Fourteen files conflicted. Where both sides had solved the same problem, main's
implementation was taken, because it is the released one and the rest of the
tree is built around it:

  ~reusable_publish.yaml and ~reusable_public_publish.yaml are deleted, as main
  did. Every change this branch made to them -- ubuntu-x64, pinned action SHAs,
  id-token permissions, Artifactory auth, the retry with a real exit code, the
  inline curl Slack calls -- is already present in the consolidated publish.yml.

  pr_workflow.yaml takes main's artifactory-npm-auth.sh over this branch's
  composite action, so the mechanism matches publish.yml. The composite action
  itself stays: lockfile_hygiene.yaml still uses it.

  curation-probe.js takes main's version, which is a superset with a
  --scan-lockfile mode. This branch's copy reads a registry= line from ~/.npmrc
  that artifactory-npm-auth.sh deliberately never writes, so it could not work
  alongside the auth mechanism above.

Where this branch had made a deliberate change main did not, this branch wins:
windows-latest-large across the e2e matrix and skip_e2e, and the removal of the
node-18 localhost override, which is dead now that only node 22 and 24 are used.

The version conflicts resolve to main's 7.1.3, and flex-plugin-webpack5 -- which
exists only here -- is bumped to match, along with its pin in
flex-plugin-scripts.

package-lock.json was regenerated rather than hand-merged. Its fourteen
conflicts were over real dependency-tree differences, not version strings, and
resolving those by hand is not reliable. It now carries all thirteen workspace
packages at 7.1.3 and keeps the ejs ^6.0.1 override. Public npm is unreachable
from a Twilio laptop, so it was generated against Artifactory and rewritten with
.github/scripts/public-lockfile.js; every resolved URL names registry.npmjs.org.

Verified locally: npm ci installs the regenerated lockfile cleanly, lint passes,
no conflict markers remain, all seven changed workflows parse as YAML,
curation-probe.js passes node --check, and builds.test.ts passes.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Move the webpack 5 PR and nightly e2e workflows from Node 24 to Node 22
until Node 24 is enabled in CI.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@shyamasish-twilio shyamasish-twilio added the run-e2e Trigger the mandatory E2E tests for Pull request label Oct 6, 2026
@github-actions github-actions Bot removed the run-e2e Trigger the mandatory E2E tests for Pull request label Oct 6, 2026
shyamasish-twilio and others added 4 commits October 7, 2026 18:23
Bring in the net change of #1151 (FLEX-6241): drop the
@twilio/flex-plugin-scripts devDependency and the
__FPB_FLEX_PLUGIN_SCRIPTS_VERSION define, and exclude node_modules from
the type-check report in flex-plugin-webpack.

The js and ts templates the PR edits were already removed on this branch,
so only js2 and ts2 are touched. The define is also removed from
flex-plugin-webpack5, which postdates the PR.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Stop pinning the plugin build runtime to node22 and use 'latest' instead,
and drop the test assertion that expected node22.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Turn the dispatchable e2e workflow into a webpack (4, 5) x Node (22, 24)
matrix so a published alpha can be checked on every combination in one
run. Combinations run one at a time because each OS leg shares a single
Twilio account, and fail-fast is off so one failure does not hide the
others.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
actions/checkout had no ref, so it built the ref the workflow was
dispatched from. Dispatching from main with BRANCH=FLEXY-6498 published
main's code (12 packages, no flex-plugin-webpack5) as an alpha. Check out
inputs.BRANCH so the BRANCH input decides what is released.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
@florianbesnard-kadensis

florianbesnard-kadensis commented Oct 9, 2026 •

Copy link
Copy Markdown

Hello @shyamasish-twilio and twilio team,
Many thanks for this PR. Can't wait for the next version 👏
Have a good day

shyamasish-twilio and others added 3 commits October 14, 2026 09:21
…ugin in flex-plugin-webpack5

terser-webpack-plugin 2.x requires 'webpack' itself, which Yarn resolved to a
different webpack 5 copy than the webpack5 alias, so builds failed with
'compilation must be an instance of Compilation'. Version 5 uses
compiler.webpack. Also remove @k88/interpolate-html-plugin, which only
flex-plugin-webpack uses.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
…nation

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
The kill step failed with exit code 128 after the JS run had already stopped
its own processes, which skipped the TS run that follows it.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Comment on lines 169 to +174
run: |
echo "os is: ${{ inputs.OS }} ${{ runner.os }}"
taskkill /f /im node.exe
# taskkill exits 128 when no node.exe is left, which is expected here
# because the e2e run already stopped its own processes.
if ($LASTEXITCODE -eq 128) { exit 0 }

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🟠 High severity issue identified in your code:
Using variable interpolation ${{...}} with github context data in a run: step could allow an attacker to inject their own code into the runner. This would allow them to steal secrets and code. github context data can have arbitrary user input and should be treated as untrusted. Instead, use an intermediate environment variable with env: to store the data and use the environment variable in the run: script. Be sure to use double-quotes the environment variable, like this: "$ENVVAR".

To resolve this comment:

🔧 No guidance has been designated for this issue. Fix according to your organization's approved methods.

💬 Ignore this finding

Reply with Semgrep commands to ignore this finding.

  • /fp <comment> for false positive
  • /ar <comment> for acceptable risk
  • /other <comment> for all other reasons

Alternatively, triage in Semgrep AppSec Platform to ignore the finding created by run-shell-injection.

Need help with this issue? Consult our appsec team or ask in #help-appsec on Slack.

You can view more details about this finding in the Semgrep AppSec Platform.

shyamasish-twilio and others added 3 commits October 14, 2026 11:38
The config resolved style-loader, css-loader, postcss-loader and sass-loader by
their plain names, which are not dependencies of flex-plugin-webpack5. They only
resolved in the monorepo through the webpack 4 package; in the Twilio CLI's
install the build failed with 'Cannot find module style-loader'.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
The macos-x64 runner uses the macos-26 image, where the Chrome 121 build
pinned by puppeteer 21 crashed right after launch in step 006 (devtools
websocket closed with 1006 / ECONNRESET).

- Bump puppeteer ^21.3.7 -> ^24.24.1 (locks 24.43.1, Chrome 148).
- Replace page.waitForXPath, removed in v22, with waitForSelector and
  the `xpath/` query handler.
- Retry the browser launch in Browser.create. The launch runs before each
  step's retryOnError, so a crash there previously failed the step with
  no retry and no screenshot. Also add --disable-dev-shm-usage.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ugin test

Left behind when #1151 dropped the __FPB_FLEX_PLUGIN_SCRIPTS_VERSION global.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
shyamasish-twilio and others added 4 commits October 15, 2026 09:48
…ejected

The login fetch result was never checked, so a 403 from submitLoginPassword led
to three 6-minute waits on a Flex page that never loaded. Log the response and
throw on an error or a status of 400 or more.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Retries skipped the login because the session was assumed to exist, so a
rejected login was followed by waits on a Flex page that could never load.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Puppeteer 24's default headless mode (the new one) intermittently gets the
Twilio Console login blocked with a CloudFront 403. The old mode
(headless: 'shell') was not blocked in a probe on the same runners, and puppeteer 21
behaved the same way.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
…Node 18

The webpack 5 dev server handed the browser an absolute flex.twilio.com bundle URL
that it fetched without credentials, so a remote plugin got a 401. Port the
webpack 4 proxy: relative plugin URLs, the /plugins/v1 route and the flex-jwe
cookie with token chunking.

Supported Node versions are now 20, 22 and 24.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
shyamasish-twilio and others added 4 commits October 16, 2026 10:08
…webpack-plugin copy

@k88/interpolate-html-plugin requires its own html-webpack-plugin, and when the
package manager installs a second copy it hooks into the wrong one, so the dev page
was served with a literal %__FPB_JS_SCRIPTS% and Flex never rendered. Replace the
placeholder while reading the template, as the webpack 5 package does.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
… 20.19

sass 1.100.0 and later require Node 20.19, and the open ^1.32.8 range let a
fresh install resolve them, along with chokidar 5 and readdirp 5, which have
the same floor.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Webpack 5 reports compile errors and warnings as objects, and the dev server cast
them to strings, so @k88/format-webpack-messages threw
'message.split is not a function' and hid the real error.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
… path

The dev source map was named with a content hash, so it fell outside the
/plugins/<name>.js proxy and the browser got a 404 for it. Name it
plugins/<name>.js.map in development, as webpack 4 does.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>

This branch was successfully deployed

1 active deployment
production — 8e44d01d Deployed Oct 16, 2026 by shyamasish-twilio via publish #13
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants