Skip to content

Commit

Permalink
Merge pull request #969 from ckeditor/i/3710-release-via-ci
Browse files Browse the repository at this point in the history
Feature (ci): Created a new binary (`ckeditor5-dev-ci-is-job-triggered-by-member`) script to check if a team member approved a CI job.

Feature (ci): Created a new binary (`ckeditor5-dev-ci-trigger-circle-build`) script to trigger a new pipeline on CircleCI.

Feature (ci): Created new binary (`ckeditor5-dev-ci-circle-disable-auto-cancel-builds`, `ckeditor5-dev-ci-circle-enable-auto-cancel-builds`) scripts to update the redundant workflows option on CircleCI.

Internal: Integrate the release process via CI in the repository.
  • Loading branch information
pomek authored Jul 11, 2024
2 parents 3aa443b + ca2d7c4 commit f77326e
Show file tree
Hide file tree
Showing 24 changed files with 1,162 additions and 40 deletions.
171 changes: 166 additions & 5 deletions .circleci/config.yml
Original file line number Diff line number Diff line change
@@ -1,9 +1,15 @@
version: 2.1

parameters:
triggerCommitHash:
type: string
default: ""
isNightly:
type: boolean
default: false
isRelease:
type: boolean
default: false

commands:
bootstrap_repository_command:
Expand All @@ -13,6 +19,7 @@ commands:
- run:
name: Install dependencies
command: yarn install
- prepare_environment_variables_commands

install_ssh_keys_command:
description: "Install SSH keys"
Expand All @@ -21,6 +28,43 @@ commands:
fingerprints:
- "a0:41:a2:56:c8:7d:3f:29:41:d1:87:92:fd:50:2b:6b"

npm_login_command:
description: "Enable interacting with `npm` using an auth token"
steps:
- run:
name: Login to the npm registry using '.npmrc' file
command: echo "//registry.npmjs.org/:_authToken=\${CKE5_NPM_TOKEN}" > ~/.npmrc

git_credentials_command:
description: "Setup git configuration"
steps:
- run:
name: Setup git configuration
command: |
git config --global user.email "ckeditor-bot@cksource.com"
git config --global user.name "CKEditorBot"
prepare_environment_variables_commands:
description: "Prepare non-secret environment variables"
steps:
- run:
name: Prepare environment variables
command: |
#!/bin/bash
# Non-secret environment variables needed for the pipeline scripts.
CKE5_GITHUB_ORGANIZATION="ckeditor"
CKE5_GITHUB_REPOSITORY="ckeditor5-dev"
CKE5_CIRCLE_APPROVAL_JOB_NAME="release_approval"
CKE5_GITHUB_RELEASE_BRANCH="master"
echo export CKE5_CIRCLE_APPROVAL_JOB_NAME=$CKE5_CIRCLE_APPROVAL_JOB_NAME >> $BASH_ENV
echo export CKE5_GITHUB_RELEASE_BRANCH=$CKE5_GITHUB_RELEASE_BRANCH >> $BASH_ENV
echo export CKE5_GITHUB_ORGANIZATION=$CKE5_GITHUB_ORGANIZATION >> $BASH_ENV
echo export CKE5_GITHUB_REPOSITORY=$CKE5_GITHUB_REPOSITORY >> $BASH_ENV
echo export CKE5_GITHUB_REPOSITORY_SLUG="$CKE5_GITHUB_ORGANIZATION/$CKE5_GITHUB_REPOSITORY" >> $BASH_ENV
echo export CKE5_COMMIT_SHA1=$CIRCLE_SHA1 >> $BASH_ENV

jobs:
notify_ci_failure:
machine: true
Expand Down Expand Up @@ -50,7 +94,7 @@ jobs:
command: yarn ckeditor5-dev-ci-circle-workflow-notifier
no_output_timeout: 1h

main:
validate_and_tests:
machine: true
steps:
- checkout
Expand Down Expand Up @@ -80,22 +124,139 @@ jobs:
name: Upload code coverage
command: cat coverage/lcov.info | ./node_modules/coveralls/bin/coveralls.js

release_prepare:
machine: true
steps:
- checkout
- bootstrap_repository_command
- run:
name: Check if packages are ready to be released
command: yarn run release:prepare-packages --verbose --compile-only

trigger_release_process:
machine: true
steps:
- checkout
- bootstrap_repository_command
- run:
name: Verify if the project is ready to release
command: |
#!/bin/bash
# Do not fail if the Node script ends with non-zero exit code.
set +e
node scripts/ci/is-project-ready-to-release.js
EXIT_CODE=$( echo $? )
if [ ${EXIT_CODE} -eq 1 ];
then
circleci-agent step halt
fi
- run:
name: Trigger the release pipeline
command: ckeditor5-dev-ci-trigger-circle-build

