@ -1,5 +1,5 @@
# Only runs if anything under the packages/ directory changes.
# Only runs if anything under the packages/ directory changes.
---
name : Levitate / Detect breaking changes in PR
name : Levitate / Detect breaking changes in PR
on :
on :
@ -18,44 +18,43 @@ jobs:
working-directory : './pr'
working-directory : './pr'
steps:
steps:
- uses : actions/checkout@v4
- uses : actions/checkout@v4
with:
with:
path : './pr'
path : './pr'
- uses : actions/setup-node@v4
- uses : actions/setup-node@v4
with:
with:
node-version : 20.9 .0
node-version : 20.9 .0
- name : Get yarn cache directory path
- name : Get yarn cache directory path
id : yarn-cache-dir-path
id : yarn-cache-dir-path
run : echo "dir=$(yarn config get cacheFolder)" >> $GITHUB_OUTPUT
run : echo "dir=$(yarn config get cacheFolder)" >> $GITHUB_OUTPUT
- name : Restore yarn cache
- name : Restore yarn cache
uses : actions/cache@v3.3.1
uses : actions/cache@v4
id : yarn-cache
id : yarn-cache
with:
with:
path : ${{ steps.yarn-cache-dir-path.outputs.dir }}
path : ${{ steps.yarn-cache-dir-path.outputs.dir }}
key : yarn-cache-folder-${{ hashFiles('**/yarn.lock', '.yarnrc.yml') }}
key : yarn-cache-folder-${{ hashFiles('**/yarn.lock', '.yarnrc.yml') }}
restore-keys : |
restore-keys : |
yarn-cache-folder-
yarn-cache-folder-
- name : Install dependencies
- name : Install dependencies
run : yarn install --immutable
run : yarn install --immutable
- name : Build packages
- name : Build packages
run : yarn packages:build
run : yarn packages:build
- name : Pack packages
- name : Pack packages
run : yarn packages:pack --out ./%s.tgz
run : yarn packages:pack --out ./%s.tgz
- name : Zip built tarballed packages
- name : Zip built tarballed packages
run : zip -r ./pr_built_packages.zip ./packages/**/*.tgz
run : zip -r ./pr_built_packages.zip ./packages/**/*.tgz
- name : Upload build output as artifact
- name : Upload build output as artifact
uses : actions/upload-artifact@v3
uses : actions/upload-artifact@v4
with:
with:
name : buildPr
name : buildPr
path : './pr/pr_built_packages.zip'
path : './pr/pr_built_packages.zip'
buildBase:
buildBase:
name : Build Base
name : Build Base
@ -65,45 +64,45 @@ jobs:
working-directory : './base'
working-directory : './base'
steps:
steps:
- uses : actions/checkout@v4
- uses : actions/checkout@v4
with:
with:
path : './base'
path : './base'
ref : ${{ github.event.pull_request.base.ref }}
ref : ${{ github.event.pull_request.base.ref }}
- uses : actions/setup-node@v4
- uses : actions/setup-node@v4
with:
with:
node-version : 20.9 .0
node-version : 20.9 .0
- name : Get yarn cache directory path
- name : Get yarn cache directory path
id : yarn-cache-dir-path
id : yarn-cache-dir-path
run : echo "dir=$(yarn config get cacheFolder)" >> $GITHUB_OUTPUT
run : echo "dir=$(yarn config get cacheFolder)" >> $GITHUB_OUTPUT
- name : Restore yarn cache
- name : Restore yarn cache
uses : actions/cache@v3.3.1
uses : actions/cache@v4
id : yarn-cache
id : yarn-cache
with:
with:
path : ${{ steps.yarn-cache-dir-path.outputs.dir }}
path : ${{ steps.yarn-cache-dir-path.outputs.dir }}
key : yarn-cache-folder-${{ hashFiles('**/yarn.lock', '.yarnrc.yml') }}
key : yarn-cache-folder-${{ hashFiles('**/yarn.lock', '.yarnrc.yml') }}
restore-keys : |
restore-keys : |
yarn-cache-folder-
yarn-cache-folder-
- name : Install dependencies
- name : Install dependencies
run : yarn install --immutable
run : yarn install --immutable
- name : Build packages
- name : Build packages
run : yarn packages:build
run : yarn packages:build
- name : Pack packages
- name : Pack packages
run : yarn packages:pack --out ./%s.tgz
run : yarn packages:pack --out ./%s.tgz
- name : Zip built tarballed packages
- name : Zip built tarballed packages
run : zip -r ./base_built_packages.zip ./packages/**/*.tgz
run : zip -r ./base_built_packages.zip ./packages/**/*.tgz
- name : Upload build output as artifact
- name : Upload build output as artifact
uses : actions/upload-artifact@v3
uses : actions/upload-artifact@v4
with:
with:
name : buildBase
name : buildBase
path : './base/base_built_packages.zip'
path : './base/base_built_packages.zip'
Detect:
Detect:
name : Detect breaking changes
name : Detect breaking changes
@ -114,14 +113,17 @@ jobs:
steps:
steps:
- uses : actions/checkout@v4
- uses : actions/checkout@v4
- uses : actions/setup-node@v4
with:
node-version : 20.9 .0
- name : Get built packages from pr
- name : Get built packages from pr
uses : actions/download-artifact@v3
uses : actions/download-artifact@v4
with:
with:
name : buildPr
name : buildPr
- name : Get built packages from base
- name : Get built packages from base
uses : actions/download-artifact@v3
uses : actions/download-artifact@v4
with:
with:
name : buildBase
name : buildBase
@ -153,7 +155,7 @@ jobs:
echo "{ \"exit_code\": ${{ steps.breaking-changes.outputs.is_breaking }}, \"message\": \"${{ steps.breaking-changes.outputs.message }}\", \"job_link\": \"${{ steps.job.outputs.link }}#step:${GITHUB_STEP_NUMBER}:1\", \"pr_number\": \"${{ github.event.pull_request.number }}\" }" > ./levitate/result.json
echo "{ \"exit_code\": ${{ steps.breaking-changes.outputs.is_breaking }}, \"message\": \"${{ steps.breaking-changes.outputs.message }}\", \"job_link\": \"${{ steps.job.outputs.link }}#step:${GITHUB_STEP_NUMBER}:1\", \"pr_number\": \"${{ github.event.pull_request.number }}\" }" > ./levitate/result.json
- name : Upload check output as artifact
- name : Upload check output as artifact
uses : actions/upload-artifact@v3
uses : actions/upload-artifact@v4
with:
with:
name : levitate
name : levitate
path : levitate/
path : levitate/
@ -165,174 +167,174 @@ jobs:
needs : [ 'Detect' ]
needs : [ 'Detect' ]
steps:
steps:
- name : "Generate token"
- name : "Generate token"
id : generate_token
id : generate_token
uses : tibdex/github-app-token@b62528385c34dbc9f38e5f4225ac829252d1ea92
uses : tibdex/github-app-token@b62528385c34dbc9f38e5f4225ac829252d1ea92
with:
with:
app_id : ${{ secrets.GRAFANA_PR_AUTOMATION_APP_ID }}
app_id : ${{ secrets.GRAFANA_PR_AUTOMATION_APP_ID }}
private_key : ${{ secrets.GRAFANA_PR_AUTOMATION_APP_PEM }}
private_key : ${{ secrets.GRAFANA_PR_AUTOMATION_APP_PEM }}
- uses : actions/checkout@v4
- uses : actions/checkout@v4
- name : 'Download artifact'
- name : 'Download artifact'
uses : actions/download-artifact@v3
uses : actions/download-artifact@v4
with:
with:
name : levitate
name : levitate
- name : Parsing levitate result
- name : Parsing levitate result
uses : actions/github-script@v6
uses : actions/github-script@v6
id : levitate-run
id : levitate-run
with:
with:
script : |
script : |
const filePath = 'result.json';
const filePath = 'result.json';
const script = require('./.github/workflows/scripts/json-file-to-job-output.js');
const script = require('./.github/workflows/scripts/json-file-to-job-output.js');
await script({ core, filePath });
await script({ core, filePath });
# Check if label exists
# Check if label exists
- name : Check if "levitate breaking change" label exists
- name : Check if "levitate breaking change" label exists
id : does-label-exist
id : does-label-exist
uses : actions/github-script@v6
uses : actions/github-script@v6
env:
env:
PR_NUMBER : ${{ github.event.pull_request.number }}
PR_NUMBER : ${{ github.event.pull_request.number }}
with:
with:
script : |
script : |
const { data } = await github.rest.issues.listLabelsOnIssue({
const { data } = await github.rest.issues.listLabelsOnIssue({
issue_number : process.env.PR_NUMBER,
issue_number : process.env.PR_NUMBER,
owner : context.repo.owner,
owner : context.repo.owner,
repo : context.repo.repo,
repo : context.repo.repo,
});
});
const labels = data.map(({ name }) => name);
const labels = data.map(({ name }) => name);
const doesExist = labels.includes('levitate breaking change');
const doesExist = labels.includes('levitate breaking change');
return doesExist ? 1 : 0 ;
return doesExist ? 1 : 0 ;
# put the markdown into a variable
# put the markdown into a variable
- name : Levitate Markdown
- name : Levitate Markdown
id : levitate-markdown
id : levitate-markdown
run : |
run : |
if [ -f "levitate.md" ]; then
if [ -f "levitate.md" ]; then
{
{
echo 'levitate_markdown<<EOF'
echo 'levitate_markdown<<EOF'
cat levitate.md
cat levitate.md
echo EOF
echo EOF
} >> $GITHUB_OUTPUT
} >> $GITHUB_OUTPUT
else
else
echo "levitate_markdown=No breaking changes detected" >> $GITHUB_OUTPUT
echo "levitate_markdown=No breaking changes detected" >> $GITHUB_OUTPUT
fi
fi
# Comment on the PR
# Comment on the PR
- name : Comment on PR
- name : Comment on PR
if : steps.levitate-run.outputs.exit_code == 1
if : steps.levitate-run.outputs.exit_code == 1
uses : marocchino/sticky-pull-request-comment@v2
uses : marocchino/sticky-pull-request-comment@v2
with:
with:
header : levitate-breaking-change-comment
header : levitate-breaking-change-comment
number : ${{ github.event.pull_request.number }}
number : ${{ github.event.pull_request.number }}
message : |
message : |
⚠️ **Possible breaking changes (md version)** ⚠️
⚠️ **Possible breaking changes (md version)** ⚠️
${{ steps.levitate-markdown.outputs.levitate_markdown }}
${{ steps.levitate-markdown.outputs.levitate_markdown }}
[ Read our guideline](https://github.com/grafana/grafana/blob/main/contribute/breaking-changes-guide/breaking-changes-guide.md)
[ Read our guideline](https://github.com/grafana/grafana/blob/main/contribute/breaking-changes-guide/breaking-changes-guide.md)
[ Console output](${{ steps.levitate-run.outputs.job_link }})
[ Console output](${{ steps.levitate-run.outputs.job_link }})
GITHUB_TOKEN : ${{ steps.generate_token.outputs.token }}
GITHUB_TOKEN : ${{ steps.generate_token.outputs.token }}
# Remove comment from the PR (no more breaking changes)
# Remove comment from the PR (no more breaking changes)
- name : Remove comment from PR
- name : Remove comment from PR
if : steps.levitate-run.outputs.exit_code == 0
if : steps.levitate-run.outputs.exit_code == 0
uses : marocchino/sticky-pull-request-comment@v2
uses : marocchino/sticky-pull-request-comment@v2
with:
with:
header : levitate-breaking-change-comment
header : levitate-breaking-change-comment
number : ${{ github.event.pull_request.number }}
number : ${{ github.event.pull_request.number }}
delete : true
delete : true
GITHUB_TOKEN : ${{ steps.generate_token.outputs.token }}
GITHUB_TOKEN : ${{ steps.generate_token.outputs.token }}
# Posts a notification to Slack if a PR has a breaking change and it did not have a breaking change before
# Posts a notification to Slack if a PR has a breaking change and it did not have a breaking change before
- name : Post to Slack
- name : Post to Slack
id : slack
id : slack
if : steps.levitate-run.outputs.exit_code == 1 && steps.does-label-exist.outputs.result == 0 && env.HAS_SECRETS
if : steps.levitate-run.outputs.exit_code == 1 && steps.does-label-exist.outputs.result == 0 && env.HAS_SECRETS
uses : slackapi/slack-github-action@v1.24.0
uses : slackapi/slack-github-action@v1.24.0
with:
with:
payload : |
payload : |
{
{
"pr_link": "https://github.com/grafana/grafana/pull/${{ steps.levitate-run.outputs.pr_number }}" ,
"pr_link": "https://github.com/grafana/grafana/pull/${{ steps.levitate-run.outputs.pr_number }}" ,
"pr_number": "${{ steps.levitate-run.outputs.pr_number }}" ,
"pr_number": "${{ steps.levitate-run.outputs.pr_number }}" ,
"job_link": "${{ steps.levitate-run.outputs.job_link }}" ,
"job_link": "${{ steps.levitate-run.outputs.job_link }}" ,
"reporting_job_link": "${{ github.event.workflow_run.html_url }}" ,
"reporting_job_link": "${{ github.event.workflow_run.html_url }}" ,
"message": "${{ steps.levitate-run.outputs.message }}"
"message": "${{ steps.levitate-run.outputs.message }}"
}
}
env:
env:
SLACK_WEBHOOK_URL : ${{ secrets.SLACK_LEVITATE_WEBHOOK_URL }}
SLACK_WEBHOOK_URL : ${{ secrets.SLACK_LEVITATE_WEBHOOK_URL }}
HAS_SECRETS : ${{ (github.repository == 'grafana/grafana' || secrets.SLACK_LEVITATE_WEBHOOK_URL != '') || '' }}
HAS_SECRETS : ${{ (github.repository == 'grafana/grafana' || secrets.SLACK_LEVITATE_WEBHOOK_URL != '') || '' }}
# Add the label
# Add the label
- name : Add "levitate breaking change" label
- name : Add "levitate breaking change" label
if : steps.levitate-run.outputs.exit_code == 1 && steps.does-label-exist.outputs.result == 0
if : steps.levitate-run.outputs.exit_code == 1 && steps.does-label-exist.outputs.result == 0
uses : actions/github-script@v6
uses : actions/github-script@v6
env:
env:
PR_NUMBER : ${{ steps.levitate-run.outputs.pr_number }}
PR_NUMBER : ${{ steps.levitate-run.outputs.pr_number }}
with:
with:
github-token : ${{ steps.generate_token.outputs.token }}
github-token : ${{ steps.generate_token.outputs.token }}
script : |
script : |
await github.rest.issues.addLabels({
await github.rest.issues.addLabels({
issue_number : process.env.PR_NUMBER,
issue_number : process.env.PR_NUMBER,
owner : context.repo.owner,
owner : context.repo.owner,
repo : context.repo.repo,
repo : context.repo.repo,
labels : [ 'levitate breaking change' ]
labels : [ 'levitate breaking change' ]
})
})
# Remove label (no more breaking changes)
# Remove label (no more breaking changes)
- name : Remove "levitate breaking change" label
- name : Remove "levitate breaking change" label
if : steps.levitate-run.outputs.exit_code == 0 && steps.does-label-exist.outputs.result == 1
if : steps.levitate-run.outputs.exit_code == 0 && steps.does-label-exist.outputs.result == 1
uses : actions/github-script@v6
uses : actions/github-script@v6
env:
env:
PR_NUMBER : ${{ steps.levitate-run.outputs.pr_number }}
PR_NUMBER : ${{ steps.levitate-run.outputs.pr_number }}
with:
with:
github-token : ${{ steps.generate_token.outputs.token }}
github-token : ${{ steps.generate_token.outputs.token }}
script : |
script : |
await github.rest.issues.removeLabel({
await github.rest.issues.removeLabel({
issue_number : process.env.PR_NUMBER,
issue_number : process.env.PR_NUMBER,
owner : context.repo.owner,
owner : context.repo.owner,
repo : context.repo.repo,
repo : context.repo.repo,
name : 'levitate breaking change'
name : 'levitate breaking change'
})
})
# Add reviewers
# Add reviewers
# This is very weird, the actual request goes through (comes back with a 201), but does not assign the team.
# This is very weird, the actual request goes through (comes back with a 201), but does not assign the team.
# Related issue: https://github.com/renovatebot/renovate/issues/1908
# Related issue: https://github.com/renovatebot/renovate/issues/1908
- name : Add "grafana/plugins-platform-frontend" as a reviewer
- name : Add "grafana/plugins-platform-frontend" as a reviewer
if : steps.levitate-run.outputs.exit_code
if : steps.levitate-run.outputs.exit_code == 1
uses : actions/github-script@v6
uses : actions/github-script@v6
env:
env:
PR_NUMBER : ${{ steps.levitate-run.outputs.pr_number }}
PR_NUMBER : ${{ steps.levitate-run.outputs.pr_number }}
with:
with:
github-token : ${{ steps.generate_token.outputs.token }}
github-token : ${{ steps.generate_token.outputs.token }}
script : |
script : |
await github.rest.pulls.requestReviewers({
await github.rest.pulls.requestReviewers({
pull_number : process.env.PR_NUMBER,
pull_number : process.env.PR_NUMBER,
owner : context.repo.owner,
owner : context.repo.owner,
repo : context.repo.repo,
repo : context.repo.repo,
reviewers : [ ] ,
reviewers : [ ] ,
team_reviewers : [ 'plugins-platform-frontend' ]
team_reviewers : [ 'plugins-platform-frontend' ]
});
});
# Remove reviewers (no more breaking changes)
# Remove reviewers (no more breaking changes)
- name : Remove "grafana/plugins-platform-frontend" from the list of reviewers
- name : Remove "grafana/plugins-platform-frontend" from the list of reviewers
if : steps.levitate-run.outputs.exit_code == 0
if : steps.levitate-run.outputs.exit_code == 0
uses : actions/github-script@v6
uses : actions/github-script@v6
env:
env:
PR_NUMBER : ${{ steps.levitate-run.outputs.pr_number }}
PR_NUMBER : ${{ steps.levitate-run.outputs.pr_number }}
with:
with:
github-token : ${{ steps.generate_token.outputs.token }}
github-token : ${{ steps.generate_token.outputs.token }}
script : |
script : |
await github.rest.pulls.removeRequestedReviewers({
await github.rest.pulls.removeRequestedReviewers({
pull_number : process.env.PR_NUMBER,
pull_number : process.env.PR_NUMBER,
owner : context.repo.owner,
owner : context.repo.owner,
repo : context.repo.repo,
repo : context.repo.repo,
reviewers : [ ] ,
reviewers : [ ] ,
team_reviewers : [ 'plugins-platform-frontend' ]
team_reviewers : [ 'plugins-platform-frontend' ]
});
});
- name : Exit
- name : Exit
run : exit ${{ steps.levitate-run.outputs.exit_code }}
run : exit ${{ steps.levitate-run.outputs.exit_code }}
shell : bash
shell : bash