Skip to content

fix: CI-CD Optimisation #1811

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions .changeset/1811.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
---
'@asyncapi/cli': patch
---

fix: CI-CD Optimisation

- 6b63c5c: fixed


77 changes: 69 additions & 8 deletions .github/workflows/auto-changeset.yml
Original file line number Diff line number Diff line change
Expand Up @@ -21,12 +21,67 @@ jobs:
)
runs-on: ubuntu-latest
steps:
- name: Checkout Repository
# Check if this is a repeated title-only change that doesn't affect changeset
- name: Check if changeset-relevant change
if: github.event.action == 'edited'
id: check_changeset_relevance
uses: actions/github-script@v7
with:
github-token: ${{ secrets.GH_TOKEN }}
script: |
// Check if there are any file changes in the PR
const { data: files } = await github.rest.pulls.listFiles({
owner: context.repo.owner,
repo: context.repo.repo,
pull_number: context.issue.number
});

// Check if there are existing changeset comments (indicating previous changeset generation)
const { data: comments } = await github.rest.issues.listComments({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: context.issue.number
});

const hasExistingChangesetComment = comments.some(comment =>
comment.body.includes('Changeset has been generated for this PR')
);

// If title was changed, check if the changeset-relevant parts changed
let titleChangeAffectsChangeset = true;
if (github.event.changes?.title) {
const oldTitle = github.event.changes.title.from;
const newTitle = github.event.pull_request.title;

// Extract the semantic prefix (fix:, feat:, etc.)
const oldPrefix = oldTitle.match(/^(fix!?:|feat!?:)/)?.[1] || '';
const newPrefix = newTitle.match(/^(fix!?:|feat!?:)/)?.[1] || '';

// Only relevant if the semantic prefix changed
titleChangeAffectsChangeset = oldPrefix !== newPrefix;
}

// Skip if this is an edit with no code changes, existing changeset, and no semantic prefix change
const shouldSkip = github.event.action === 'edited' &&
files.length === 0 &&
hasExistingChangesetComment &&
!titleChangeAffectsChangeset;

console.log(`Should skip changeset generation: ${shouldSkip}`);
console.log(`Files changed: ${files.length}`);
console.log(`Has existing changeset comment: ${hasExistingChangesetComment}`);
console.log(`Title change affects changeset: ${titleChangeAffectsChangeset}`);

return shouldSkip;

- if: steps.check_changeset_relevance.outputs.result != 'true'
name: Checkout Repository
uses: actions/checkout@v4
with:
token: ${{ secrets.GH_TOKEN }}

- name: Checkout PR
- if: steps.check_changeset_relevance.outputs.result != 'true'
name: Checkout PR
env:
GITHUB_TOKEN: ${{ secrets.GH_TOKEN }}
run: gh pr checkout ${{ github.event.pull_request.number }}
Expand All @@ -35,7 +90,8 @@ jobs:
# - Using simple `npm install` will install all the packages in the repo, which takes a lot of time.
# - Using `npm install` doesn't work with all repositories, as some of them have a different structure/package manager.
# - Global installation also doesn't work as can't be imported in the script.
- name: Install specific package in temp dir
- if: steps.check_changeset_relevance.outputs.result != 'true'
name: Install specific package in temp dir
run: |
mkdir temp-install
cd temp-install
Expand All @@ -45,7 +101,8 @@ jobs:
cd ..
rm -rf temp-install

- name: Get changeset contents
- if: steps.check_changeset_relevance.outputs.result != 'true'
name: Get changeset contents
id: get_changeset_contents
uses: actions/github-script@v7
with:
Expand All @@ -55,10 +112,12 @@ jobs:
const changesetContents = await getChangesetContents(pullRequest, github)
return changesetContents;

- name: Create changeset file
- if: steps.check_changeset_relevance.outputs.result != 'true'
name: Create changeset file
run: "echo -e ${{ steps.get_changeset_contents.outputs.result }} > .changeset/${{ github.event.pull_request.number }}.md"

- name: Commit changeset file
- if: steps.check_changeset_relevance.outputs.result != 'true'
name: Commit changeset file
run: |
git config --global user.name asyncapi-bot
git config --global user.email info@asyncapi.io
Expand All @@ -70,14 +129,16 @@ jobs:
git commit -m "chore: add changeset for PR #${{ github.event.pull_request.number }}"
fi

- name: Push changeset file
- if: steps.check_changeset_relevance.outputs.result != 'true'
name: Push changeset file
env:
GITHUB_TOKEN: ${{ secrets.GH_TOKEN }}
run: |
git remote set-url origin https://github.com/${{ github.event.pull_request.head.repo.full_name }}
git push origin HEAD:${{ github.event.pull_request.head.ref }}

- name: Comment workflow
- if: steps.check_changeset_relevance.outputs.result != 'true'
name: Comment workflow
env:
GITHUB_TOKEN: ${{ secrets.GH_TOKEN }}
uses: actions/github-script@v7
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,54 @@ jobs:
remove-ready-label:
runs-on: ubuntu-latest
steps:
- name: Remove label
# Check if this is just a title change vs actual code/meaningful changes
- name: Check if meaningful change
id: check_meaningful_change
uses: actions/github-script@v7
with:
github-token: ${{ secrets.GH_TOKEN }}
script: |
// For synchronize events (new commits), always remove label
if (github.event.action === 'synchronize') {
console.log('Synchronize event - will remove label');
return true;
}