release_project:
machine: true
steps:
- checkout
- bootstrap_repository_command
- run:
name: Verify the trigger commit from the repository
command: |
#!/bin/bash
CKE5_LATEST_COMMIT_HASH=$( git log -n 1 --pretty=format:%H origin/master )
CKE5_TRIGGER_COMMIT_HASH=<< pipeline.parameters.triggerCommitHash >>

if [[ "${CKE5_LATEST_COMMIT_HASH}" != "${CKE5_TRIGGER_COMMIT_HASH}" ]]; then
echo "There is a newer commit in the repository on the \`#master\` branch. Use its build to start the release."
circleci-agent step halt
fi
- npm_login_command
- git_credentials_command
- run:
name: Verify if a releaser triggered the job
command: |
#!/bin/bash
# Do not fail if the Node script ends with non-zero exit code.
set +e

ckeditor5-dev-ci-is-job-triggered-by-member
EXIT_CODE=$( echo $? )

if [ ${EXIT_CODE} -ne 0 ];
then
echo "Aborting the release due to failed verification of the approver (no rights to release)."
circleci-agent step halt
fi
- run:
name: Disable the redundant workflows option
command: ckeditor5-dev-ci-circle-disable-auto-cancel-builds
- run:
name: Prepare the new version to release
command: yarn run release:prepare-packages --verbose
- run:
name: Publish the packages
command: yarn run release:publish-packages --verbose
- run:
name: Enable the redundant workflows option
command: ckeditor5-dev-ci-circle-enable-auto-cancel-builds
when: always
- run:
name: Pack the "release/" directory (in case of failure)
command: |
zip -r ./release.zip ./release
when: always
- store_artifacts:
path: ./release.zip
when: always

workflows:
version: 2
main:
unless: << pipeline.parameters.isNightly >>
when:
and:
- equal: [ false, << pipeline.parameters.isNightly >> ]
- equal: [ false, << pipeline.parameters.isRelease >> ]
jobs:
- main
- validate_and_tests
- release_prepare
- trigger_release_process:
requires:
- validate_and_tests
- release_prepare
filters:
branches:
only:
- master
- notify_ci_failure:
filters:
branches:
only:
- master

release:
when:
and:
- equal: [ false, << pipeline.parameters.isNightly >> ]
- equal: [ true, << pipeline.parameters.isRelease >> ]
jobs:
- release_approval:
type: approval
- release_project:
requires:
- release_approval

nightly:
when: << pipeline.parameters.isNightly >>
when:
and:
- equal: [ true, << pipeline.parameters.isNightly >> ]
- equal: [ false, << pipeline.parameters.isRelease >> ]
jobs:
- main
- validate_and_tests
- notify_ci_failure:
hideAuthor: "true"
filters:
Expand Down
34 changes: 9 additions & 25 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -57,31 +57,15 @@ yarn run coverage

## Releasing packages

### Changelog

1. Fetch all changes and switch to `master`!
2. Execute `npm run changelog`:
* This task checks what changed in each package and bumps the version accordingly. If nothing changed at all, it won't create a new changelog entry. If changes were irrelevant (e.g. only depedencies) it will create an "internal changes" entry.
* Scan the logs which are printed by the tool in search for errors (incorrect changelog entries). Incorrect entries (e.g. ones without the type) are being ignored. You may need to create entries for them manually. This is done directly in `CHANGELOG.md` (in the root directory). Make sure to verify the proposed version after you modify the changelog.
* When unsure what has really changed in this version of a specific package, use `git diff <hash of previous release> packages/ckeditor5-dev-<name>/`.

### Publishing

After generating the changelog, you are able to release the package.

First, you need to bump the version:

```bash
npm run release:prepare-packages
```

After bumping the version, you can publish the changes:

```bash
npm run release:publish-packages
```

Your job's done. You can go now to `ckeditor5`, remove `yarn.lock`, potentially update entries in `package.json`, run `yarn install` and commit that as `"Internal: Updated dependencies."`.
The release process is automated via CircleCI. Before you start, you need to prepare the changelog entries.

