chore: use circleci cli to package ci configurations (#32462)

* add husky script to build circleci yml files

* add circleci cli as a required tool for working with .circleci

* break the original workflows.yml file into separate pieces, using circleci config pack to compose them into the main workflows.yml file

* fix pull request workflow def

* more robust precommit for circleci packing

* even nicer stdout for precommit :)

* allow pr pipeline on this branch

* split up the config.yml to demonstrate more fully

* fix conditional on pr pipeline

* exit 1 if circleci cli not found and circleci config files staged for commit

* use linux-x64 executor for unit-tests

* try using ipv6 in contributor with correct executor

* ensure node

* update github action to update browser versions to point to the correct file

* ensure node more times

* fix export

* reduce expected result count

* run full workflow menu on this branch

* bump config class to medium

* index on use-pack-for-circle: a9bcbe87b0 run full workflow menu on this branch

* index on use-pack-for-circle: a9bcbe87b0 run full workflow menu on this branch

* index on use-pack-for-circle: a9bcbe87b0 run full workflow menu on this branch

* revert to small for checkout code in config workflow; remove from multi branch trigger

* fix incorrect conflict resolution for bettersqlite3 changes w/ electron update

* make path to circleci workflows file more explicit, comment why it is that file

---------

Co-authored-by: cypress-bot[bot] <+cypress-bot[bot]@users.noreply.github.com>
This commit is contained in:
Cacie Prins
2025-09-19 09:22:59 -04:00
committed by GitHub
parent 99deaf6061
commit 4afbf26009
13 changed files with 9103 additions and 3536 deletions

57
.circleci/README.md Normal file
View File

