├── .nvmrc ├── .prettierrc.json ├── .github ├── CODEOWNERS ├── PULL_REQUEST_TEMPLATE │ └── PULL_REQUEST.md └── ISSUE_TEMPLATE │ ├── FEATURE_REQUEST.yml │ └── BUG.yml ├── .gitignore ├── .circleci └── config.yml ├── .eslintrc.cjs ├── src ├── index.ts └── lib │ └── CircleCIPipelineTrigger.ts ├── jest.config.ts ├── examples ├── 01-Trigger-Workflow-On-Pull_Request │ ├── README.md │ ├── .github │ │ └── workflows │ │ │ └── main.yml │ └── .circleci │ │ └── config.yml └── 02-Trigger-Workflow-On-Release │ ├── README.md │ ├── .github │ └── workflows │ │ └── main.yml │ └── .circleci │ └── config.yml ├── .husky └── pre-commit ├── __tests__ └── CircleCIPipelineTrigger.test.ts ├── package.json ├── action.yml ├── CONTRIBUTING.md ├── README.md ├── tsconfig.json └── dist └── licenses.txt /.nvmrc: -------------------------------------------------------------------------------- 1 | v16 2 | -------------------------------------------------------------------------------- /.prettierrc.json: -------------------------------------------------------------------------------- 1 | {} 2 | -------------------------------------------------------------------------------- /.github/CODEOWNERS: -------------------------------------------------------------------------------- 1 | @KyleTryon 2 | @CircleCI-Public/cpeng -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules/ 2 | .DS_Store 3 | .idea 4 | .vscode -------------------------------------------------------------------------------- /.circleci/config.yml: -------------------------------------------------------------------------------- 1 | version: 2.1 2 | orbs: 3 | node: circleci/node@5.1.0 4 | workflows: 5 | test: 6 | jobs: 7 | - node/test: 8 | test-results-for: jest 9 | -------------------------------------------------------------------------------- /.eslintrc.cjs: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | extends: ["eslint:recommended", "plugin:@typescript-eslint/recommended"], 3 | parser: "@typescript-eslint/parser", 4 | plugins: ["@typescript-eslint"], 5 | root: true, 6 | }; 7 | -------------------------------------------------------------------------------- /src/index.ts: -------------------------------------------------------------------------------- 1 | import { CircleCIPipelineTrigger } from "./lib/CircleCIPipelineTrigger"; 2 | import { context } from "@actions/github"; 3 | 4 | const trigger = new CircleCIPipelineTrigger(context); 5 | trigger.triggerPipeline(); 6 | -------------------------------------------------------------------------------- /jest.config.ts: -------------------------------------------------------------------------------- 1 | // jest.config.ts 2 | import type { Config } from "@jest/types"; 3 | 4 | const config: Config.InitialOptions = { 5 | preset: "ts-jest", 6 | testEnvironment: "node", 7 | }; 8 | 9 | export default config; 10 | -------------------------------------------------------------------------------- /examples/01-Trigger-Workflow-On-Pull_Request/README.md: -------------------------------------------------------------------------------- 1 | # 01 Trigger Workflow On Pull_Request 2 | 3 | Trigger your CircleCI pipelines on updates to a _pull_request_. 4 | 5 | https://docs.github.com/en/actions/learn-github-actions/events-that-trigger-workflows#pull_request -------------------------------------------------------------------------------- /examples/02-Trigger-Workflow-On-Release/README.md: -------------------------------------------------------------------------------- 1 | # 02 Conditionally Trigger a Workflow on a GitHub Release 2 | 3 | Trigger a specific workflow when a _release_ is created. 4 | 5 | https://docs.github.com/en/actions/learn-github-actions/events-that-trigger-workflows#release -------------------------------------------------------------------------------- /.husky/pre-commit: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | . "$(dirname "$0")/_/husky.sh" 3 | 4 | npm run lint && npm run format && npm run build 5 | # Stage modified files 6 | ## https://github.com/CircleCI-Public/trigger-circleci-pipeline-action/pull/51#discussion_r1152164608 7 | # git add $(git diff --name-only) -------------------------------------------------------------------------------- /examples/02-Trigger-Workflow-On-Release/.github/workflows/main.yml: -------------------------------------------------------------------------------- 1 | on: 2 | release: 3 | types: [published] 4 | jobs: 5 | trigger-circleci: 6 | runs-on: ubuntu-latest 7 | steps: 8 | - name: 9 | id: 10 | uses: CircleCI-Public/trigger-circleci-pipeline-action@v1.0 11 | env: 12 | CCI_TOKEN: ${{ secrets.CCI_TOKEN }} -------------------------------------------------------------------------------- /examples/01-Trigger-Workflow-On-Pull_Request/.github/workflows/main.yml: -------------------------------------------------------------------------------- 1 | on: 2 | pull_request: 3 | types: [opened, reopened, synchronize, assigned, edited] 4 | jobs: 5 | trigger-circleci: 6 | runs-on: ubuntu-latest 7 | steps: 8 | - name: CircleCI Trigger on Pull Request 9 | id: 10 | uses: CircleCI-Public/trigger-circleci-pipeline-action@v1.0 11 | env: 12 | CCI_TOKEN: ${{ secrets.CCI_TOKEN }} -------------------------------------------------------------------------------- /examples/01-Trigger-Workflow-On-Pull_Request/.circleci/config.yml: -------------------------------------------------------------------------------- 1 | version: 2.1 2 | ## 3 | # The config will be executed on each pull_request update due to the GitHub Workflow. 4 | # Each push will also trigger the config, due to default CircleCI's behavior. 5 | ## 6 | 7 | parameters: 8 | GHA_Actor: 9 | type: string 10 | default: "" 11 | GHA_Action: 12 | type: string 13 | default: "" 14 | GHA_Event: 15 | type: string 16 | default: "" 17 | GHA_Meta: 18 | type: string 19 | default: "" 20 | 21 | jobs: 22 | test: 23 | docker: 24 | - image: cimg/node:lts 25 | steps: 26 | - run: npm install 27 | - run: npm test 28 | 29 | workflows: 30 | test: 31 | # This workflow is set to be conditionally triggered, only when 32 | # the GitHub Action is triggered. 33 | # With no other workflows, normal push events will be ignored currently. 34 | when: << pipeline.parameters.GHA_Action >> 35 | jobs: 36 | - test 37 | -------------------------------------------------------------------------------- /examples/02-Trigger-Workflow-On-Release/.circleci/config.yml: -------------------------------------------------------------------------------- 1 | version: 2.1 2 | ## 3 | # The `GHA_Event` parameter will be populated with the value `release` when triggered by 4 | # the GitHub workflow. This can be used in conditional statements to run a specific workflow 5 | # for a specific event. 6 | ## 7 | 8 | parameters: 9 | GHA_Event: 10 | type: string 11 | default: "" 12 | GHA_Actor: 13 | type: string 14 | default: "" 15 | GHA_Action: 16 | type: string 17 | default: "" 18 | GHA_Meta: 19 | type: string 20 | default: "" 21 | 22 | jobs: 23 | release: 24 | docker: 25 | - image: cimg/node:lts 26 | steps: 27 | - run: npm install 28 | - run: npm build 29 | - run: npm publish 30 | 31 | workflows: 32 | release: 33 | when: 34 | equal: [ "release", << pipeline.parameters.GHA_Event >> ] 35 | jobs: 36 | - release 37 | # This is mandatory to trigger a pipeline when pushing a tag 38 | filters: 39 | tags: 40 | only: /.*/ 41 | -------------------------------------------------------------------------------- /__tests__/CircleCIPipelineTrigger.test.ts: -------------------------------------------------------------------------------- 1 | import { Context } from "@actions/github/lib/context"; 2 | import { CircleCIPipelineTrigger } from "../src/lib//CircleCIPipelineTrigger"; 3 | 4 | describe("CircleCIPipelineTrigger", () => { 5 | const contextBranch: Partial = { 6 | ref: "refs/heads/main", 7 | actor: "testActor", 8 | }; 9 | 10 | const contextTag: Partial = { 11 | ref: "refs/tags/v1.0.0", 12 | actor: "testActor", 13 | }; 14 | 15 | it("should be defined", () => { 16 | expect(CircleCIPipelineTrigger).toBeDefined(); 17 | }); 18 | 19 | it("should get branch from context", () => { 20 | const trigger = new CircleCIPipelineTrigger(contextBranch as Context); 21 | expect(trigger.branch).toEqual("main"); 22 | }); 23 | 24 | it("should get tag from context", () => { 25 | const trigger = new CircleCIPipelineTrigger(contextTag as Context); 26 | expect(trigger.tag).toEqual("v1.0.0"); 27 | }); 28 | 29 | it("should parse a slug", () => { 30 | const trigger = new CircleCIPipelineTrigger(contextBranch as Context); 31 | const slug = "gh/testOwner/testRepo"; 32 | const { vcs, owner, repo } = trigger.parseSlug(slug); 33 | expect(vcs).toEqual("gh"); 34 | expect(owner).toEqual("testOwner"); 35 | expect(repo).toEqual("testRepo"); 36 | }); 37 | }); 38 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "trigger-circleci-pipeline-gha", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "dist/index.js", 6 | "scripts": { 7 | "test": "jest --config=jest.config.ts", 8 | "build": "ncc build src/index.ts --license licenses.txt", 9 | "lint": "eslint src/", 10 | "format": "prettier --write src/index.ts", 11 | "prepare": "husky install" 12 | }, 13 | "repository": { 14 | "type": "git", 15 | "url": "git+https://github.com/CircleCI-Public/trigger-circleci-pipeline-action.git" 16 | }, 17 | "keywords": [], 18 | "author": "", 19 | "license": "ISC", 20 | "bugs": { 21 | "url": "https://github.com/CircleCI-Public/trigger-circleci-pipeline-action/issues" 22 | }, 23 | "homepage": "https://github.com/CircleCI-Public/trigger-circleci-pipeline-action#readme", 24 | "dependencies": { 25 | "@actions/core": "^1.10.0", 26 | "@actions/github": "^5.1.1", 27 | "axios": "^0.27.2" 28 | }, 29 | "devDependencies": { 30 | "@types/jest": "^29.5.0", 31 | "@types/node": "^18.15.10", 32 | "@typescript-eslint/eslint-plugin": "^5.57.0", 33 | "@typescript-eslint/parser": "^5.57.0", 34 | "@vercel/ncc": "^0.33.3", 35 | "eslint": "^8.36.0", 36 | "husky": "^7.0.0", 37 | "jest": "^29.5.0", 38 | "jest-junit": "^15.0.0", 39 | "prettier": "2.5.0", 40 | "ts-jest": "^29.1.0", 41 | "ts-node": "^10.9.1", 42 | "typescript": "^5.0.2" 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /action.yml: -------------------------------------------------------------------------------- 1 | name: 'Trigger CircleCI Pipeline' 2 | description: 'Trigger pipelines on CircleCI for any event on GitHub.' 3 | branding: 4 | icon: "check-circle" 5 | color: "green" 6 | inputs: 7 | GHA_Meta: 8 | required: false 9 | description: 'An optional additional metadata parameter. Will be available on the CircleCI pipeline as GHA_Meta.' 10 | target-slug: 11 | required: false 12 | description: 'The slug of the target CircleCI project. For example, "github//". Will default to the current project. Can be overwritten with "TARGET_SLUG" environment variable.' 13 | target-branch: 14 | required: false 15 | description: 'The branch of the target CircleCI project. Will default to the current branch name. This should be overwritten if "target-slug" is set. Can be overwritten with "TARGET_BRANCH" environment variable.' 16 | target-tag: 17 | required: false 18 | description: 'The tag of the target CircleCI project. Will default to the current tag name if set. This or branch should be overwritten if "target-slug" is set. Can be overwritten with "TARGET_TAG" environment variable.' 19 | outputs: 20 | id: 21 | description: The unique ID of the pipeline. 22 | state: 23 | description: The current state of the pipeline. 24 | number: 25 | description: The number of the pipeline. 26 | created_at: 27 | description: The date and time the pipeline was created. 28 | runs: 29 | using: 'node20' 30 | main: 'dist/index.js' 31 | -------------------------------------------------------------------------------- /.github/PULL_REQUEST_TEMPLATE/PULL_REQUEST.md: -------------------------------------------------------------------------------- 1 | ## PR Checklist 2 | Please check if your PR fulfills the following requirements: 3 | 4 | - [ ] The commit message follows our contributor [guidelines](https://github.com/CircleCI-Public/circleci-config-sdk-ts/blob/main/CONTRIBUTING.md). 5 | - [ ] Tests for the changes have been added (for bug fixes / features) 6 | - [ ] Documentation has been added or updated where needed. 7 | 8 | ## PR Type 9 | What kind of change does this PR introduce? 10 | 11 | 12 | 13 | - [ ] Bug fix 14 | - [ ] Feature 15 | - [ ] Code style update (formatting, local variables) 16 | - [ ] Refactoring (no functional changes, no api changes) 17 | - [ ] Build related changes 18 | - [ ] CI related changes 19 | - [ ] Other... Please describe: 20 | 21 | > more details 22 | 23 | ## What issues are resolved by this PR? 24 | 25 | - #[00] 26 | 27 | ## Describe the new behavior. 28 | 29 | 30 | > Description 31 | 32 | ## Does this PR introduce a breaking change? 33 | 34 | - [ ] Yes 35 | - [ ] No 36 | 37 | 38 | 39 | ## Other information 40 | 41 | 42 | > More information (optional) 43 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/FEATURE_REQUEST.yml: -------------------------------------------------------------------------------- 1 | name: "\U0001F4A1 Feature Request" 2 | description: Have an idea for a new feature? Begin by submitting a Feature Request 3 | title: 'Request: ' 4 | labels: [feature_request] 5 | # assignees: '' 6 | body: 7 | - type: checkboxes 8 | attributes: 9 | label: "Is there an existing issue that is already proposing this?" 10 | description: "Please search [here](https://github.com/CircleCI-Public/trigger-circleci-pipeline-action/issues?q=is%3Aissue) to see if an issue already exists for the feature you are requesting" 11 | options: 12 | - label: "I have searched the existing issues" 13 | required: true 14 | - type: textarea 15 | id: contact 16 | attributes: 17 | label: "Is your feature request related to a problem? Please describe it" 18 | description: "A clear and concise description of what the problem is" 19 | placeholder: | 20 | I have an issue when ... 21 | validations: 22 | required: false 23 | - type: textarea 24 | validations: 25 | required: true 26 | attributes: 27 | label: "Describe the solution you'd like" 28 | description: "A clear and concise description of what you want to happen. Add any considered drawbacks" 29 | - type: textarea 30 | validations: 31 | required: true 32 | attributes: 33 | label: "Teachability, documentation, adoption, migration strategy" 34 | description: "If you can, explain how users will be able to use this and possibly write out a version the docs." 35 | - type: textarea 36 | validations: 37 | required: true 38 | attributes: 39 | label: "What is the motivation / use case for changing the behavior?" 40 | description: "Describe the motivation or the concrete use case" -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/BUG.yml: -------------------------------------------------------------------------------- 1 | name: "\U0001F41E Bug Report" 2 | description: Report any identified bugs. 3 | title: 'Bug: ' 4 | labels: [bug] 5 | # assignees: '' 6 | body: 7 | - type: checkboxes 8 | attributes: 9 | label: "Is there an existing issue for this?" 10 | description: "Please search [here](https://github.com/CircleCI-Public/trigger-circleci-pipeline-action/issues?q=is%3Aissue) to see if an issue already exists for the bug you encountered" 11 | options: 12 | - label: "I have searched the existing issues" 13 | required: true 14 | 15 | - type: textarea 16 | validations: 17 | required: true 18 | attributes: 19 | label: "Current behavior" 20 | description: "How does the issue manifest?" 21 | 22 | - type: input 23 | validations: 24 | required: true 25 | attributes: 26 | label: "Minimum reproduction code" 27 | description: "An URL to some git repository or gist which contains the minimum needed code to reproduce the error" 28 | placeholder: "https://github.com/..." 29 | 30 | - type: textarea 31 | attributes: 32 | label: "Steps to reproduce" 33 | description: | 34 | Detail the steps to take to replicate the issue. 35 | You may leave this blank if you have covered the issue in the minimum reproduction code above. 36 | placeholder: | 37 | 1. `npm i` 38 | 2. `npm start:dev` 39 | 3. See error... 40 | 41 | - type: textarea 42 | validations: 43 | required: true 44 | attributes: 45 | label: "Expected behavior" 46 | description: "A clear and concise description of what you expected to happen (or code)" 47 | 48 | - type: markdown 49 | attributes: 50 | value: | 51 | --- 52 | 53 | - type: input 54 | attributes: 55 | label: "GitHub Action Version" 56 | description: | 57 | Which version of `trigger-circleci-pipeline` are you using? 58 | placeholder: "1.0.0" 59 | 60 | - type: textarea 61 | attributes: 62 | label: "Other" 63 | description: | 64 | Anything else relevant? 65 | **Tip:** You can attach images, recordings or log files by clicking this area to highlight it and then dragging files in. 66 | -------------------------------------------------------------------------------- /src/lib/CircleCIPipelineTrigger.ts: -------------------------------------------------------------------------------- 1 | import { 2 | getInput, 3 | info, 4 | setFailed, 5 | setOutput, 6 | startGroup, 7 | error as coreError, 8 | endGroup, 9 | } from "@actions/core"; 10 | import axios from "axios"; 11 | import { Context } from "@actions/github/lib/context"; 12 | 13 | export class CircleCIPipelineTrigger { 14 | vcs: string; 15 | owner: string; 16 | repo: string; 17 | tag?: string; 18 | branch?: string; 19 | host: string; 20 | context: Context; 21 | url: string; 22 | metaData: string; 23 | parameters: CircleCIPipelineParams; 24 | 25 | constructor(context: Context, host = process.env.CCI_HOST || "circleci.com") { 26 | this.context = context; 27 | this.host = host; 28 | const slug = process.env.TARGET_SLUG ?? getInput("target-slug"); 29 | const { vcs, owner, repo } = slug 30 | ? this.parseSlug(slug) 31 | : { ...context.repo, vcs: "gh" }; 32 | this.vcs = vcs; 33 | this.owner = owner; 34 | this.repo = repo; 35 | this.url = `https://${this.host}/api/v2/project/${this.vcs}/${this.owner}/${this.repo}/pipeline`; 36 | this.metaData = getInput("GHA_Meta"); 37 | this.tag = this.getTag(); 38 | this.branch = this.getBranch(); 39 | this.parameters = { 40 | GHA_Actor: context.actor, 41 | GHA_Action: context.action, 42 | GHA_Event: context.eventName, 43 | }; 44 | } 45 | 46 | parseSlug(slug: string) { 47 | const [vcs, owner, repo] = slug.split("/"); 48 | if (!owner || !repo || !vcs) { 49 | throw new Error(`Invalid target-slug: ${slug}`); 50 | } 51 | return { vcs, owner, repo }; 52 | } 53 | 54 | getTag() { 55 | let tag = process.env.TARGET_TAG ?? getInput("target-tag"); 56 | if (!tag) { 57 | const tagRef = "refs/tags/"; 58 | if (this.context.ref.startsWith(tagRef)) { 59 | tag = this.context.ref.substring(tagRef.length); 60 | } 61 | } 62 | return tag; 63 | } 64 | 65 | getBranch() { 66 | let branch = process.env.TARGET_BRANCH ?? getInput("target-branch"); 67 | if (!branch) { 68 | if (this.context.ref.startsWith("refs/heads/")) { 69 | branch = this.context.ref.substring(11); 70 | } else if (this.context.ref.startsWith("refs/pull/")) { 71 | info(`This is a PR. Using head PR branch`); 72 | const pullRequestNumber = ( 73 | this.context.ref.match(/refs\/pull\/([0-9]*)\//) as RegExpMatchArray 74 | )[1]; 75 | const newref = `pull/${pullRequestNumber}/head`; 76 | branch = newref; 77 | } 78 | } 79 | return branch; 80 | } 81 | 82 | triggerPipeline() { 83 | const body: CircleCITriggerPipelineRequest = { 84 | parameters: this.parameters, 85 | }; 86 | startGroup("Preparing CircleCI Pipeline Trigger"); 87 | info(`Org: ${this.owner}`); 88 | info(`Repo: ${this.repo}`); 89 | if (this.metaData.length > 0) { 90 | this.parameters.GHA_Meta = this.metaData; 91 | } 92 | body[this.tag ? "tag" : "branch"] = this.tag || this.branch; 93 | info(`Triggering CircleCI Pipeline for ${this.owner}/${this.repo}`); 94 | info(` Triggering URL: ${this.url}`); 95 | const trigger = this.tag ? `tag: ${this.tag}` : `branch: ${this.branch}`; 96 | info(` Triggering ${trigger}`); 97 | info(` Parameters:\n${JSON.stringify(this.parameters)}`); 98 | endGroup(); 99 | axios 100 | .post(this.url, body, { 101 | headers: { 102 | "content-type": "application/json", 103 | "x-attribution-login": this.context.actor, 104 | "x-attribution-actor-id": this.context.actor, 105 | "Circle-Token": `${process.env.CCI_TOKEN}`, 106 | }, 107 | }) 108 | .then((response) => { 109 | startGroup("Successfully triggered CircleCI Pipeline"); 110 | info(`CircleCI API Response: ${JSON.stringify(response.data)}`); 111 | setOutput("created_at", response.data.created_at); 112 | setOutput("id", response.data.id); 113 | setOutput("number", response.data.number); 114 | setOutput("state", response.data.state); 115 | endGroup(); 116 | }) 117 | .catch((error) => { 118 | startGroup("Failed to trigger CircleCI Pipeline"); 119 | coreError(error); 120 | setFailed(error.message); 121 | endGroup(); 122 | }); 123 | } 124 | } 125 | 126 | type CircleCIPipelineParams = { 127 | GHA_Actor: string; 128 | GHA_Action: string; 129 | GHA_Event: string; 130 | GHA_Meta?: string; 131 | }; 132 | 133 | type CircleCITriggerPipelineRequest = { 134 | parameters: CircleCIPipelineParams; 135 | branch?: string; 136 | tag?: string; 137 | }; 138 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing 2 | 3 | Thank you for considering to contribute to the CircleCI Config SDK! Before you 4 | get started, we recommend taking a look at the guidelines belowL 5 | 6 | - [Have a Question?](#question) 7 | - [Issues and Bugs](#issue) 8 | - [Feature Requests](#feature) 9 | - [Contributing](#contribute) 10 | - [Submission Guidelines](#guidelines) 11 | - [Release Process](#release) 12 | 13 | ## Have a Question? 14 | 15 | ### I have a general question about CircleCI or CircleCI's `config.yml` file. 16 | 17 | Contact CircleCI's general support by filing a ticket here: 18 | [Submit a request](https://support.circleci.com/hc/en-us/requests/new) 19 | 20 | 21 | ## Discover a Bug? 22 | 23 | Find an issue or bug? 24 | 25 | You can help us resolve the issue by 26 | [submitting an issue](https://github.com/CircleCI-Public/trigger-circleci-pipeline-action/issues) 27 | on our GitHub repository. 28 | 29 | Up for a challenge? If you think you can fix the issue, consider sending in a 30 | [Pull Request](#pull). 31 | 32 | ## Missing Feature? 33 | 34 | Is anything missing? 35 | 36 | You can request a new feature by 37 | [submitting an issue](https://github.com/CircleCI-Public/trigger-circleci-pipeline-action/issues) 38 | to our GitHub repository, utilizing the `Feature Request` template. 39 | 40 | If you would like to instead contribute a pull request, please follow the 41 | [Submission Guidelines](#guidelines) 42 | 43 | ## Contributing 44 | 45 | Thank you for contributing to the CircleCI Config SDK! 46 | 47 | Before submitting any new Issue or Pull Request, search our repository for any 48 | existing or previous related submissions. 49 | 50 | - [Search Pull Requests](https://github.com/CircleCI-Public/trigger-circleci-pipeline-action/pulls?q=) 51 | - [Search Issues](https://github.com/CircleCI-Public/trigger-circleci-pipeline-action/issues?q=) 52 | 53 | ### Submission Guidelines 54 | 55 | #### Commit Conventions 56 | 57 | This project strictly adheres to the 58 | [conventional commits](https://www.conventionalcommits.org/en/v1.0.0/) 59 | specification for creating human readable commit messages with appropriate 60 | automation capabilities, such as changelog generation. 61 | 62 | ##### Commit Message Format 63 | 64 | Each commit message consists of a header, a body and a footer. The header has a 65 | special format that includes a type, a scope and a subject: 66 | 67 | ``` 68 | (optional ): 69 | 70 | 71 | 72 |