1. Make sure the `#master` branch is up-to-date: `git fetch && git checkout master && git pull`.
1. Prepare a release branch: `git checkout -b release-[YYYY-MM-DD]` where `YYYY-MM-DD` is the current day.
1. Generate the changelog entries: `yarn run changelog --branch release-[YYYY-MM-DD]`.
* This task checks what changed in each package and bumps the version accordingly. If nothing changes at all, it won't create a new changelog entry. If changes were irrelevant (e.g., only dependencies), it would make an "_internal changes_" entry.
* Scan the logs printed by the tool to search for errors (incorrect changelog entries). Incorrect entries (e.g., ones without the type) should be addressed. You may need to create entries for them manually. This is done directly in CHANGELOG.md (in the root directory). Make sure to verify the proposed version after you modify the changelog.
1. Commit all changes and prepare a new pull request targeting the `#master` branch.
1. Ping the @ckeditor/ckeditor-5-devops team to review the pull request and trigger the release process.

## License

Expand Down
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,8 @@
"lint-staged": "^10.2.4",
"listr2": "^6.5.0",
"mocha": "^7.1.2",
"nyc": "^15.1.0"
"nyc": "^15.1.0",
"semver": "^7.5.3"
},
"engines": {
"node": ">=18.0.0"
Expand Down
49 changes: 49 additions & 0 deletions packages/ckeditor5-dev-ci/bin/circle-disable-auto-cancel-builds.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
#!/usr/bin/env node

/**
* @license Copyright (c) 2003-2024, CKSource Holding sp. z o.o. All rights reserved.
* For licensing, see LICENSE.md.
*/

'use strict';

const circleUpdateAutoCancelBuilds = require( '../lib/circle-update-auto-cancel-builds' );

/**
* This script updates CircleCI settings to disable the "Auto-cancel redundant workflows" option.
*
* It's needed when triggering a release process via CI to avoid canceling the release workflow by pushing
* a new commit (the released one) that will trigger a new pipeline.
*
* In order to integrate the action in your pipeline, you need prepare a few environment variables:
*
* - CKE5_CIRCLE_TOKEN - an authorization token to talk to CircleCI REST API.
* - CKE5_GITHUB_ORGANIZATION - your GitHub organization.
* - CKE5_GITHUB_REPOSITORY - your GitHub repository.
*
* Example usage:
* CKE5_CIRCLE_TOKEN=... ckeditor5-dev-ci-circle-disable-auto-cancel-builds
*/

const {
CKE5_CIRCLE_TOKEN,
CKE5_GITHUB_ORGANIZATION,
CKE5_GITHUB_REPOSITORY
} = process.env;

const options = {
circleToken: CKE5_CIRCLE_TOKEN,
githubOrganization: CKE5_GITHUB_ORGANIZATION,
githubRepository: CKE5_GITHUB_REPOSITORY,
newValue: false
};

circleUpdateAutoCancelBuilds( options )
.then( () => {
console.log( 'Auto-cancel redundant workflows is now disabled.' );
} )
.catch( err => {
console.error( err );

process.exit( 1 );
} );
49 changes: 49 additions & 0 deletions packages/ckeditor5-dev-ci/bin/circle-enable-auto-cancel-builds.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
#!/usr/bin/env node

/**
* @license Copyright (c) 2003-2024, CKSource Holding sp. z o.o. All rights reserved.
* For licensing, see LICENSE.md.
*/

'use strict';

const circleUpdateAutoCancelBuilds = require( '../lib/circle-update-auto-cancel-builds' );

/**
* This script updates CircleCI settings to enable the "Auto-cancel redundant workflows" option.
*
* It should be done only if a release workflow uses the `ckeditor5-dev-ci-circle-disable-auto-cancel-builds`
* script to disable the same option.
*
* In order to integrate the action in your pipeline, you need prepare a few environment variables:
*
* - CKE5_CIRCLE_TOKEN - an authorization token to talk to CircleCI REST API.
* - CKE5_GITHUB_ORGANIZATION - your GitHub organization.
* - CKE5_GITHUB_REPOSITORY - your GitHub repository.
*
* Example usage:
* CKE5_CIRCLE_TOKEN=... ckeditor5-dev-ci-circle-enable-auto-cancel-builds
*/

const {
CKE5_CIRCLE_TOKEN,
CKE5_GITHUB_ORGANIZATION,
CKE5_GITHUB_REPOSITORY
} = process.env;

const options = {
circleToken: CKE5_CIRCLE_TOKEN,
githubOrganization: CKE5_GITHUB_ORGANIZATION,
githubRepository: CKE5_GITHUB_REPOSITORY,
newValue: true
};

circleUpdateAutoCancelBuilds( options )
.then( () => {
console.log( 'Auto-cancel redundant workflows is now enabled.' );
} )
.catch( err => {
console.error( err );

process.exit( 1 );
} );
Loading

0 comments on commit f77326e

Please sign in to comment.