@@ -0,0 +1,57 @@
# CircleCI Configuration
This directory contains CircleCI configuration files that are automatically generated and updated.
## Prerequisites
### CircleCI Local CLI
The CircleCI Local CLI is required to generate the `pull-request.yml` file from the source configuration.
**Installation:**
- **macOS (Homebrew):**
```bash
brew install circleci
```
- **Linux:**
```bash
curl -fLSs https://raw.githubusercontent.com/CircleCI-Public/circleci-cli/master/install.sh | bash
```
- **Windows:**
```bash
choco install circleci-cli
```
- **Manual installation:**
Download from [CircleCI Local CLI releases](https://github.com/CircleCI-Public/circleci-cli/releases)
For more detailed installation instructions, see the [CircleCI Local CLI documentation](https://circleci.com/docs/2.0/local-cli/).
## Lint-Staged Rules
When files in this directory are modified, the following lint-staged rule will automatically run:
```bash
circleci config pack .circleci/workflows-src > .circleci/workflows.yml
```
This command:
1. Takes the source configuration from `./.circleci/workflows-src/`
2. Packs it into a single YAML file
3. Outputs the result to `./circleci/workflows.yml`
## File Structure
- `workflows-src/` - Source configuration files (modify these)
- `workflows.yml` - Generated configuration file (auto-generated, do not edit manually)
## Development Workflow
1. Make changes to files in `workflows-src/`
2. The lint-staged hook will automatically regenerate `workflows.yml` and stage it
3. Commit both the source changes and the generated file
**Note:** Always commit both the source files and the generated `workflows.yml` file together to ensure the CircleCI configuration stays in sync.

View File

@@ -1,63 +1,60 @@
version: 2.1
setup: true
orbs:
continuation: circleci/continuation@1.1.0
jobs:
verify-ci-should-run:
resource_class: small
docker:
- image: cimg/node:current
steps:
- run:
name: Verify CI should run
command: |
# run CI when manually triggers via CircleCi Dashboard
if [ <<pipeline.trigger_source>> == 'api' ]; then
echo "Always run CI when manually triggered from the UI."
exit 0
fi
verify-ci-should-run:
docker:
- image: cimg/node:current
resource_class: small
steps:
- run:
command: |
# run CI when manually triggers via CircleCi Dashboard
if [ <<pipeline.trigger_source>> == 'api' ]; then
echo "Always run CI when manually triggered from the UI."
exit 0
fi
if [[ "$CIRCLE_BRANCH" == "develop" || "$CIRCLE_BRANCH" == "release/"* ]]; then
echo "Always run CI for develop and for release candidate branches."
exit 0
fi
if [[ "$CIRCLE_BRANCH" == "develop" || "$CIRCLE_BRANCH" == "release/"* ]]; then
echo "Always run CI for develop and for release candidate branches."
exit 0
fi
LAST_COMMIT_MESSAGE=$(curl --silent "https://api.github.com/repos/${CIRCLE_PROJECT_USERNAME}/${CIRCLE_PROJECT_REPONAME}/commits/${CIRCLE_BRANCH}" | jq '.commit.message')
LAST_COMMIT_MESSAGE=$(curl --silent "https://api.github.com/repos/${CIRCLE_PROJECT_USERNAME}/${CIRCLE_PROJECT_REPONAME}/commits/${CIRCLE_BRANCH}" | jq '.commit.message')
if [[ "$LAST_COMMIT_MESSAGE" =~ "run ci" ]]; then
echo "Always run CI when the commit message includes 'run ci'."
exit 0
fi
if [[ "$LAST_COMMIT_MESSAGE" =~ "run ci" ]]; then
echo "Always run CI when the commit message includes 'run ci'."
exit 0
fi
cancel_build () {
echo "Canceling the CI build..."
circleci-agent step halt
}
cancel_build () {
echo "Canceling the CI build..."
circleci-agent step halt
}
TRIGGER_INSTRUCTIONS="to trigger CI , include 'run ci' in the commit message or click the 'Trigger Pipeline' button in the CircleCI UI."
TRIGGER_INSTRUCTIONS="to trigger CI , include 'run ci' in the commit message or click the 'Trigger Pipeline' button in the CircleCI UI."
if [ ! -z "${CIRCLE_PULL_REQUEST##*/}" ]; then
DRAFT=$(curl --silent "https://api.github.com/repos/${CIRCLE_PROJECT_USERNAME}/${CIRCLE_PROJECT_REPONAME}/pulls/${CIRCLE_PULL_REQUEST##*/}" | jq '.draft')
if [ ! -z "${CIRCLE_PULL_REQUEST##*/}" ]; then
DRAFT=$(curl --silent "https://api.github.com/repos/${CIRCLE_PROJECT_USERNAME}/${CIRCLE_PROJECT_REPONAME}/pulls/${CIRCLE_PULL_REQUEST##*/}" | jq '.draft')
if [[ "${DRAFT}" == true ]]; then
echo "Skipping CI; PR is in draft - $TRIGGER_INSTRUCTIONS"
cancel_build
fi
if [[ "${DRAFT}" == true ]]; then
echo "Skipping CI; PR is in draft - $TRIGGER_INSTRUCTIONS"
cancel_build
fi
echo "Always run CI for PR that is ready for review."
exit 0
fi
echo "Skipping CI; branch in progress - $TRIGGER_INSTRUCTIONS"
cancel_build
- checkout
- continuation/continue:
configuration_path: .circleci/workflows.yml
echo "Always run CI for PR that is ready for review."
exit 0
fi
echo "Skipping CI; branch in progress - $TRIGGER_INSTRUCTIONS"
cancel_build
name: Verify CI should run
- checkout
- continuation/continue:
configuration_path: .circleci/workflows.yml
orbs:
continuation: circleci/continuation@1.1.0
setup: true
version: 2.1
workflows:
# the setup-workflow workflow is always triggered.
setup-workflow:
jobs:
- verify-ci-should-run
setup-workflow:
jobs:
- verify-ci-should-run

View File

@@ -0,0 +1,4 @@
version: 2.1
setup: true
orbs:
continuation: circleci/continuation@1.1.0

View File

@@ -0,0 +1,49 @@
resource_class: small
docker:
- image: cimg/node:current
steps:
- run:
name: Verify CI should run
command: |
# run CI when manually triggers via CircleCi Dashboard
if [ <<pipeline.trigger_source>> == 'api' ]; then
echo "Always run CI when manually triggered from the UI."
exit 0
fi
if [[ "$CIRCLE_BRANCH" == "develop" || "$CIRCLE_BRANCH" == "release/"* ]]; then
echo "Always run CI for develop and for release candidate branches."
exit 0
fi
LAST_COMMIT_MESSAGE=$(curl --silent "https://api.github.com/repos/${CIRCLE_PROJECT_USERNAME}/${CIRCLE_PROJECT_REPONAME}/commits/${CIRCLE_BRANCH}" | jq '.commit.message')
if [[ "$LAST_COMMIT_MESSAGE" =~ "run ci" ]]; then
echo "Always run CI when the commit message includes 'run ci'."
exit 0
fi
cancel_build () {
echo "Canceling the CI build..."
circleci-agent step halt
}
TRIGGER_INSTRUCTIONS="to trigger CI , include 'run ci' in the commit message or click the 'Trigger Pipeline' button in the CircleCI UI."
if [ ! -z "${CIRCLE_PULL_REQUEST##*/}" ]; then
DRAFT=$(curl --silent "https://api.github.com/repos/${CIRCLE_PROJECT_USERNAME}/${CIRCLE_PROJECT_REPONAME}/pulls/${CIRCLE_PULL_REQUEST##*/}" | jq '.draft')
if [[ "${DRAFT}" == true ]]; then
echo "Skipping CI; PR is in draft - $TRIGGER_INSTRUCTIONS"
cancel_build
fi
echo "Always run CI for PR that is ready for review."
exit 0
fi
echo "Skipping CI; branch in progress - $TRIGGER_INSTRUCTIONS"
cancel_build
- checkout
- continuation/continue:
configuration_path: .circleci/workflows.yml

View File

@@ -0,0 +1,2 @@
jobs:
- verify-ci-should-run

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,319 @@
when:
and:
- not:
matches:
pattern: /^release\//
value: << pipeline.git.branch >>
- not:
matches:
pattern: /^develop/
value: << pipeline.git.branch >>
- not:
matches:
pattern: /^pull\/[0-9]+/
value: << pipeline.git.branch >>
jobs:
- node_modules_install:
build-better-sqlite3: true
- build:
context: test-runner:env-canary
requires:
- node_modules_install
- check-ts:
requires:
- build
- lint:
name: linux-lint
requires:
- build
- percy-finalize:
context: test-runner:percy
required_env_var: PERCY_TOKEN
requires:
- cli-visual-tests
- reporter-integration-tests
- run-app-component-tests-chrome
- run-app-integration-tests-chrome
- run-frontend-shared-component-tests-chrome
- run-launchpad-component-tests-chrome
- run-launchpad-integration-tests-chrome
- run-reporter-component-tests-chrome
- run-webpack-dev-server-integration-tests
- run-vite-dev-server-integration-tests
# Cypress run must be completed to fetch Accessibility report
- verify-accessibility-results:
context: test-runner:cypress-record-key
requires:
- reporter-integration-tests
- run-app-component-tests-chrome
- run-app-integration-tests-chrome
- run-frontend-shared-component-tests-chrome
- run-launchpad-component-tests-chrome
- run-launchpad-integration-tests-chrome
- run-reporter-component-tests-chrome
- run-webpack-dev-server-integration-tests
- run-vite-dev-server-integration-tests
- driver-integration-tests-firefox
- driver-integration-tests-chrome
- driver-integration-tests-chrome-inject-document-domain
- driver-integration-tests-chrome-beta-inject-document-domain
- driver-integration-tests-electron
- driver-integration-tests-webkit
- driver-integration-memory-tests
- lint-types:
requires:
- build
# unit, integration and e2e tests
- cli-visual-tests:
context: test-runner:percy
requires:
- build
- unit-tests:
requires:
- build
- verify-release-readiness:
context: test-runner:npm-release
requires:
- build
- server-unit-tests:
requires:
- build
- server-integration-tests:
requires:
- build
- server-performance-tests:
requires:
- build
- system-tests-node-modules-install:
context: test-runner:performance-tracking
requires:
- build
- system-tests-chrome:
context: test-runner:performance-tracking
requires:
- system-tests-node-modules-install
- system-tests-electron:
context: test-runner:performance-tracking
requires:
- system-tests-node-modules-install
- system-tests-firefox:
context: test-runner:performance-tracking
requires:
- system-tests-node-modules-install
- system-tests-webkit:
context: test-runner:performance-tracking
requires:
- system-tests-node-modules-install
- system-tests-non-root:
context: test-runner:performance-tracking
executor: non-root-docker-user
requires:
- system-tests-node-modules-install
- driver-integration-tests-chrome:
context: test-runner:cypress-record-key
requires:
- build
- driver-integration-tests-chrome-inject-document-domain:
context: test-runner:cypress-record-key
requires:
- build
- driver-integration-tests-chrome-beta:
context: test-runner:cypress-record-key
requires:
- build
- driver-integration-tests-chrome-beta-inject-document-domain:
context: test-runner:cypress-record-key
requires:
- build
- driver-integration-tests-firefox:
context: test-runner:cypress-record-key
requires:
- build
- driver-integration-tests-electron:
context: test-runner:cypress-record-key
requires:
- build
- driver-integration-tests-webkit:
context: test-runner:cypress-record-key
requires:
- build
- driver-integration-memory-tests:
requires:
- build
- run-frontend-shared-component-tests-chrome:
context:
[
test-runner:cypress-record-key,
test-runner:launchpad-tests,
test-runner:percy
]
percy: true
requires:
- build
- run-launchpad-integration-tests-chrome:
context:
[
test-runner:cypress-record-key,
test-runner:launchpad-tests,
test-runner:percy
]
percy: true
requires:
- build
- run-launchpad-component-tests-chrome:
context:
[
test-runner:cypress-record-key,
test-runner:launchpad-tests,
test-runner:percy
]
percy: true
requires:
- build
- run-app-integration-tests-chrome:
context:
[
test-runner:cypress-record-key,
test-runner:launchpad-tests,
test-runner:percy
]
percy: true
requires:
- build
- run-webpack-dev-server-integration-tests:
context: [ test-runner:cypress-record-key, test-runner:percy ]
requires:
- system-tests-node-modules-install
- run-vite-dev-server-integration-tests:
context: [ test-runner:cypress-record-key, test-runner:percy ]
requires:
- system-tests-node-modules-install
- run-app-component-tests-chrome:
context:
[
test-runner:cypress-record-key,
test-runner:launchpad-tests,
test-runner:percy
]
percy: true
requires:
- build
- run-reporter-component-tests-chrome:
context: [ test-runner:cypress-record-key, test-runner:percy ]
percy: true
requires:
- build
- reporter-integration-tests:
context: [ test-runner:cypress-record-key, test-runner:percy ]
requires:
- build
- npm-webpack-dev-server:
requires:
- system-tests-node-modules-install
- npm-vite-dev-server:
requires:
- build
- npm-vite-plugin-cypress-esm:
requires:
- build
- npm-webpack-preprocessor:
requires:
- build
- npm-webpack-batteries-included-preprocessor:
requires:
- build
- npm-vue:
requires:
- build
- npm-puppeteer-unit-tests:
requires:
- build
- npm-puppeteer-cypress-tests:
requires:
- build
- npm-react:
requires:
- build
- npm-angular:
requires:
- build
- npm-mount-utils:
requires:
- build
- npm-grep:
requires:
- build
- npm-eslint-plugin-dev:
requires:
- build
- npm-cypress-schematic:
requires:
- build
- v8-integration-tests:
requires:
- system-tests-node-modules-install
- create-and-trigger-packaging-artifacts:
context:
- test-runner:upload
- test-runner:build-binary
- publish-binary
requires:
- node_modules_install
- wait-for-binary-publish:
type: approval
requires:
- create-and-trigger-packaging-artifacts
- get-published-artifacts:
context:
- publish-binary
- test-runner:commit-status-checks
requires:
- wait-for-binary-publish
- test-kitchensink:
requires:
- build
- test-npm-module-on-minimum-node-version:
context: publish-binary
requires:
- get-published-artifacts
- test-types-cypress-and-jest:
context: publish-binary
requires:
- get-published-artifacts
- test-full-typescript-project:
context: publish-binary
requires:
- get-published-artifacts
- test-binary-against-kitchensink:
context: publish-binary
requires:
- get-published-artifacts
- test-binary-as-specific-user:
name: "test binary as a non-root user"
executor: non-root-docker-user
context: publish-binary
requires:
- get-published-artifacts
- test-binary-as-specific-user:
name: "test binary as a root user"
context: publish-binary
requires:
- get-published-artifacts
- binary-system-tests:
context: publish-binary
requires:
- get-published-artifacts
- system-tests-node-modules-install
- yarn-pnp-preprocessor-system-test:
context: publish-binary
requires:
- get-published-artifacts
- system-tests-node-modules-install
- svelte-webpack-system-test:
context: publish-binary
requires:
- get-published-artifacts
- system-tests-node-modules-install

File diff suppressed because it is too large Load Diff

View File

@@ -1,4 +1,41 @@
#!/bin/sh
. "$(dirname "$0")/_/husky.sh"
# Pack CircleCI config if any files in .circleci/src were changed
if git diff --cached --name-only | grep -q "^\.circleci/src/"; then
if ! which circleci > /dev/null; then
echo "❌ Warning: CircleCI CLI not found! Install the CircleCi CLI to edit the CircleCI configuration."
exit 1
fi
echo "Processing CircleCI configurations..."
# Find all directories in .circleci/src
for dir in ./.circleci/src/*/; do
if [ -d "$dir" ]; then
dirname=$(basename "$dir")
output_file="./.circleci/${dirname}.yml"
echo "📦 Packing ${dirname}.yml configuration..."
if ! circleci config pack "$dir" > "$output_file"; then
echo " ❌ Failed to pack ${output_file}"
exit 1
fi
echo " ✅ Packed ${output_file}"
echo " 🔍 Validating ${output_file}"
if ! circleci config validate "$output_file"; then
echo " ❌ Validating ${output_file} failed"
exit 1
fi
echo " ✅ ${dirname}.yml configuration validated successfully"
git add "$output_file"
echo " 📝 ${output_file} staged for commit"
fi
done
echo "🎉 All CircleCI configurations processed successfully!"
fi
npx lint-staged

View File

@@ -237,6 +237,7 @@ You must have the following installed on your system to contribute locally:
- [`Node.js`](https://nodejs.org/en/) (See the root [.node-version](.node-version) file for the required version. You can find a list of tools on [node-version-usage](https://github.com/shadowspawn/node-version-usage) to switch the version of [`Node.js`](https://nodejs.org/en/) based on [.node-version](.node-version).)
- [`Yarn v1 Classic`](https://yarnpkg.com/en/docs/install) (See also [Corepack](#corepack) below.)
- [`python`](https://www.python.org/downloads/) (since we use `node-gyp`. See their [repo](https://github.com/nodejs/node-gyp) for Python version requirements.)
- [`circleci CLI`](https://circleci.com/docs/guides/toolkit/local-cli/) if you intend on editing the CI configuration.
#### Debian/Ubuntu

View File

@@ -1,10 +1,14 @@
const https = require('https')
const fs = require('fs')
const yaml = require('yaml')
const path = require('path')
const CHROME_STABLE_KEY = 'chrome-stable-version'
const CHROME_BETA_KEY = 'chrome-beta-version'
// This is the path to the CircleCI file that contains the browser version anchors
const CIRCLECI_WORKFLOWS_FILEPATH = path.join(__dirname, '../../.circleci/src/workflows/@workflows.yml')
// https://developer.chrome.com/docs/versionhistory/reference/#platform-identifiers
const getLatestVersionData = ({ channel, currentVersion }) => {
const options = {
@@ -37,8 +41,7 @@ const getLatestVersionData = ({ channel, currentVersion }) => {
const getVersions = async ({ core }) => {
try {
// file path is relative to repo root
const doc = yaml.parseDocument(fs.readFileSync('./.circleci/workflows.yml', 'utf8'))
const doc = yaml.parseDocument(fs.readFileSync(CIRCLECI_WORKFLOWS_FILEPATH, 'utf8'))
const currentChromeStable = doc.contents.items.find((item) => item.key.value === CHROME_STABLE_KEY).value.value
const currentChromeBeta = doc.contents.items.find((item) => item.key.value === CHROME_BETA_KEY).value.value
@@ -74,8 +77,7 @@ const getVersions = async ({ core }) => {
}
const checkNeedForBranchUpdate = ({ core, latestStableVersion, latestBetaVersion }) => {
// file path is relative to repo root
const doc = yaml.parseDocument(fs.readFileSync('./.circleci/workflows.yml', 'utf8'))
const doc = yaml.parseDocument(fs.readFileSync(CIRCLECI_WORKFLOWS_FILEPATH, 'utf8'))
const currentChromeStable = doc.contents.items.find((item) => item.key.value === CHROME_STABLE_KEY).value.value
const currentChromeBeta = doc.contents.items.find((item) => item.key.value === CHROME_BETA_KEY).value.value
@@ -87,7 +89,7 @@ const checkNeedForBranchUpdate = ({ core, latestStableVersion, latestBetaVersion
}
const updateBrowserVersionsFile = ({ latestBetaVersion, latestStableVersion }) => {
const doc = yaml.parseDocument(fs.readFileSync('./.circleci/workflows.yml', 'utf8'))
const doc = yaml.parseDocument(fs.readFileSync(CIRCLECI_WORKFLOWS_FILEPATH, 'utf8'))
const currentChromeStableYamlRef = doc.contents.items.find((item) => item.key.value === CHROME_STABLE_KEY)
const currentChromeBetaYamlRef = doc.contents.items.find((item) => item.key.value === CHROME_BETA_KEY)
@@ -95,8 +97,7 @@ const updateBrowserVersionsFile = ({ latestBetaVersion, latestStableVersion }) =
currentChromeStableYamlRef.value.value = latestStableVersion
currentChromeBetaYamlRef.value.value = latestBetaVersion
// file path is relative to repo root
fs.writeFileSync('./.circleci/workflows.yml', yaml.stringify(doc), 'utf8')
fs.writeFileSync(CIRCLECI_WORKFLOWS_FILEPATH, yaml.stringify(doc), 'utf8')
}
const updatePRTitle = async ({ context, github, baseBranch, branchName, description }) => {
@@ -126,4 +127,5 @@ module.exports = {
checkNeedForBranchUpdate,
updateBrowserVersionsFile,
updatePRTitle,
CIRCLECI_WORKFLOWS_FILEPATH,
}

View File

@@ -13,6 +13,7 @@ const {
checkNeedForBranchUpdate,
updateBrowserVersionsFile,
updatePRTitle,
CIRCLECI_WORKFLOWS_FILEPATH,
} = require('../../github-actions/update-browser-versions')
const coreStub = () => {
@@ -29,7 +30,7 @@ const stubChromeVersionResult = (channel, result) => {
const stubRepoVersions = ({ betaVersion, stableVersion }) => {
mockfs({
'./.circleci/workflows.yml': `chrome-stable-version: &chrome-stable-version "${stableVersion}"\nchrome-beta-version: &chrome-beta-version "${betaVersion}"\n`,
[CIRCLECI_WORKFLOWS_FILEPATH]: `chrome-stable-version: &chrome-stable-version "${stableVersion}"\nchrome-beta-version: &chrome-beta-version "${betaVersion}"\n`,
})
}
@@ -254,7 +255,7 @@ describe('update browser version github action', () => {
latestStableVersion: '2.0',
})
expect(fs.writeFileSync).to.be.calledWith('./.circleci/workflows.yml', `chrome-stable-version: &chrome-stable-version "2.0"\nchrome-beta-version: &chrome-beta-version "2.1"\n`, 'utf8')
expect(fs.writeFileSync).to.be.calledWith(CIRCLECI_WORKFLOWS_FILEPATH, `chrome-stable-version: &chrome-stable-version "2.0"\nchrome-beta-version: &chrome-beta-version "2.1"\n`, 'utf8')
})
})