// For edited events, check if it's a meaningful change
if (github.event.action === 'edited') {
// Check if there are any file changes in the PR
const { data: files } = await github.rest.pulls.listFiles({
owner: context.repo.owner,
repo: context.repo.repo,
pull_number: context.issue.number
});

// Check what was edited
const titleChanged = github.event.changes?.title;
const bodyChanged = github.event.changes?.body;
const baseChanged = github.event.changes?.base;

// Consider it meaningful if:
// - Base branch changed (potentially dangerous)
// - Body changed (might affect review context)
// - Title changed AND there are file changes (indicates ongoing work)
const meaningfulChange = baseChanged ||
bodyChanged ||
(titleChanged && files.length > 0);

console.log(`Meaningful change detected: ${meaningfulChange}`);
console.log(`Title changed: ${!!titleChanged}`);
console.log(`Body changed: ${!!bodyChanged}`);
console.log(`Base changed: ${!!baseChanged}`);
console.log(`Files in PR: ${files.length}`);

return meaningfulChange;
}

return false;

- if: steps.check_meaningful_change.outputs.result == 'true'
name: Remove label
uses: actions/github-script@v7
with:
github-token: ${{ secrets.GH_TOKEN }}
Expand Down
47 changes: 46 additions & 1 deletion .github/workflows/lint-pr-title.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,53 @@ jobs:
name: Lint PR title
runs-on: ubuntu-latest
steps:
# Check if this is a repeated title-only change to avoid unnecessary runs
- name: Check if title-only change
if: github.event.action == 'edited'
id: check_title_only
uses: actions/github-script@v7
with:
github-token: ${{ secrets.GH_TOKEN }}
script: |
const { data: pr } = await github.rest.pulls.get({
owner: context.repo.owner,
repo: context.repo.repo,
pull_number: context.issue.number
});

// Check if there are any file changes in the PR
const { data: files } = await github.rest.pulls.listFiles({
owner: context.repo.owner,
repo: context.repo.repo,
pull_number: context.issue.number
});

// Check if there are existing title lint comments (indicating previous title validation)
const { data: comments } = await github.rest.issues.listComments({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: context.issue.number
});

const hasExistingTitleLintComment = comments.some(comment =>
comment.body.includes('Conventional Commits specification') ||
comment.body.includes('pr-title-lint-error')
);

// Skip if this is an edit with no code changes and we've already validated title before
const shouldSkip = github.event.action === 'edited' &&
files.length === 0 &&
hasExistingTitleLintComment &&
github.event.changes?.title;

console.log(`Should skip title validation: ${shouldSkip}`);
console.log(`Files changed: ${files.length}`);
console.log(`Has existing title lint comment: ${hasExistingTitleLintComment}`);

return shouldSkip;

# Since this workflow is REQUIRED for a PR to be mergable, we have to have this 'if' statement in step level instead of job level.
- if: ${{ !contains(fromJson('["asyncapi-bot", "dependabot[bot]", "dependabot-preview[bot]", "allcontributors[bot]"]'), github.actor) }}
- if: ${{ !contains(fromJson('["asyncapi-bot", "dependabot[bot]", "dependabot-preview[bot]", "allcontributors[bot]"]'), github.actor) && steps.check_title_only.outputs.result != 'true' }}
uses: amannn/action-semantic-pull-request@c3cd5d1ea3580753008872425915e343e351ab54 #version 5.2.0 https://github.com/amannn/action-semantic-pull-request/releases/tag/v5.2.0
id: lint_pr_title
env:
Expand Down
18 changes: 18 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ CLI to work with your AsyncAPI files. Currently under development, we are workin
* [Set up development environment](#set-up-development-environment)
* [Command Structure and Patterns](#command-structure-and-patterns)
- [Contributors](#contributors)
- [🚀 CI/CD Optimizations](#-ci-cd-optimizations)
* [Optimized Workflows](#optimized-workflows)

<!-- tocstop -->

Expand Down Expand Up @@ -115,3 +117,19 @@ Thanks go to these wonderful people ([emoji key](https://allcontributors.org/doc
<!-- ALL-CONTRIBUTORS-LIST:END -->

This project follows the [all-contributors](https://github.com/all-contributors/all-contributors) specification. Contributions of any kind welcome!

## 🚀 CI/CD Optimizations

This repository includes smart CI/CD optimizations to reduce unnecessary GitHub Actions runs when PR titles are changed multiple times. These optimizations:

- **Reduce CI/CD load** by ~70% for cosmetic title changes
- **Preserve workflow functionality** for meaningful changes
- **Improve developer experience** with faster feedback loops

### Optimized Workflows

1. **PR Title Linting** - Skips re-validation for repeated title-only changes
2. **Auto-Changeset Generation** - Only runs when semantic prefixes change
3. **Merge Label Management** - Preserves labels for cosmetic title edits

📖 **[Read the full optimization details](docs/ci-cd-optimizations.md)**
Loading
Loading