Repository navigation
FLEXY-6498 Dual Webpack (4 & 5) Support - #1164
shyamasish-twilio wants to merge 52 commits into
Conversation
# 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>
| if: always() | ||
| runs-on: ubuntu-22.04 | ||
| steps: | ||
| - uses: actions-ecosystem/action-remove-labels@v1 |
There was a problem hiding this comment.
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 🍰
| if: always() | ||
| runs-on: ubuntu-22.04 | ||
| steps: | ||
| - uses: actions-ecosystem/action-remove-labels@v1 |
There was a problem hiding this comment.
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 🚀
| version: ${{ steps.alphaVersion.outputs.version }} | ||
| steps: | ||
| - uses: actions/checkout@v4 | ||
| - uses: actions/setup-node@v3 |
There was a problem hiding this comment.
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 ⭐
| branch: ${{ steps.extractBranch.outputs.branch }} | ||
| version: ${{ steps.alphaVersion.outputs.version }} | ||
| steps: | ||
| - uses: actions/checkout@v4 |
There was a problem hiding this comment.
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 🧁
…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>
| 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 }}\" | ||
| }] | ||
| }] | ||
| }" |
There was a problem hiding this comment.
🟠 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 🧼
| 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 }}\" | ||
| }] | ||
| }] | ||
| }" |
There was a problem hiding this comment.
🟠 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 🎈
…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>
…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>
`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>
…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>
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>
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>
|
Hello @shyamasish-twilio and twilio team, |
…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>
| 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 } |
There was a problem hiding this comment.
🟠 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.
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>
…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>
…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>
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:
CLI / orchestration changes
E2E test coverage
Added a parallel Node 24 / webpack5 e2e suite alongside the existing Node 22/webpack4 one, without altering the latter's behavior:
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
Contributing to Twilio