.circleci/config.yml
# This config is equivalent to both the '.circleci/extended/orb-free.yml' and the base '.circleci/config.yml'
version: 2.1
x-params:
node-version-non-default: &test-matrix-nodeversion-nondefault ["14.19.3", "18.4.0"]
node-version-default: &test-matrix-nodeversion-default "16.16.0"
test-matrix: ¶ms-test-matrix
parameters: &test-matrix
# os: &test-matrix-os [&test-matrix-os-default linux, macos, windows]
os: &test-matrix-os [&test-matrix-os-default linux, windows]
node-version: &test-matrix-nodeversion [ "16.16.0", "14.19.3", "18.4.0" ] # !FORMAT node-version: &test-matrix-nodeversion [ ${*test-matrix-nodeversion-default}, ${...*test-matrix-nodeversion-nondefault} ]
# Orbs are reusable packages of CircleCI configuration that you may share across projects, enabling you to create encapsulated, parameterized commands, jobs, and executors that can be used across multiple projects.
# See: https://circleci.com/docs/2.0/orb-intro/
orbs:
node: circleci/node@5.2.0
knodes-typedoc-orb:
orbs:
node: circleci/node@5.2.0
commands:
install:
parameters:
os:
type: string
type:
default: clean-install
type: string
steps:
- when:
condition: { equal: [windows, <<parameters.os>>] }
steps:
- node/install-packages:
override-ci-command: npm run ci:<<parameters.type>>
cache-path: C:\Users\circleci\AppData\Roaming\npm-cache
cache-version: v1-<<parameters.os>>
- unless:
condition: { equal: [windows, <<parameters.os>>] }
steps:
- node/install-packages:
override-ci-command: npm run ci:<<parameters.type>>
cache-version: v1-<<parameters.os>>
codeclimate-install-only:
steps:
- run:
name: Install Code Climate Test Reporter
command: |
curl -L https://codeclimate.com/downloads/test-reporter/test-reporter-latest-linux-amd64 > ./cc-test-reporter
chmod +x ./cc-test-reporter
codeclimate-prebuild:
steps:
- codeclimate-install-only
- run:
name: Run Code Climate test-reporter `before-build`
command: ./cc-test-reporter before-build
coverage-arrange:
parameters:
os:
type: string
coverageJson:
type: string
buildId:
type: string
steps:
- when:
condition:
equal: [<<parameters.os>>, "windows"]
steps:
- run:
name: Normalize windows report
command: |
set -eo pipefail
for file in "coverage/coverage-summary.json" "<<parameters.coverageJson>>"; do
cat $file |
sed 's|C:\\\\\\\\Users\\\\\\\\circleci\\\\\\\\project|/home/circleci/project|g' |
sed 's|\\\\\\\\|/|g' > $file
done
- run:
name: Move files to use buildId <<parameters.buildId>>
command: |
set -eo pipefail
mv EXIT_CODE coverage/EXIT_CODE_<<parameters.buildId>>
mv coverage/coverage-summary.json coverage/coverage-summary-<<parameters.buildId>>.json
mv <<parameters.coverageJson>> coverage/coverage-part-<<parameters.buildId>>.json
- persist_to_workspace:
root: .
paths:
- coverage/coverage-part-*.json
- coverage/EXIT_CODE_*
- store_artifacts:
path: coverage
stub-bins:
parameters:
bins:
type: string
steps:
- run:
name: Stub bins
command: |
for bin in <<parameters.bins>>; do
bin_path=$(npx which $bin)
if ! [ -z "$HOMEDRIVE" ]; then
echo "Unsupported Windows"
exit 1
fi
echo "Stubbing ${bin_path}"
echo "echo \"STUB $bin\"" > ${bin_path}
chmod +x ${bin_path}
done
executors:
node:
docker:
- image: cimg/node:lts
linux: # a Linux VM running Ubuntu 20.04
machine:
image: ubuntu-2004:202107-02
resource_class: medium
macos: # macos executor running Xcode
macos:
xcode: 14.2.0
resource_class: macos.x86.medium.gen2
windows:
machine:
image: windows-server-2019-vs2019:stable
shell: bash.exe
resource_class: windows.medium
default:
docker:
- image: cimg/base:stable
git:
docker:
- image: alpine/git
jobs:
checkout:
executor: git
resource_class: small
steps:
- attach_workspace:
at: .
- checkout
- persist_to_workspace:
root: .
paths:
- '*'
npm-install:
parameters:
install-type:
type: string
default: clean-install
os:
type: string
node-version:
type: string
executor: <<parameters.os>>
steps:
- when: &node-install-windows
condition:
equal: [ <<parameters.os>>, windows ]
steps:
- run:
name: Install Node <<parameters.node-version>>
shell: cmd.exe
command: |
nvm list
nvm install <<parameters.node-version>>
nvm use <<parameters.node-version>>
node --version
npm --version
- unless: &node-install-non-windows
condition:
equal: [ <<parameters.os>>, windows ]
steps:
- node/install:
node-version: <<parameters.node-version>>
- attach_workspace:
at: .
- knodes-typedoc-orb/install:
type: <<parameters.install-type>>
os: <<parameters.os>>
- run:
name: Update submodule & patch
command: |
git submodule update --init --recursive
npm run tools:patch -- apply --no-stash
- persist_to_workspace:
root: .
paths:
- '.git'
- 'typedoc'
- 'package-lock.json'
- 'node_modules'
- 'packages/*/node_modules'
lint:
executor: node
resource_class: small
environment:
NODE_OPTIONS: --max-old-space-size=2048
steps:
- attach_workspace:
at: .
- run: npm run lint
- run: npm run lint:md
test-sources:
parameters:
os:
type: string
node-version:
type: string
coverage:
type: boolean
default: false
executor: <<parameters.os>>
parallelism: 2
steps:
- when: *node-install-windows
- unless: *node-install-non-windows
- attach_workspace:
at: .
- run:
name: Split tests
command: |
set -eo pipefail
circleci tests glob "./packages/**/*.spec.ts" |
circleci tests split --split-by=timings > TEST_FILES
if ! [ -z $HOMEDRIVE ]; then
sed -i 's:\\\:/:g' TEST_FILES
fi
echo "
Will be ran on following files:
$(cat TEST_FILES)";
# Run tests
- when:
condition: &test-matrix-coverage-condition
and:
- <<parameters.coverage>>
- { equal: [<<parameters.os>>, *test-matrix-os-default ] }
- { equal: [<<parameters.node-version>>, *test-matrix-nodeversion-default ] }
steps:
- run: |
set -eo pipefail
npm run ci:test:coverage -- $(cat TEST_FILES)
echo $? > EXIT_CODE
- knodes-typedoc-orb/coverage-arrange:
os: <<parameters.os>>
coverageJson: coverage/coverage-final.json
buildId: test-sources-${CIRCLE_NODE_INDEX}
- unless:
condition: *test-matrix-coverage-condition
steps:
- run: npm run ci:test -- -- $(cat TEST_FILES)
# Finalize
- store_test_results:
path: ./junit.xml
test-tools:
parameters:
os:
type: string
coverage:
type: boolean
default: false
executor: <<parameters.os>>
steps:
- node/install:
node-version: *test-matrix-nodeversion-default
- attach_workspace:
at: .
- when:
condition: &test-matrix-coverage-tools-condition <<parameters.coverage>>
steps:
- knodes-typedoc-orb/stub-bins:
bins: eslint jest tsc
- run:
name: Run precommit with coverage
command: |
set -eo pipefail
npx nyc --reporter json-summary --reporter json npm run precommit
echo $? > EXIT_CODE
- knodes-typedoc-orb/coverage-arrange:
os: <<parameters.os>>
coverageJson: coverage/coverage-final.json
buildId: test-tools-<<parameters.os>>
- unless:
condition: *test-matrix-coverage-tools-condition
steps:
- knodes-typedoc-orb/stub-bins:
bins: eslint jest tsc typedoc
- run:
name: Run precommit
command: npm run precommit
build:
parameters:
os:
type: string
node-version:
type: string
executor: <<parameters.os>>
steps:
- node/install:
node-version: <<parameters.node-version>>
- attach_workspace:
at: .
- run: |
npm run build
mkdir dists
npm pack -ws --pack-destination dists
for file in $(find ./dists -name '*.tgz'); do
mkdir -p dists-content/$(basename $file .tgz)
tar -xzf $file -C dists-content/$(basename $file .tgz)
done
- store_artifacts:
path: ./dists
- store_artifacts:
path: ./dists-content
- persist_to_workspace:
root: .
paths:
- ./packages/**
infer-version:
executor: node
resource_class: small
steps:
- attach_workspace:
at: .
- run:
name: Maybe abort ci
command: |
npm run tools:infer-next-version --silent > RELEASE_TYPE
echo "Should release $(cat ./RELEASE_TYPE)"
- persist_to_workspace:
root: .
paths:
- RELEASE_TYPE
- run:
name: Check files
command: npm publish --dry-run
do-release:
executor: node
resource_class: small
steps:
- attach_workspace:
at: .
- run:
name: Config git
command: |
git config --global user.email "Knodes-publish-bot@users.noreply.github.com"
git config --global user.name "Knodes-publish-bot"
- run:
name: Run standard-version
command: |
release_type="$(cat ./RELEASE_TYPE)"
if [ "${release_type}" != "NONE" ]; then
npm run tools:release -- ${release_type}
fi
- run:
name: Prepare archive
command: |
ARCHIVE="$(npm pack --ignore-scripts --silent --workspaces)"
echo "${ARCHIVE}" > ARCHIVE
- persist_to_workspace:
root: .
paths:
- .git
- docs
- VERSION
- CHANGELOG.md
- README.md
- package.json
- package-lock.json
- ARCHIVE
- '*.tgz'
github-push:
executor: git
resource_class: small
steps:
- attach_workspace:
at: .
- run:
name: Config git
command: |
git config --global user.email "Knodes-publish-bot@users.noreply.github.com"
git config --global user.name "Knodes-publish-bot"
- run:
name: Push branch & tag
command: |
git remote set-url origin https://$CIRCLE_PROJECT_USERNAME:$GITHUB_AUTH_SECRET@github.com/$CIRCLE_PROJECT_USERNAME/$CIRCLE_PROJECT_REPONAME
git push --follow-tags --set-upstream origin $CIRCLE_BRANCH
github-release:
executor: default
resource_class: small
steps:
- attach_workspace:
at: .
- run:
name: Install GitHub CLI
command: | # From https://circleci.com/developer/orbs/orb/circleci/github-cli#orb-source
#!/bin/bash
# set smart sudo
if [[ $EUID == 0 ]]; then export SUDO=""; else export SUDO="sudo"; fi
# Get auth token
export GITHUB_TOKEN=${GITHUB_AUTH_SECRET}
[ -z "${GITHUB_TOKEN}" ] && echo "A GitHub token must be supplied." && exit 1
echo "export GITHUB_TOKEN=\"${GITHUB_TOKEN}\"" >> "$BASH_ENV"
# Define current platform
if [[ "$(uname -s)" == "Linux" && "$(uname -m)" == "x86_64" ]]; then
export SYS_ENV_PLATFORM=linux_x86
else
echo "This platform appears to be unsupported."
uname -a
exit 1
fi
# If not installed
if ! command -v gh >/dev/null 2>&1; then
GH_CLI_VERSION=2.0.0
echo "Installing the GitHub CLI"
case $SYS_ENV_PLATFORM in
linux_x86)
curl -sSL "https://github.com/cli/cli/releases/download/v${GH_CLI_VERSION}/gh_${GH_CLI_VERSION}_linux_amd64.deb" -o "gh-cli.deb"
$SUDO apt install ./gh-cli.deb
rm gh-cli.deb
;;
*)
echo "This orb does not currently support your platform. If you believe it should, please consider opening an issue on the GitHub repository:"
echo "https://github.com/CircleCI-Public/github-cli-orb"
exit 1
;;
esac
# Validate install.
echo
echo "GH CLI installed"
command -v gh
else
echo "GH CLI is already installed."
fi
# Authenticate
echo
echo "Authenticating GH CLI"
git config --global credential.https://github.com.helper ''
git config --global --add credential.https://github.com.helper '!'"$(which gh) auth git-credential"
gh auth status
# Configure
echo
echo "Disabling interactive prompts for GH CLI"
gh config set prompt disabled
- run:
name: Publish GitHub release
command: |-
#!/bin/bash
ARCHIVE="$(cat ./ARCHIVE)"
VERSION="$(cat ./VERSION)"
BODY="$(git diff HEAD^...HEAD CHANGELOG.md | sed '0,/^@@.*@@$/d' | grep -oP '^\+\K.*$' | sed '0,/^### \[.*$/d')"
if ! [ -z "$(cat ./RELEASE_TYPE)" ]; then
set -- "$@" --prerelease
fi
gh release create "${VERSION}" --target ${CIRCLE_BRANCH} --notes "${BODY}" "$@" ./{${ARCHIVE},package.json,package-lock.json,README.md,LICENSE,CHANGELOG.md}
npm-publish:
executor: node
resource_class: small
steps:
- attach_workspace:
at: .
- run:
name: Authenticate with registry
command: echo "//registry.npmjs.org/:_authToken=$NPM_TOKEN" > ./.npmrc
- run:
name: Publish package
command: |
release_type="$(cat ./RELEASE_TYPE)"
if [ -z ${release_type} ]; then
npm publish
else
npm publish --tag ${release_type}
fi
git-merge-develop:
executor: git
resource_class: small
steps:
- attach_workspace:
at: .
- run:
name: Config git
command: |
git config --global user.email "Knodes-autosync-bot@users.noreply.github.com"
git config --global user.name "Knodes-autosync-bot"
- run:
name: Merge to develop
command: |
git remote set-url origin https://$CIRCLE_PROJECT_USERNAME:$GITHUB_AUTH_SECRET@github.com/$CIRCLE_PROJECT_USERNAME/$CIRCLE_PROJECT_REPONAME
git merge $CIRCLE_BRANCH origin/develop -m "ci(auto-merge): auto merge $CIRCLE_BRANCH
[skip ci]"
git push --set-upstream origin develop
codeclimate-upload:
executor: node
resource_class: small
steps:
- attach_workspace:
at: .
- knodes-typedoc-orb/codeclimate-install-only
- run:
name: Merge coverages & clean
command: |
exit_code=$(cat coverage/EXIT_CODE_* | sort | tail -1)
rm coverage/EXIT_CODE_*
PARTS=$(find coverage -name '*.json')
echo "Running coverage report by merging ${PARTS}"
mv coverage coverage-tmp
npx nyc report --reporter lcov --reporter json-summary --temp-dir coverage-tmp
./cc-test-reporter after-build --coverage-input-type lcov --exit-code $(echo ${exit_code} | sort | tail -f)
- store_artifacts:
path: coverage
# Invoke jobs via workflows
# See: https://circleci.com/docs/2.0/configuration-reference/#workflows
workflows:
renovate: # Workflow ran only on `renovate/*`
when:
matches: { pattern: "^renovate/.+$", value: <<pipeline.git.branch>> }
jobs:
- checkout
- npm-install:
matrix:
parameters:
os: *test-matrix-os
node-version: *test-matrix-nodeversion-default
requires:
- checkout
- build:
os: *test-matrix-os-default
node-version: *test-matrix-nodeversion-default
requires:
- npm-install-linux # !FORMAT - npm-install-${*test-matrix-os-default}
- lint:
requires:
- npm-install-linux # !FORMAT - npm-install-${*test-matrix-os-default}
- test-sources:
matrix:
parameters:
os: *test-matrix-os
node-version: *test-matrix-nodeversion-default
requires:
- npm-install-<<matrix.os>>
- test-tools:
name: test-tools-<<matrix.os>>
matrix:
parameters:
os: *test-matrix-os
exclude:
- os: windows
requires:
- npm-install-<<matrix.os>>
check-partial: # Workflow ran on all custom branches (no `main`, `develop` or `renovate/*`)
unless:
or:
- matches: { pattern: "^main$", value: <<pipeline.git.branch>> }
- matches: { pattern: "^develop$", value: <<pipeline.git.branch>> }
- matches: { pattern: "^renovate/.+$", value: <<pipeline.git.branch>> }
jobs:
- checkout
- npm-install:
matrix:
parameters:
os: *test-matrix-os
install-type: install
node-version: *test-matrix-nodeversion-default
requires:
- checkout
- build:
os: *test-matrix-os-default
node-version: *test-matrix-nodeversion-default
requires:
- npm-install-linux # !FORMAT - npm-install-${*test-matrix-os-default}
- lint:
requires:
- npm-install-linux # !FORMAT - npm-install-${*test-matrix-os-default}
- test-sources:
coverage: true
matrix:
parameters:
os: *test-matrix-os
node-version: *test-matrix-nodeversion-default
requires:
- npm-install-<<matrix.os>>
- test-tools:
name: test-tools-<<matrix.os>>-STUB
matrix:
parameters:
os: *test-matrix-os
exclude:
- os: *test-matrix-os-default
- os: windows
requires:
- npm-install-<<matrix.os>>
- test-tools:
name: test-tools-linux-coverage # !FORMAT name: test-tools-${!*test-matrix-os-default}-coverage
os: *test-matrix-os-default
coverage: true
requires:
- npm-install-linux # !FORMAT - npm-install-${!*test-matrix-os-default}
- build
- codeclimate-upload:
requires:
- test-sources-linux # !FORMAT - test-sources-${*test-matrix-os-default}
- test-tools-linux-coverage # !FORMAT - test-tools-${!*test-matrix-os-default}-coverage
check-full: # Workflow ran on `main` & `develop`
when:
or:
- matches: { pattern: "^main$", value: <<pipeline.git.branch>> }
- matches: { pattern: "^develop$", value: <<pipeline.git.branch>> }
jobs:
- checkout
- npm-install:
matrix:
parameters:
os: *test-matrix-os
install-type: install
node-version: *test-matrix-nodeversion-default
requires:
- checkout
- build:
os: *test-matrix-os-default
node-version: *test-matrix-nodeversion-default
requires:
- npm-install-linux # !FORMAT - npm-install-${*test-matrix-os-default}
- lint:
requires:
- npm-install-linux # !FORMAT - npm-install-${*test-matrix-os-default}
- test-sources:
coverage: true
matrix: *params-test-matrix
requires:
- npm-install-<<matrix.os>>
- test-tools:
name: test-tools-<<matrix.os>>-STUB
matrix:
parameters:
os: *test-matrix-os
exclude:
- os: *test-matrix-os-default
- os: windows
requires:
- npm-install-<<matrix.os>>
- test-tools:
name: test-tools-linux-coverage # !FORMAT name: test-tools-${!*test-matrix-os-default}-coverage
os: *test-matrix-os-default
coverage: true
requires:
- npm-install-linux # !FORMAT - npm-install-${!*test-matrix-os-default}
- build
- codeclimate-upload:
requires:
- test-sources-16.16.0-linux # !FORMAT - test-sources-${!*test-matrix-nodeversion-default}-${*test-matrix-os-default}
- test-tools-linux-coverage # !FORMAT - test-tools-${!*test-matrix-os-default}-coverage
# - test-tools-16.16.0-macos # !FORMAT # - test-tools-${!*test-matrix-nodeversion-default}-macos
# - test-tools-16.16.0-windows # !FORMAT # - test-tools-${!*test-matrix-nodeversion-default}-windows
# publish: # Workflow ran only on `main` & `develop`
# when:
# or:
# - equal: [ main, <<pipeline.git.branch>> ]
# - equal: [ develop, <<pipeline.git.branch>> ]
# jobs:
# - npm-ci-install
# - codeclimate-before
# - test:
# requires:
# - npm-ci-install
# - codeclimate-before
# - codeclimate-after:
# requires:
# - test
# - build:
# requires:
# - npm-ci-install
# - infer-version:
# requires:
# - build
# - test
# - Confirm new release:
# type: approval
# requires:
# - infer-version
# - do-release:
# requires:
# - Confirm new release
# - npm-publish:
# requires:
# - do-release
# - github-push:
# requires:
# - do-release
# - github-release:
# requires:
# - github-push
# - git-merge-develop:
# filters:
# branches:
# only: main
# requires:
# - github-push