1. version: 2.1
    
  2. 
    
  3. aliases:
    
  4.   - &docker
    
  5.     - image: cimg/openjdk:18.0-node
    
  6. 
    
  7.   - &environment
    
  8.     TZ: /usr/share/zoneinfo/America/Los_Angeles
    
  9. 
    
  10.   - &restore_yarn_cache_fixtures_dom
    
  11.     restore_cache:
    
  12.       name: Restore yarn cache for fixtures/dom
    
  13.       keys:
    
  14.         - v2-yarn_cache-{{ arch }}-{{ checksum "yarn.lock" }}-fixtures/dom
    
  15. 
    
  16.   - &yarn_install_fixtures_dom
    
  17.     run:
    
  18.       name: Install dependencies in fixtures/dom
    
  19.       working_directory: fixtures/dom
    
  20.       command: yarn install --frozen-lockfile --cache-folder ~/.cache/yarn
    
  21. 
    
  22.   - &yarn_install_fixtures_dom_retry
    
  23.     run:
    
  24.       name: Install dependencies in fixtures/dom (retry)
    
  25.       when: on_fail
    
  26.       working_directory: fixtures/dom
    
  27.       command: yarn install --frozen-lockfile --cache-folder ~/.cache/yarn
    
  28. 
    
  29.   - &save_yarn_cache_fixtures_dom
    
  30.     save_cache:
    
  31.       name: Save yarn cache for fixtures/dom
    
  32.       key: v2-yarn_cache-{{ arch }}-{{ checksum "yarn.lock" }}-fixtures/dom
    
  33.       paths:
    
  34.         - ~/.cache/yarn
    
  35. 
    
  36.   - &TEST_PARALLELISM 20
    
  37. 
    
  38.   - &attach_workspace
    
  39.     at: build
    
  40. 
    
  41. commands:
    
  42.   setup_node_modules:
    
  43.     description: "Restore node_modules"
    
  44.     steps:
    
  45.       - restore_cache:
    
  46.           name: Restore yarn cache
    
  47.           keys:
    
  48.             - v2-yarn_cache-{{ arch }}-{{ checksum "yarn.lock" }}
    
  49.       - run:
    
  50.           name: Install dependencies
    
  51.           command: |
    
  52.             yarn install --frozen-lockfile --cache-folder ~/.cache/yarn
    
  53.             if [ $? -ne 0 ]; then
    
  54.               yarn install --frozen-lockfile --cache-folder ~/.cache/yarn
    
  55.             fi
    
  56.           environment:
    
  57.           # If we start needing the Electron binary, please ensure the binary is cached in CI following https://www.electronjs.org/docs/latest/tutorial/installation
    
  58.             ELECTRON_SKIP_BINARY_DOWNLOAD: 1
    
  59.       - save_cache:
    
  60.           name: Save yarn cache
    
  61.           key: v2-yarn_cache-{{ arch }}-{{ checksum "yarn.lock" }}
    
  62.           paths:
    
  63.             - ~/.cache/yarn
    
  64. 
    
  65. # The CircleCI API doesn't yet support triggering a specific workflow, but it
    
  66. # does support triggering a pipeline. So as a workaround you can triggger the
    
  67. # entire pipeline and use parameters to disable everything except the workflow
    
  68. # you want. CircleCI recommends this workaround here:
    
  69. # https://support.circleci.com/hc/en-us/articles/360050351292-How-to-trigger-a-workflow-via-CircleCI-API-v2-
    
  70. parameters:
    
  71.   # This is only set when triggering the CI pipeline via an API request.
    
  72.   prerelease_commit_sha:
    
  73.     type: string
    
  74.     default: ''
    
  75. 
    
  76. jobs:
    
  77.   yarn_lint:
    
  78.     docker: *docker
    
  79.     environment: *environment
    
  80. 
    
  81.     steps:
    
  82.       - checkout
    
  83.       - setup_node_modules
    
  84.       - run: node ./scripts/prettier/index
    
  85.       - run: node ./scripts/tasks/eslint
    
  86.       - run: ./scripts/circleci/check_license.sh
    
  87.       - run: ./scripts/circleci/check_modules.sh
    
  88.       - run: ./scripts/circleci/test_print_warnings.sh
    
  89. 
    
  90.   yarn_flow:
    
  91.     docker: *docker
    
  92.     environment: *environment
    
  93.     parallelism: 5
    
  94. 
    
  95.     steps:
    
  96.       - checkout
    
  97.       - setup_node_modules
    
  98.       - run: node ./scripts/tasks/flow-ci
    
  99. 
    
  100.   scrape_warning_messages:
    
  101.     docker: *docker
    
  102.     environment: *environment
    
  103. 
    
  104.     steps:
    
  105.       - checkout
    
  106.       - setup_node_modules
    
  107.       - run:
    
  108.           command: |
    
  109.             mkdir -p ./build
    
  110.             node ./scripts/print-warnings/print-warnings.js > build/WARNINGS
    
  111.       - persist_to_workspace:
    
  112.           root: .
    
  113.           paths:
    
  114.             - build
    
  115. 
    
  116.   yarn_build:
    
  117.     docker: *docker
    
  118.     environment: *environment
    
  119.     parallelism: 40
    
  120.     steps:
    
  121.       - checkout
    
  122.       - setup_node_modules
    
  123.       - run: yarn build
    
  124.       - persist_to_workspace:
    
  125.           root: .
    
  126.           paths:
    
  127.             - build
    
  128. 
    
  129.   download_build:
    
  130.     docker: *docker
    
  131.     environment: *environment
    
  132.     parameters:
    
  133.       revision:
    
  134.         type: string
    
  135.     steps:
    
  136.       - checkout
    
  137.       - setup_node_modules
    
  138.       - run:
    
  139.           name: Download artifacts for revision
    
  140.           command: |
    
  141.               git fetch origin main
    
  142.               cd ./scripts/release && yarn && cd ../../
    
  143.               scripts/release/download-experimental-build.js --commit=<< parameters.revision >> --allowBrokenCI
    
  144.       - persist_to_workspace:
    
  145.           root: .
    
  146.           paths:
    
  147.             - build
    
  148. 
    
  149.   download_base_build_for_sizebot:
    
  150.     docker: *docker
    
  151.     environment: *environment
    
  152.     steps:
    
  153.       - checkout
    
  154.       - setup_node_modules
    
  155.       - run:
    
  156.           name: Download artifacts for base revision
    
  157.           command: |
    
  158.             git fetch origin main
    
  159.             cd ./scripts/release && yarn && cd ../../
    
  160.             scripts/release/download-experimental-build.js --commit=$(git merge-base HEAD origin/main) --allowBrokenCI
    
  161.             mv ./build ./base-build
    
  162. 
    
  163.       - run:
    
  164.           # TODO: The `download-experimental-build` script copies the npm
    
  165.           # packages into the `node_modules` directory. This is a historical
    
  166.           # quirk of how the release script works. Let's pretend they
    
  167.           # don't exist.
    
  168.           name: Delete extraneous files
    
  169.           command: rm -rf ./base-build/node_modules
    
  170. 
    
  171.       - persist_to_workspace:
    
  172.           root: .
    
  173.           paths:
    
  174.             - base-build
    
  175. 
    
  176.   process_artifacts_combined:
    
  177.     docker: *docker
    
  178.     environment: *environment
    
  179.     steps:
    
  180.       - checkout
    
  181.       - attach_workspace:
    
  182.           at: .
    
  183.       - setup_node_modules
    
  184.       - run: echo "<< pipeline.git.revision	>>" >> build/COMMIT_SHA
    
  185.         # Compress build directory into a single tarball for easy download
    
  186.       - run: tar -zcvf ./build.tgz ./build
    
  187.         # TODO: Migrate scripts to use `build` directory instead of `build2`
    
  188.       - run: cp ./build.tgz ./build2.tgz
    
  189.       - store_artifacts:
    
  190.           path: ./build2.tgz
    
  191.       - store_artifacts:
    
  192.           path: ./build.tgz
    
  193. 
    
  194.   sizebot:
    
  195.     docker: *docker
    
  196.     environment: *environment
    
  197.     steps:
    
  198.       - checkout
    
  199.       - attach_workspace:
    
  200.           at: .
    
  201.       - run: echo "<< pipeline.git.revision	>>" >> build/COMMIT_SHA
    
  202.       - setup_node_modules
    
  203.       - run:
    
  204.           command: node ./scripts/tasks/danger
    
  205. 
    
  206.   build_devtools_and_process_artifacts:
    
  207.     docker: *docker
    
  208.     environment: *environment
    
  209.     steps:
    
  210.       - checkout
    
  211.       - attach_workspace:
    
  212.           at: .
    
  213.       - setup_node_modules
    
  214.       - run:
    
  215.           environment:
    
  216.             RELEASE_CHANNEL: experimental
    
  217.           command: ./scripts/circleci/pack_and_store_devtools_artifacts.sh
    
  218.       - store_artifacts:
    
  219.           path: ./build/devtools.tgz
    
  220. 
    
  221.   run_devtools_e2e_tests:
    
  222.     docker: *docker
    
  223.     environment: *environment
    
  224.     steps:
    
  225.       - checkout
    
  226.       - attach_workspace:
    
  227.           at: .
    
  228.       - setup_node_modules
    
  229.       - run:
    
  230.           name: Playwright install deps
    
  231.           command: |
    
  232.             npx playwright install
    
  233.             sudo npx playwright install-deps
    
  234.       - run:
    
  235.           environment:
    
  236.             RELEASE_CHANNEL: experimental
    
  237.           command: ./scripts/circleci/run_devtools_e2e_tests.js
    
  238. 
    
  239.   run_devtools_tests_for_versions:
    
  240.     docker: *docker
    
  241.     environment: *environment
    
  242.     parallelism: *TEST_PARALLELISM
    
  243.     parameters:
    
  244.       version:
    
  245.         type: string
    
  246.     steps:
    
  247.       - checkout
    
  248.       - attach_workspace:
    
  249.           at: .
    
  250.       - setup_node_modules
    
  251.       - run: ./scripts/circleci/download_devtools_regression_build.js << parameters.version >> --replaceBuild
    
  252.       - run: node ./scripts/jest/jest-cli.js --build --project devtools --release-channel=experimental --reactVersion << parameters.version >> --ci
    
  253. 
    
  254.   run_devtools_e2e_tests_for_versions:
    
  255.     docker: *docker
    
  256.     environment: *environment
    
  257.     parallelism: *TEST_PARALLELISM
    
  258.     parameters:
    
  259.       version:
    
  260.         type: string
    
  261.     steps:
    
  262.       - checkout
    
  263.       - attach_workspace:
    
  264.           at: .
    
  265.       - setup_node_modules
    
  266.       - run:
    
  267.           name: Playwright install deps
    
  268.           command: |
    
  269.             npx playwright install
    
  270.             sudo npx playwright install-deps
    
  271.       - run: ./scripts/circleci/download_devtools_regression_build.js << parameters.version >>
    
  272.       - run:
    
  273.           environment:
    
  274.             RELEASE_CHANNEL: experimental
    
  275.           command: ./scripts/circleci/run_devtools_e2e_tests.js << parameters.version >>
    
  276.       - run:
    
  277.           name: Cleanup build regression folder
    
  278.           command: rm -r ./build-regression
    
  279.       - store_artifacts:
    
  280.           path: ./tmp/screenshots
    
  281. 
    
  282.   yarn_lint_build:
    
  283.     docker: *docker
    
  284.     environment: *environment
    
  285.     steps:
    
  286.       - checkout
    
  287.       - attach_workspace:
    
  288.           at: .
    
  289.       - setup_node_modules
    
  290.       - run: yarn lint-build
    
  291. 
    
  292.   yarn_check_release_dependencies:
    
  293.     docker: *docker
    
  294.     environment: *environment
    
  295.     steps:
    
  296.       - checkout
    
  297.       - attach_workspace:
    
  298.           at: .
    
  299.       - setup_node_modules
    
  300.       - run: yarn check-release-dependencies
    
  301. 
    
  302. 
    
  303.   check_error_codes:
    
  304.     docker: *docker
    
  305.     environment: *environment
    
  306.     steps:
    
  307.       - checkout
    
  308.       - attach_workspace: *attach_workspace
    
  309.       - setup_node_modules
    
  310.       - run:
    
  311.           name: Search build artifacts for unminified errors
    
  312.           command: |
    
  313.             yarn extract-errors
    
  314.             git diff --quiet || (echo "Found unminified errors. Either update the error codes map or disable error minification for the affected build, if appropriate." && false)
    
  315. 
    
  316.   check_generated_fizz_runtime:
    
  317.     docker: *docker
    
  318.     environment: *environment
    
  319.     steps:
    
  320.       - checkout
    
  321.       - attach_workspace: *attach_workspace
    
  322.       - setup_node_modules
    
  323.       - run:
    
  324.           name: Confirm generated inline Fizz runtime is up to date
    
  325.           command: |
    
  326.             yarn generate-inline-fizz-runtime
    
  327.             git diff --quiet || (echo "There was a change to the Fizz runtime. Run `yarn generate-inline-fizz-runtime` and check in the result." && false)
    
  328. 
    
  329.   yarn_test:
    
  330.     docker: *docker
    
  331.     environment: *environment
    
  332.     parallelism: *TEST_PARALLELISM
    
  333.     parameters:
    
  334.       args:
    
  335.         type: string
    
  336.     steps:
    
  337.       - checkout
    
  338.       - setup_node_modules
    
  339.       - run: yarn test <<parameters.args>> --ci
    
  340. 
    
  341.   yarn_test_build:
    
  342.     docker: *docker
    
  343.     environment: *environment
    
  344.     parallelism: *TEST_PARALLELISM
    
  345.     parameters:
    
  346.       args:
    
  347.         type: string
    
  348.     steps:
    
  349.       - checkout
    
  350.       - attach_workspace:
    
  351.           at: .
    
  352.       - setup_node_modules
    
  353.       - run: yarn test --build <<parameters.args>> --ci
    
  354. 
    
  355.   RELEASE_CHANNEL_stable_yarn_test_dom_fixtures:
    
  356.     docker: *docker
    
  357.     environment: *environment
    
  358.     steps:
    
  359.       - checkout
    
  360.       - attach_workspace:
    
  361.           at: .
    
  362.       - setup_node_modules
    
  363.       - *restore_yarn_cache_fixtures_dom
    
  364.       - *yarn_install_fixtures_dom
    
  365.       - *yarn_install_fixtures_dom_retry
    
  366.       - *save_yarn_cache_fixtures_dom
    
  367.       - run:
    
  368.           name: Run DOM fixture tests
    
  369.           environment:
    
  370.             RELEASE_CHANNEL: stable
    
  371.           working_directory: fixtures/dom
    
  372.           command: |
    
  373.             yarn predev
    
  374.             yarn test --maxWorkers=2
    
  375. 
    
  376.   test_fuzz:
    
  377.     docker: *docker
    
  378.     environment: *environment
    
  379.     steps:
    
  380.       - checkout
    
  381.       - setup_node_modules
    
  382.       - run:
    
  383.           name: Run fuzz tests
    
  384.           command: |
    
  385.             FUZZ_TEST_SEED=$RANDOM yarn test fuzz --ci
    
  386.             FUZZ_TEST_SEED=$RANDOM yarn test --prod fuzz --ci
    
  387. 
    
  388.   publish_prerelease:
    
  389.     parameters:
    
  390.       commit_sha:
    
  391.         type: string
    
  392.       release_channel:
    
  393.         type: string
    
  394.       dist_tag:
    
  395.         type: string
    
  396.     docker: *docker
    
  397.     environment: *environment
    
  398.     steps:
    
  399.       - checkout
    
  400.       - setup_node_modules
    
  401.       - run:
    
  402.           name: Run publish script
    
  403.           command: |
    
  404.             git fetch origin main
    
  405.             cd ./scripts/release && yarn && cd ../../
    
  406.             scripts/release/prepare-release-from-ci.js --skipTests -r << parameters.release_channel >> --commit=<< parameters.commit_sha >>
    
  407.             cp ./scripts/release/ci-npmrc ~/.npmrc
    
  408.             scripts/release/publish.js --ci --tags << parameters.dist_tag >>
    
  409. 
    
  410. workflows:
    
  411. 
    
  412.   build_and_test:
    
  413.     unless: << pipeline.parameters.prerelease_commit_sha >>
    
  414.     jobs:
    
  415.       - yarn_flow:
    
  416.           filters:
    
  417.             branches:
    
  418.               ignore:
    
  419.                 - builds/facebook-www
    
  420.       - check_generated_fizz_runtime:
    
  421.           filters:
    
  422.             branches:
    
  423.               ignore:
    
  424.                 - builds/facebook-www
    
  425.       - yarn_lint:
    
  426.           filters:
    
  427.             branches:
    
  428.               ignore:
    
  429.                 - builds/facebook-www
    
  430.       - yarn_test:
    
  431.           filters:
    
  432.             branches:
    
  433.               ignore:
    
  434.                 - builds/facebook-www
    
  435.           matrix:
    
  436.             parameters:
    
  437.               args:
    
  438.                 # Intentionally passing these as strings instead of creating a
    
  439.                 # separate parameter per CLI argument, since it's easier to
    
  440.                 # control/see which combinations we want to run.
    
  441.                 - "-r=stable --env=development"
    
  442.                 - "-r=stable --env=production"
    
  443.                 - "-r=experimental --env=development"
    
  444.                 - "-r=experimental --env=production"
    
  445.                 - "-r=www-classic --env=development --variant=false"
    
  446.                 - "-r=www-classic --env=production --variant=false"
    
  447.                 - "-r=www-classic --env=development --variant=true"
    
  448.                 - "-r=www-classic --env=production --variant=true"
    
  449.                 - "-r=www-modern --env=development --variant=false"
    
  450.                 - "-r=www-modern --env=production --variant=false"
    
  451.                 - "-r=www-modern --env=development --variant=true"
    
  452.                 - "-r=www-modern --env=production --variant=true"
    
  453. 
    
  454.                 # TODO: Test more persistent configurations?
    
  455.                 - '-r=stable --env=development --persistent'
    
  456.                 - '-r=experimental --env=development --persistent'
    
  457.       - yarn_build:
    
  458.           filters:
    
  459.             branches:
    
  460.               ignore:
    
  461.                 - builds/facebook-www
    
  462.       - scrape_warning_messages:
    
  463.           filters:
    
  464.             branches:
    
  465.               ignore:
    
  466.                 - builds/facebook-www
    
  467.       - process_artifacts_combined:
    
  468.           requires:
    
  469.             - scrape_warning_messages
    
  470.             - yarn_build
    
  471.       - yarn_test_build:
    
  472.           requires:
    
  473.             - yarn_build
    
  474.           matrix:
    
  475.             parameters:
    
  476.               args:
    
  477.                 # Intentionally passing these as strings instead of creating a
    
  478.                 # separate parameter per CLI argument, since it's easier to
    
  479.                 # control/see which combinations we want to run.
    
  480.                 - "-r=stable --env=development"
    
  481.                 - "-r=stable --env=production"
    
  482.                 - "-r=experimental --env=development"
    
  483.                 - "-r=experimental --env=production"
    
  484. 
    
  485.                 # Dev Tools
    
  486.                 - "--project=devtools -r=experimental"
    
  487. 
    
  488.                 # TODO: Update test config to support www build tests
    
  489.                 # - "-r=www-classic --env=development --variant=false"
    
  490.                 # - "-r=www-classic --env=production --variant=false"
    
  491.                 # - "-r=www-classic --env=development --variant=true"
    
  492.                 # - "-r=www-classic --env=production --variant=true"
    
  493.                 # - "-r=www-modern --env=development --variant=false"
    
  494.                 # - "-r=www-modern --env=production --variant=false"
    
  495.                 # - "-r=www-modern --env=development --variant=true"
    
  496.                 # - "-r=www-modern --env=production --variant=true"
    
  497. 
    
  498.                 # TODO: Test more persistent configurations?
    
  499.       - download_base_build_for_sizebot:
    
  500.           filters:
    
  501.             branches:
    
  502.               ignore:
    
  503.                 - main
    
  504.                 - builds/facebook-www
    
  505.       - sizebot:
    
  506.           filters:
    
  507.             branches:
    
  508.               ignore:
    
  509.                 - main
    
  510.           requires:
    
  511.             - download_base_build_for_sizebot
    
  512.             - yarn_build
    
  513.       - yarn_lint_build:
    
  514.           requires:
    
  515.             - yarn_build
    
  516.       - yarn_check_release_dependencies:
    
  517.           requires:
    
  518.             - yarn_build
    
  519.       - check_error_codes:
    
  520.           requires:
    
  521.             - yarn_build
    
  522.       - RELEASE_CHANNEL_stable_yarn_test_dom_fixtures:
    
  523.           requires:
    
  524.             - yarn_build
    
  525.       - build_devtools_and_process_artifacts:
    
  526.           requires:
    
  527.             - yarn_build
    
  528.       - run_devtools_e2e_tests:
    
  529.           requires:
    
  530.             - build_devtools_and_process_artifacts
    
  531. 
    
  532.   fuzz_tests:
    
  533.     unless: << pipeline.parameters.prerelease_commit_sha >>
    
  534.     triggers:
    
  535.       - schedule:
    
  536.           # Fuzz tests run hourly
    
  537.           cron: "0 * * * *"
    
  538.           filters:
    
  539.             branches:
    
  540.               only:
    
  541.                 - main
    
  542.     jobs:
    
  543.       - test_fuzz
    
  544. 
    
  545.   devtools_regression_tests:
    
  546.     unless: << pipeline.parameters.prerelease_commit_sha >>
    
  547.     triggers:
    
  548.       - schedule:
    
  549.           # DevTools regression tests run once a day
    
  550.           cron: "0 0 * * *"
    
  551.           filters:
    
  552.             branches:
    
  553.               only:
    
  554.                 - main
    
  555.     jobs:
    
  556.       - download_build:
    
  557.           revision: << pipeline.git.revision >>
    
  558.       - build_devtools_and_process_artifacts:
    
  559.           requires:
    
  560.             - download_build
    
  561.       - run_devtools_tests_for_versions:
    
  562.           requires:
    
  563.             - build_devtools_and_process_artifacts
    
  564.           matrix:
    
  565.             parameters:
    
  566.               version:
    
  567.                 - "16.0"
    
  568.                 - "16.5" # schedule package
    
  569.                 - "16.8" # hooks
    
  570.                 - "17.0"
    
  571.                 - "18.0"
    
  572.       - run_devtools_e2e_tests_for_versions:
    
  573.           requires:
    
  574.             - build_devtools_and_process_artifacts
    
  575.           matrix:
    
  576.             parameters:
    
  577.               version:
    
  578.                 - "16.0"
    
  579.                 - "16.5" # schedule package
    
  580.                 - "16.8" # hooks
    
  581.                 - "17.0"
    
  582.                 - "18.0"
    
  583. 
    
  584.   # Used to publish a prerelease manually via the command line
    
  585.   publish_preleases:
    
  586.     when: << pipeline.parameters.prerelease_commit_sha >>
    
  587.     jobs:
    
  588.       - publish_prerelease:
    
  589.           name: Publish to Canary channel
    
  590.           commit_sha: << pipeline.parameters.prerelease_commit_sha >>
    
  591.           release_channel: stable
    
  592.           # The tags to use when publishing canaries. The main one we should
    
  593.           # always include is "canary" but we can use multiple (e.g. alpha,
    
  594.           # beta, rc). To declare multiple, use a comma-separated string, like
    
  595.           # this:
    
  596.           #   dist_tag: "canary,alpha,beta,rc"
    
  597.           #
    
  598.           # TODO: We currently tag canaries with "next" in addition to "canary"
    
  599.           # because this used to be called the "next" channel and some
    
  600.           # downstream consumers might still expect that tag. We can remove this
    
  601.           # after some time has elapsed and the change has been communicated.
    
  602.           dist_tag: "canary,next"
    
  603.       - publish_prerelease:
    
  604.           name: Publish to Experimental channel
    
  605.           requires:
    
  606.             # NOTE: Intentionally running these jobs sequentially because npm
    
  607.             # will sometimes fail if you try to concurrently publish two
    
  608.             # different versions of the same package, even if they use different
    
  609.             # dist tags.
    
  610.             - Publish to Canary channel
    
  611.           commit_sha: << pipeline.parameters.prerelease_commit_sha >>
    
  612.           release_channel: experimental
    
  613.           dist_tag: experimental
    
  614. 
    
  615.   # Publishes on a cron schedule
    
  616.   publish_preleases_nightly:
    
  617.     unless: << pipeline.parameters.prerelease_commit_sha >>
    
  618.     triggers:
    
  619.       - schedule:
    
  620.           # At 10 minutes past 16:00 on Mon, Tue, Wed, Thu, and Fri
    
  621.           cron: "10 16 * * 1,2,3,4,5"
    
  622.           filters:
    
  623.             branches:
    
  624.               only:
    
  625.                 - main
    
  626.     jobs:
    
  627.       - publish_prerelease:
    
  628.           name: Publish to Canary channel
    
  629.           commit_sha: << pipeline.git.revision >>
    
  630.           release_channel: stable
    
  631.           dist_tag: "canary,next"
    
  632.       - publish_prerelease:
    
  633.           name: Publish to Experimental channel
    
  634.           requires:
    
  635.             # NOTE: Intentionally running these jobs sequentially because npm
    
  636.             # will sometimes fail if you try to concurrently publish two
    
  637.             # different versions of the same package, even if they use different
    
  638.             # dist tags.
    
  639.             - Publish to Canary channel
    
  640.           commit_sha: << pipeline.git.revision >>
    
  641.           release_channel: experimental
    
  642.           dist_tag: experimental