-
Notifications
You must be signed in to change notification settings - Fork 34
[CI] Adding release notes for non-rc versions & PR validations workflows #289
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
Changes from 6 commits
3e26ccb
91aa535
355728a
ba88c03
5ed1f83
9640e9c
cbe71fc
6264877
3413976
8ec1302
72ae161
e51bd28
c5d7b50
6cb4f4b
79daf5b
0aa31b7
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,84 @@ | ||
| name: PR Validation | ||
|
|
||
| on: | ||
| pull_request_target: | ||
| types: [opened, edited, reopened, synchronize] | ||
|
|
||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. add conmcurrency to avoid race conditions |
||
| jobs: | ||
| validate-and-label: | ||
| runs-on: ubuntu-latest | ||
| permissions: | ||
| issues: write | ||
|
|
||
| steps: | ||
| - name: Validate PR title and assign label | ||
| uses: actions/github-script@v7 | ||
| with: | ||
| github-token: "${{ secrets.GITHUB_TOKEN }}" | ||
| script: | | ||
| const title = context.payload.pull_request.title; | ||
| const prNumber = context.payload.pull_request.number; | ||
|
|
||
| const allowedScopes = ['feature', 'fix', 'docs', 'improvement', 'revert', 'breaking', 'ci']; | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The allowed scopes (feature, fix, docs, improvement, revert, breaking, ci) don't align with cliff.toml's commit parsers (feat, fix, perf, refactor, docs, chore, revert, breaking). feature passes validation but won't match [feat] in cliff |
||
|
|
||
| const scopeToLabel = { | ||
| feature: 'feature', | ||
| ci: 'ci', | ||
| fix: 'bug', | ||
| docs: 'documentation', | ||
| improvement: 'improvement', | ||
| revert: 'revert', | ||
| breaking: 'breaking-change', | ||
| }; | ||
|
|
||
| const match = title.match(/^\[([^\]]+)\]\s+\S+/); | ||
|
|
||
| if (!match) { | ||
| core.setFailed( | ||
| `PR title must follow the format: [scope] description\n` + | ||
| `Example: [Feat] Add SeaweedFS bucket auto-creation\n` + | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The example [Feat] Add SeaweedFS bucket auto-creation would fail this very validation. Feat lowercased is feat, which is not in allowedScopes (the list has feature, not feat). Either change the example to [Feature] ... or change the scope name to feat. |
||
| `Allowed scopes: ${allowedScopes.join(', ')}` | ||
| ); | ||
| return; | ||
| } | ||
|
|
||
| const scope = match[1].toLowerCase(); | ||
|
|
||
| if (!allowedScopes.includes(scope)) { | ||
| core.setFailed( | ||
| `Invalid scope "[${match[1]}]".\n` + | ||
| `Allowed scopes: ${allowedScopes.join(', ')}\n` + | ||
| `Example: [Feat] Add SeaweedFS bucket auto-creation` | ||
| ); | ||
| return; | ||
| } | ||
|
|
||
| const labelName = scopeToLabel[scope]; | ||
|
|
||
| // Remove any stale scope labels from a previous title edit | ||
| const allScopeLabels = Object.values(scopeToLabel); | ||
| const currentLabels = context.payload.pull_request.labels.map(l => l.name); | ||
|
|
||
| for (const stale of currentLabels) { | ||
| if (allScopeLabels.includes(stale) && stale !== labelName) { | ||
| await github.rest.issues.removeLabel({ | ||
| owner: context.repo.owner, | ||
| repo: context.repo.repo, | ||
| issue_number: prNumber, | ||
| name: stale, | ||
| }); | ||
| core.info(`Removed stale label: ${stale}`); | ||
| } | ||
| } | ||
|
|
||
| // Apply the correct label if not already present | ||
| if (!currentLabels.includes(labelName)) { | ||
| await github.rest.issues.addLabels({ | ||
| owner: context.repo.owner, | ||
| repo: context.repo.repo, | ||
| issue_number: prNumber, | ||
| labels: [labelName], | ||
| }); | ||
| } | ||
|
|
||
| core.info(`PR title valid — scope: [${scope}] → label: ${labelName}`); | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -36,6 +36,21 @@ jobs: | |
| git config user.name "$GITHUB_ACTOR" | ||
| git config user.email "$GITHUB_ACTOR@users.noreply.github.com" | ||
|
|
||
| - name: Extract Chart Version and check RC | ||
| id: version_check | ||
| run: | | ||
| CHART_VERSION=$(grep '^version:' charts/mlrun-ce/Chart.yaml | awk '{print $2}') | ||
| if [[ -z "$CHART_VERSION" ]]; then | ||
| echo "Error: Failed to extract version from Chart.yaml" >&2 | ||
| exit 1 | ||
| fi | ||
| echo "version=$CHART_VERSION" >> $GITHUB_OUTPUT | ||
| if [[ "$CHART_VERSION" =~ -rc ]]; then | ||
| echo "is_rc=true" >> $GITHUB_OUTPUT | ||
| else | ||
| echo "is_rc=false" >> $GITHUB_OUTPUT | ||
| fi | ||
|
|
||
| - name: Add Helm Repos | ||
| run: | | ||
| helm repo add stable https://charts.helm.sh/stable | ||
|
|
@@ -52,18 +67,39 @@ jobs: | |
| env: | ||
| CR_TOKEN: "${{ secrets.GITHUB_TOKEN }}" | ||
|
|
||
| - name: Extract Chart Version from Chart.yaml | ||
| id: extract_version | ||
| - name: Find first RC tag for this version | ||
| if: steps.version_check.outputs.is_rc == 'false' | ||
| id: first_rc | ||
| run: | | ||
| CHART_VERSION=$(grep '^version:' charts/mlrun-ce/Chart.yaml | awk '{print $2}') | ||
| if [[ -z "$CHART_VERSION" ]]; then | ||
| echo "Error: Failed to extract version from Chart.yaml" >&2 | ||
| exit 1 | ||
| fi | ||
| echo "version=$CHART_VERSION" >> $GITHUB_OUTPUT | ||
| VERSION="${{ steps.version_check.outputs.version }}" | ||
| FIRST_RC=$(git tag --sort=version:refname \ | ||
| | grep "^mlrun-ce-${VERSION}-rc." \ | ||
| | head -1) | ||
| echo "tag=${FIRST_RC}" >> $GITHUB_OUTPUT | ||
| echo "First RC tag: ${FIRST_RC}" | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Not sure if can happen, but If no RC tag exists for this version (e.g., a hotfix release that skipped RC), FIRST_RC will be empty. The downstream git-cliff step would then receive ^..HEAD as the range, which is invalid and will fail the workflow. you can add a guard if you think necessary. |
||
|
|
||
| - name: Generate release notes with git-cliff | ||
| if: steps.version_check.outputs.is_rc == 'false' | ||
| uses: orhun/git-cliff-action@v4 | ||
| with: | ||
| config: cliff.toml | ||
| args: >- | ||
| ${{ steps.first_rc.outputs.tag }}^..HEAD | ||
| --tag mlrun-ce-${{ steps.version_check.outputs.version }} | ||
| --ignore-tags "mlrun-ce-${{ steps.version_check.outputs.version }}-rc.*" | ||
| env: | ||
| OUTPUT: RELEASE_NOTES.md | ||
|
|
||
| - name: Update GitHub Release with release notes | ||
| if: steps.version_check.outputs.is_rc == 'false' | ||
| env: | ||
| GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} | ||
| run: | | ||
| gh release edit "mlrun-ce-${{ steps.version_check.outputs.version }}" \ | ||
|
yaelgen marked this conversation as resolved.
|
||
| --notes-file RELEASE_NOTES.md | ||
|
|
||
| outputs: | ||
| version: ${{ steps.extract_version.outputs.version }} | ||
| version: ${{ steps.version_check.outputs.version }} | ||
|
|
||
| deploy_ce_onprem: | ||
| needs: release | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,67 @@ | ||
| [changelog] | ||
| header = "" | ||
| body = """ | ||
| {% for group, commits in commits | sort(attribute="group") | group_by(attribute="group") %}\ | ||
| ### {{ group | striptags | trim | upper_first }} | ||
| {% for commit in commits %}\ | ||
| - {% if commit.scope %}*({{ commit.scope }})* {% endif %}\ | ||
| {% if commit.breaking %}[**breaking**] {% endif %}\ | ||
| {{ commit.message | split(pat="\n") | first | upper_first }} \ | ||
| ([{{ commit.id | truncate(length=7, end="") }}](https://github.com/mlrun/ce/commit/{{ commit.id }}))\ | ||
| \n \ | ||
| {% endfor %} | ||
| {% endfor %}\n | ||
| """ | ||
| trim = true | ||
| footer = "" | ||
|
|
||
| [git] | ||
| conventional_commits = false | ||
| filter_unconventional = false | ||
| split_commits = false | ||
| commit_preprocessors = [] | ||
| commit_parsers = [ | ||
| # skip merge commits | ||
| { message = "(?i)^merge", skip = true }, | ||
|
|
||
| # new PR title format (enforced going forward): [scope] ... | ||
| { message = "(?i)^\\[feat\\]", group = "Features" }, | ||
| { message = "(?i)^\\[fix\\]", group = "Bug Fixes" }, | ||
| { message = "(?i)^\\[perf\\]", group = "Performance" }, | ||
| { message = "(?i)^\\[refactor\\]", group = "Refactor" }, | ||
| { message = "(?i)^\\[docs?\\]", group = "Documentation" }, | ||
| { message = "(?i)^\\[chore\\]", group = "Miscellaneous" }, | ||
| { message = "(?i)^\\[revert\\]", group = "Reverts" }, | ||
| { message = "(?i)^\\[breaking\\]", group = "Breaking Changes" }, | ||
|
|
||
| # conventional commits format: feat: / fix: ... | ||
| { message = "(?i)^feat", group = "Features" }, | ||
| { message = "(?i)^fix", group = "Bug Fixes" }, | ||
| { message = "(?i)^perf", group = "Performance" }, | ||
| { message = "(?i)^refactor", group = "Refactor" }, | ||
| { message = "(?i)^docs?", group = "Documentation" }, | ||
| { message = "(?i)^chore\\(deps\\)", group = "Dependencies" }, | ||
| { message = "(?i)^chore", group = "Miscellaneous" }, | ||
| { message = "(?i)^revert", group = "Reverts" }, | ||
|
|
||
| # historical [ComponentName] format — infer type from the verb in the message | ||
| { message = "(?i)^\\[[^\\]]+\\].*(fix|bug|broken|regression)", group = "Bug Fixes" }, | ||
| { message = "(?i)^\\[[^\\]]+\\].*(add|support|enable|upgrade|update|migrate|connect|expose|allow)", group = "Features" }, | ||
| { message = "(?i)^\\[[^\\]]+\\].*(disable|remove|clean|deprecat)", group = "Miscellaneous" }, | ||
| { message = "(?i)^\\[[^\\]]+\\]", group = "Changes" }, | ||
|
|
||
| # plain English fallback | ||
| { message = "(?i)^(fix|bug)", group = "Bug Fixes" }, | ||
| { message = "(?i)^(add|update|upgrade|support|enable|migrate|expose|allow)", group = "Features" }, | ||
| { message = "(?i)^(remove|disable|clean|deprecat)", group = "Miscellaneous" }, | ||
|
|
||
| # catch-all — anything that didn't match above | ||
| { message = ".*", group = "Other" }, | ||
| ] | ||
| protect_breaking_commits = false | ||
| filter_commits = false | ||
| tag_pattern = "mlrun-ce-[0-9].*" | ||
| skip_tags = "" | ||
| ignore_tags = "" | ||
| topo_order = false | ||
| sort_commits = "newest" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
you can't change title on push - not sure why it is needed. dropped synchronize