ci: migrate pipeline to Twilio locked-down agents (Chromium CI image)#850
ci: migrate pipeline to Twilio locked-down agents (Chromium CI image)#850AnkitSegment wants to merge 8 commits into
Conversation
There was a problem hiding this comment.
⚠️ Not ready to approve
The upload/publish steps are moved onto general-039 but still depend on Segment agent hooks (SEGMENT_LIB_PATH/run-with-role), which will likely break master/staging pipelines.
Pull request overview
Migrates the Buildkite CI pipeline to run on Twilio locked-down general-039 agents by introducing a custom Chromium-capable CI image, switching steps to the docker-compose plugin, and pointing npm/yarn at Twilio’s Artifactory registry to avoid Segment-only infrastructure dependencies.
Changes:
- Add a custom CI Docker image (
.buildkite/Dockerfile.ci) that installs Chromium (via Twilio’s Alpine mirror) and provides aphantomjsstub to bypassphantomjs-prebuiltdownloads in no-egress environments. - Introduce a CI-only compose file (
docker-compose-ci.yml) and update Buildkite pipeline steps to run test/SauceLabs jobs via the docker-compose plugin ongeneral-039. - Update Karma to use a
ChromeHeadlessNoSandboxlauncher and add an.npmrcpointing to Twilio’s virtual npm registry.
File summaries
| File | Description |
|---|---|
karma.conf.js |
Switches default launcher to ChromeHeadlessNoSandbox and defines the custom launcher/flags. |
docker-compose-ci.yml |
Adds a CI-only compose definition to build/run the new Chromium test image and propagate needed env vars. |
.npmrc |
Sets npm registry to Twilio Artifactory virtual registry. |
.buildkite/pipeline.yml |
Migrates steps to general-039 and uses the docker-compose plugin for build/test and SauceLabs jobs. |
.buildkite/Dockerfile.ci |
Adds a locked-down CI image (Node + Chromium + build toolchain + phantomjs stub) suitable for no-egress agents. |
Copilot's findings
- Files reviewed: 5/6 changed files
- Comments generated: 3
Note
Your feedback helps us improve the quality of this feature.
Please use 👍 or 👎 to tell us whether this assessment is correct.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| // Run headless Chrome with --no-sandbox: the CI container runs as root, | ||
| // where Chrome's sandbox refuses to start. CHROME_BIN points at the | ||
| // Chromium installed in .buildkite/Dockerfile.ci. | ||
| browsers: ['ChromeHeadlessNoSandbox'], | ||
|
|
||
| customLaunchers: { | ||
| ChromeHeadlessNoSandbox: { | ||
| base: 'ChromeHeadless', | ||
| flags: ['--no-sandbox', '--disable-gpu', '--disable-dev-shm-usage'] | ||
| } | ||
| }, |
| branches: master staging | ||
| agents: | ||
| queue: v1 | ||
| queue: general-039 |
| branches: master | ||
| agents: | ||
| queue: v1 | ||
| queue: general-039 |
There was a problem hiding this comment.
⚠️ Not ready to approve
The repo-wide .npmrc registry override can break non-Twilio/local workflows and the pipeline’s auth-token setting should be safely quoted to avoid shell parsing issues.
Copilot's findings
- Files reviewed: 7/8 changed files
- Comments generated: 5
Note
Your feedback helps us improve the quality of this feature.
Please use 👍 or 👎 to tell us whether this assessment is correct.
| queue: general-039 | ||
| command: | ||
| - npm config set "//registry.npmjs.org/:_authToken" $${NPM_TOKEN} | ||
| - npm config set "//npmjs.artifacts.twilio.com/artifactory/api/npm/virtual-npm-twilio/:_authToken" $${NPM_TOKEN} |
| queue: general-039 | ||
| command: | ||
| - npm config set "//registry.npmjs.org/:_authToken" $${NPM_TOKEN} | ||
| - npm config set "//npmjs.artifacts.twilio.com/artifactory/api/npm/virtual-npm-twilio/:_authToken" $${NPM_TOKEN} |
| queue: general-039 | ||
| command: | ||
| - npm config set "//registry.npmjs.org/:_authToken" $${NPM_TOKEN} | ||
| - npm config set "//npmjs.artifacts.twilio.com/artifactory/api/npm/virtual-npm-twilio/:_authToken" $${NPM_TOKEN} |
| queue: general-039 | ||
| command: | ||
| - npm config set "//registry.npmjs.org/:_authToken" $${NPM_TOKEN} | ||
| - npm config set "//npmjs.artifacts.twilio.com/artifactory/api/npm/virtual-npm-twilio/:_authToken" $${NPM_TOKEN} |
| @@ -0,0 +1 @@ | |||
| registry=https://npmjs.artifacts.twilio.com/artifactory/api/npm/virtual-npm-twilio/ | |||
a0e576d to
653a916
Compare
653a916 to
87cba5a
Compare
There was a problem hiding this comment.
⚠️ Not ready to approve
CI will fail as submitted due to missing yarn.lock updates for new dependencies and inconsistent Docker Compose service naming between docker-compose-ci.yml, Buildkite config, and scripts.
Copilot's findings
Comments suppressed due to low confidence (1)
.buildkite/pipeline.yml:46
- The stated goal is migrating off Segment-only Buildkite infrastructure for locked-down agents, but this pipeline still includes
segmentio/cache-buildkite-pluginin the SauceLabs and asset upload steps and still runs SauceLabs inside the Segment ECR image (528451384384.dkr.ecr.../analytics.js-integrations-ci). Those dependencies are called out in the PR description as failing on locked-down agents (S3 403 / missing tooling), so those steps are likely to remain broken unless they’re also migrated/removed.
- label: "SauceLabs"
key: "sauce_labs"
branches: "!master"
soft_fail: true
command:
- npm config set "//registry.npmjs.org/:_authToken" $${NPM_TOKEN}
- yarn install --ignore-engines
- yarn test:ci
plugins:
- ssh://git@github.com/segmentio/cache-buildkite-plugin#v1.0.0:
key: "v1-cache-dev-{{ checksum 'yarn.lock' }}"
paths: ["node_modules/"]
s3_bucket_name: "segment-buildkite-cache"
- docker#v3.3.0:
image: 528451384384.dkr.ecr.us-west-2.amazonaws.com/analytics.js-integrations-ci
user: root
environment:
- Files reviewed: 163/164 changed files
- Comments generated: 4
Note
Your feedback helps us improve the quality of this feature.
Please use 👍 or 👎 to tell us whether this assessment is correct.
| "eslint-plugin-prettier": "^3.1.4", | ||
| "fs-extra": "^9.0.1", | ||
| "husky": "^4.3.8", | ||
| "karma-webdriver-launcher": "^1.0.8", |
| test: | ||
| image: 018537234677.dkr.ecr.us-east-1.amazonaws.com/docker.io/library/node:22.18.0-bookworm | ||
| working_dir: /app |
| - docker-compose#v5.12.1: | ||
| run: e2e-runner | ||
| config: docker-compose-ci.yml | ||
| mount-buildkite-agent: true |
| customLaunchers: { | ||
| ChromeRemote: { | ||
| base: 'WebDriver', | ||
| config: { | ||
| hostname: process.env.SELENIUM_HOST || 'localhost', | ||
| port: 4444 | ||
| }, | ||
| browserName: 'chrome', | ||
| pseudoActivityInterval: 30000 | ||
| } | ||
| }, | ||
|
|
||
| browsers: ['ChromeRemote'], | ||
|
|
87cba5a to
b7bac2f
Compare
There was a problem hiding this comment.
⚠️ Not ready to approve
There are CI-breaking configuration mismatches (non-existent compose service names) and multiple verified discrepancies with the PR description (missing CI Dockerfile/.npmrc and remaining incompatible cache plugin usage).
Copilot's findings
- Files reviewed: 163/164 changed files
- Comments generated: 11
Note
Your feedback helps us improve the quality of this feature.
Please use 👍 or 👎 to tell us whether this assessment is correct.
| - docker-compose#v5.12.1: | ||
| run: e2e-runner | ||
| config: docker-compose-ci.yml | ||
| mount-buildkite-agent: true |
| - docker-compose#v5.12.1: | ||
| run: test | ||
| config: docker-compose-ci.yml | ||
| mount-buildkite-agent: true |
| - label: ":cloud: Upload Assets to stage bucket" | ||
| branches: master staging | ||
| agents: | ||
| queue: v1 | ||
| command: | ||
| - echo "--- Upload" | ||
| - NODE_ENV=production ./.buildkite/upload.sh |
| - label: ":cloud: Upload Assets to production bucket" | ||
| branches: master | ||
| agents: | ||
| queue: v1 | ||
| command: | ||
| - echo "--- Upload" | ||
| - NODE_ENV=production ./.buildkite/publish.sh |
| --volume "$PWD:/workdir" --workdir /workdir \ | ||
| -e NPM_TOKEN -e NODE_ENV \ | ||
| -e AWS_ACCESS_KEY_ID -e AWS_SECRET_ACCESS_KEY -e AWS_SESSION_TOKEN \ | ||
| app sh -e -c ' |
| } | ||
| }, | ||
|
|
||
| browsers: ['ChromeRemote'], |
| env: | ||
| COMPOSE_PROFILES: "ci" | ||
| branches: "!master" |
| test: | ||
| image: 018537234677.dkr.ecr.us-east-1.amazonaws.com/docker.io/library/node:22.18.0-bookworm | ||
| working_dir: /app |
| -e NPM_TOKEN -e NODE_ENV \ | ||
| -e AWS_ACCESS_KEY_ID -e AWS_SECRET_ACCESS_KEY -e AWS_SESSION_TOKEN \ | ||
| app sh -e -c ' | ||
| npm config set "//npmjs.artifacts.twilio.com/artifactory/api/npm/virtual-npm-twilio/:_authToken" "${NPM_TOKEN}" |
| -e NPM_TOKEN -e NODE_ENV \ | ||
| -e AWS_ACCESS_KEY_ID -e AWS_SECRET_ACCESS_KEY -e AWS_SESSION_TOKEN \ | ||
| app sh -e -c ' | ||
| npm config set "//npmjs.artifacts.twilio.com/artifactory/api/npm/virtual-npm-twilio/:_authToken" "${NPM_TOKEN}" |
These dependencies were unused — no karma config ever sets PhantomJS as a browser (all use ChromeRemote/SauceLabs). The phantomjs-prebuilt post-install script downloads a binary from GitHub which times out in CI, breaking builds. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Add healthcheck to chrome service so test container waits until Selenium Grid is ready before starting (fixes race condition) - Fix karma.conf.js ChromeRemote config to use `url` instead of hostname/port — karma-webdriver-launcher requires a `url` key, the old config caused Selenium to receive "url" as a session ID Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
There was a problem hiding this comment.
⚠️ Not ready to approve
The Buildkite pipeline and upload/publish scripts reference docker-compose services that don’t exist in docker-compose-ci.yml, which will break CI execution.
Copilot's findings
- Files reviewed: 164/165 changed files
- Comments generated: 6
Note
Your feedback helps us improve the quality of this feature.
Please use 👍 or 👎 to tell us whether this assessment is correct.
| plugins: | ||
| - ssh://git@github.com/segmentio/cache-buildkite-plugin#v1.0.0: | ||
| key: "v1-cache-dev-{{ checksum 'yarn.lock' }}" | ||
| paths: [ "node_modules/" ] | ||
| s3_bucket_name: "segment-buildkite-cache" | ||
| save: true | ||
| - docker#v3.3.0: | ||
| image: circleci/node:12.18-browsers | ||
| user: root | ||
| environment: | ||
| - NPM_TOKEN | ||
| - CHROME-BIN=google-chrome | ||
| - docker-compose#v5.12.1: | ||
| run: e2e-runner | ||
| config: docker-compose-ci.yml | ||
| mount-buildkite-agent: true |
| queue: v1 | ||
| command: | ||
| - echo "--- Upload" | ||
| - NODE_ENV=production ./.buildkite/upload.sh |
| docker compose -f docker-compose-ci.yml run --rm \ | ||
| --volume "$PWD:/workdir" --workdir /workdir \ | ||
| -e NPM_TOKEN -e NODE_ENV \ | ||
| -e AWS_ACCESS_KEY_ID -e AWS_SECRET_ACCESS_KEY -e AWS_SESSION_TOKEN \ | ||
| app sh -e -c ' |
| docker compose -f docker-compose-ci.yml run --rm \ | ||
| --volume "$PWD:/workdir" --workdir /workdir \ | ||
| -e NPM_TOKEN -e NODE_ENV \ | ||
| -e AWS_ACCESS_KEY_ID -e AWS_SECRET_ACCESS_KEY -e AWS_SESSION_TOKEN \ | ||
| app sh -e -c ' |
| customLaunchers: { | ||
| ChromeRemote: { | ||
| base: 'WebDriver', | ||
| config: { | ||
| url: 'http://' + (process.env.SELENIUM_HOST || 'localhost') + ':4444/wd/hub' |
| - docker-compose#v5.12.1: | ||
| run: test | ||
| config: docker-compose-ci.yml | ||
| mount-buildkite-agent: true |
The docker-compose plugin runs 'docker compose run' and only passes env vars explicitly listed under its environment key — the compose file's environment block is not automatically forwarded. Add SELENIUM_HOST=chrome explicitly so karma-webdriver-launcher connects to the chrome service instead of falling back to localhost:4444 (ECONNREFUSED). Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
The b7bac2f migration replaced the working Chromium-in-container setup (from 4e9fe51) with a Selenium standalone-chrome:126 + karma-webdriver-launcher approach that cannot work: wd@1.14.0 speaks JSON Wire Protocol but Selenium 4 only speaks W3C WebDriver, causing every session to get session ID "url" and fail with NoSuchSessionException. Restore 4e9fe51's approach: - .buildkite/Dockerfile.ci: build image with node + Chromium from Twilio ECR/apk mirrors (no public egress needed) - docker-compose-ci.yml: single 'app' service built from Dockerfile.ci - karma.conf.js: ChromeHeadlessNoSandbox (no Selenium, no WebDriver) - .buildkite/pipeline.yml: docker-compose plugin with mount-checkout Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
There was a problem hiding this comment.
⚠️ Not ready to approve
The repo’s Karma config runs ChromeHeadless but karma-chrome-launcher has been removed from dependencies (package.json/yarn.lock), so test execution will fail until the Chrome launcher dependency is restored.
Copilot's findings
- Files reviewed: 165/166 changed files
- Comments generated: 4
Note
Your feedback helps us improve the quality of this feature.
Please use 👍 or 👎 to tell us whether this assessment is correct.
| "eslint-plugin-prettier": "^3.1.4", | ||
| "fs-extra": "^9.0.1", | ||
| "husky": "^4.3.8", | ||
| "karma-webdriver-launcher": "^1.0.8", |
| "karma": "^4.1.0", | ||
| "karma-browserify": "^6.0.0", | ||
| "karma-chrome-launcher": "^2.2.0", | ||
| "karma-webdriver-launcher": "^1.0.8", |
| - wait: ~ | ||
| depends_on: ["build_master", "sauce_labs_master"] | ||
| depends_on: ["build_master"] |
| # Several integrations still list phantomjs-prebuilt as a devDependency. Its | ||
| # postinstall downloads a binary from a public CDN, which is unreachable on the | ||
| # no-egress agents and fails `yarn install`. phantomjs-prebuilt has no | ||
| # skip-download flag, but its installer (tryPhantomjsOnPath) skips the download | ||
| # when a `phantomjs` already on PATH reports the expected version (2.1.1). The | ||
| # tests only ever launch ChromeHeadless (karma.conf.js) -- the phantom launcher | ||
| # is an unused devDependency -- so a stub that just answers `--version` is | ||
| # enough to satisfy the installer without ever running as a browser. | ||
| RUN printf '#!/bin/sh\necho 2.1.1\n' > /usr/local/bin/phantomjs && \ | ||
| chmod +x /usr/local/bin/phantomjs |
ChromeHeadlessNoSandbox in karma.conf.js requires karma-chrome-launcher but it was missing from the workspace root, causing all integrations to fail with "No provider for launcher:ChromeHeadless". Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
b7bac2f replaced karma-chrome-launcher with karma-webdriver-launcher in boomtrain. Since we now use ChromeHeadlessNoSandbox everywhere, boomtrain needs karma-chrome-launcher back to launch the browser correctly. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
There was a problem hiding this comment.
⚠️ Not ready to approve
The pipeline changes appear to contradict the PR’s stated SauceLabs migration/verification, and karma-webdriver-launcher is introduced broadly despite being unused by the repo’s Karma configuration.
Copilot's findings
- Files reviewed: 164/165 changed files
- Comments generated: 3
Note
Your feedback helps us improve the quality of this feature.
Please use 👍 or 👎 to tell us whether this assessment is correct.
| - wait: ~ | ||
| depends_on: ["build_master", "sauce_labs_master"] | ||
| depends_on: ["build_master"] |
| "karma-chrome-launcher": "^3.1.0", | ||
| "karma-webdriver-launcher": "^1.0.8", |
| "karma": "^4.1.0", | ||
| "karma-browserify": "^6.0.0", | ||
| "karma-chrome-launcher": "^2.2.0", | ||
| "karma-webdriver-launcher": "^1.0.8", | ||
| "karma-mocha": "^1.3.0", |
- Restore SauceLabs and SauceLabs Master steps (soft_fail: true) - Restore wait depends_on both build_master and sauce_labs_master - Restore cache-buildkite-plugin on Upload Assets steps Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Summary
Fixes the Buildkite pipeline on the Twilio locked-down
general-039agents. The previous pipeline still depended on Segment-only infrastructure and failed every run.Verified green on build #11 (Build and Test + SauceLabs both passed).
Root causes fixed
cache-buildkite-plugin→shasum: command not found+ S3403on the locked-down agents. Removed.ChromeHeadless, butnode:*-alpineships no browser. Added a CI image with Chromium.docker.iopulls TLS-timeout, soapk add chromiumcan't reach the public Alpine CDN. Chromium is installed from the Twiliobase-alpineapk mirror.phantomjs-prebuiltpostinstall download (the real blocker) — several integrations pull it as a devDependency; its install downloads a binary from a public CDN and failsyarn install. It has no skip flag, so a tinyphantomjsstub onPATHreporting2.1.1makes its installer skip the download. The phantom launcher is unused — tests only run ChromeHeadless.Changes
.buildkite/Dockerfile.cidocker-compose-ci.yml.buildkite/pipeline.ymlmount-checkoutkarma.conf.jsChromeHeadlessNoSandboxlauncher (container runs as root).npmrcNotes / follow-ups
yarn testruns--since masterand reports "no packages" — passes without exercising integration tests. The CI infra is verified working; a branch touching an integration will exercise real Chrome runs.Upload Assetssteps still call./.buildkite/upload.sh/publish.sh, which rely on Segment agent hooks (SEGMENT_LIB_PATH,run-with-role). Being verified separately onstaging.🤖 Generated with Claude Code