diff --git a/.github/workflows/detect-breaking-changes-build.yml b/.github/workflows/detect-breaking-changes-build.yml
new file mode 100644
index 00000000000..c846e7d7336
--- /dev/null
+++ b/.github/workflows/detect-breaking-changes-build.yml
@@ -0,0 +1,49 @@
+name: Levitate / Detect breaking changes
+
+on: pull_request
+
+jobs:
+ build:
+ name: Detect
+ runs-on: ubuntu-latest
+
+ steps:
+ - uses: actions/checkout@v2
+
+ - name: Setup environment
+ uses: actions/setup-node@v2
+ with:
+ node-version: '16'
+
+ - name: Get link for the Github Action job
+ id: job
+ uses: actions/github-script@v5
+ with:
+ script: |
+ const script = require('./.github/workflows/scripts/pr-get-job-link.js')
+ await script({github, context, core})
+
+ - name: Install dependencies
+ run: yarn install --immutable
+
+ - name: Build packages
+ run: yarn packages:build
+
+ - name: Detect breaking changes
+ id: breaking-changes
+ run: ./scripts/check-breaking-changes.sh
+ env:
+ FORCE_COLOR: 3
+ GITHUB_JOB_LINK: ${{ steps.job.outputs.link }}
+ GITHUB_STEP_NUMBER: 7
+
+ - name: Persisting the check output
+ run: |
+ mkdir -p ./levitate
+ echo "{ \"exit_code\": ${{ steps.breaking-changes.outputs.is_breaking }}, \"message\": \"${{ steps.breaking-changes.outputs.mesage }}\", \"job_link\": \"${{ steps.job.outputs.link }}\" }" > ./levitate/result.json
+
+ - name: Upload check output as artifact
+ uses: actions/upload-artifact@v2
+ with:
+ name: levitate
+ path: levitate/
diff --git a/.github/workflows/detect-breaking-changes.yml b/.github/workflows/detect-breaking-changes-report.yml
similarity index 50%
rename from .github/workflows/detect-breaking-changes.yml
rename to .github/workflows/detect-breaking-changes-report.yml
index b4f92c57ca5..5c7c3c3f209 100644
--- a/.github/workflows/detect-breaking-changes.yml
+++ b/.github/workflows/detect-breaking-changes-report.yml
@@ -1,46 +1,53 @@
-name: Levitate
+name: Levitate / Report breaking changes
-on: push
+on:
+ workflow_run:
+ workflows: ["Levitate / Detect breaking changes"]
+ types: [completed]
jobs:
- build:
- name: Detecting breaking changes
+ notify:
+ name: Report
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- - name: Install Node.js
+ - name: Setup environment
uses: actions/setup-node@v2
with:
- node-version: '16'
+ node-version: 16
+ - run: npm install adm-zip
- - name: Install Yarn
- run: npm install --global yarn
-
- # We need this as we can only access the "Run ID" through the context and we need the "Job ID".
- - name: Get link for the Github Action job
- id: get-job-link
+ - name: Download artifact
uses: actions/github-script@v5
+ id: download-artifact
+ env:
+ RUN_ID: ${{github.event.workflow_run.id }}
with:
result-encoding: string
script: |
- const { owner, repo } = context.repo;
- const url = `https://api.github.com/repos/${owner}/${repo}/actions/runs/${context.runId}/jobs`
- const result = await github.request(url)
- console.log(result.data)
-
- return `https://github.com/grafana/grafana/runs/${result.data.jobs[0].id}?check_suite_focus=true`;
-
- - name: Find current pull request ID
- uses: jwalton/gh-find-current-pr@v1
- id: finder
+ const runId = process.env.RUN_ID;
+ const artifactName = 'levitate';
+ const script = require('./.github/workflows/scripts/get-workflow-run-artifact.js');
+ return await script({ github, context, core, runId, artifactName });
+
+ - name: Parsing levitate result
+ uses: actions/github-script@v5
+ id: levitate-run
+ env:
+ ARTIFACT_FOLDER: ${{ steps.download-artifact.outputs.result }}
+ with:
+ script: |
+ const filePath = `${process.env.ARTIFACT_FOLDER}/result.json`;
+ const script = require('./.github/workflows/scripts/json-file-to-job-output.js');
+ await script({ core, filePath });
- name: Check if "breaking change" label exists
id: does-label-exist
uses: actions/github-script@v5
env:
- PR_NUMBER: ${{ steps.finder.outputs.pr }}
+ PR_NUMBER: ${{ github.event.workflow_run.pull_requests[0].number }}
with:
script: |
const { data } = await github.rest.issues.listLabelsOnIssue({
@@ -53,52 +60,36 @@ jobs:
return doesExist ? 1 : 0;
- - name: Debug
- run: echo -e "Job link - ${{steps.get-job-link.outputs.result}} \nPull request - ${{steps.finder.outputs.pr}} \nLabel exists - ${{steps.does-label-exist.outputs.result}}"
-
- - name: Install dependencies
- run: yarn install --immutable
-
- - name: Build packages
- run: yarn packages:build
-
- - name: Detect breaking changes
- id: breaking-changes
- run: ./scripts/check-breaking-changes.sh
- env:
- FORCE_COLOR: 3
- GITHUB_JOB_LINK: ${{steps.get-job-link.outputs.result}}
-
- name: Comment on PR
- if: ${{ steps.breaking-changes.outputs.is_breaking == 1 }}
+ if: ${{ steps.levitate-run.outputs.exit_code == 1 }}
uses: marocchino/sticky-pull-request-comment@v2
with:
- number: ${{ steps.finder.outputs.pr }}
+ number: ${{ github.event.workflow_run.pull_requests[0].number }}
message: |
⚠️ **Possible breaking changes**
_(Open the links below in a new tab to go to the correct steps)_
- ${{ steps.breaking-changes.outputs.message }}
+ ${{ steps.levitate-run.outputs.message }}
- [Check console output](${{steps.get-job-link.outputs.result}})
+ [Check console output](${{ steps.levitate-run.outputs.job_link }})
- name: Remove comment on PR
- if: ${{ steps.breaking-changes.outputs.is_breaking == 0 }}
+ if: ${{ steps.levitate-run.outputs.exit_code == 0 }}
uses: marocchino/sticky-pull-request-comment@v2
with:
- number: ${{ steps.finder.outputs.pr }}
+ number: ${{ github.event.workflow_run.pull_requests[0].number }}
delete: true
- name: Add "breaking change" label
- if: ${{ steps.breaking-changes.outputs.is_breaking == 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@v5
env:
- PR_NUMBER: ${{ steps.finder.outputs.pr }}
+ PR_NUMBER: ${{ github.event.workflow_run.pull_requests[0].number }}
with:
script: |
- github.rest.issues.addLabels({
+ await github.rest.issues.addLabels({
issue_number: process.env.PR_NUMBER,
owner: context.repo.owner,
repo: context.repo.repo,
@@ -106,13 +97,13 @@ jobs:
})
- name: Remove "breaking change" label
- if: ${{ steps.breaking-changes.outputs.is_breaking == 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@v5
env:
- PR_NUMBER: ${{ steps.finder.outputs.pr }}
+ PR_NUMBER: ${{ github.event.workflow_run.pull_requests[0].number }}
with:
script: |
- github.rest.issues.removeLabel({
+ await github.rest.issues.removeLabel({
issue_number: process.env.PR_NUMBER,
owner: context.repo.owner,
repo: context.repo.repo,
@@ -122,40 +113,36 @@ jobs:
# 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
- name: Add "grafana/plugins-platform-frontend" as a reviewer
- if: ${{ steps.breaking-changes.outputs.is_breaking == 1 }}
+ if: ${{ steps.levitate-run.outputs.exit_code == 1 }}
uses: actions/github-script@v5
env:
- PR_NUMBER: ${{ steps.finder.outputs.pr }}
+ PR_NUMBER: ${{ github.event.workflow_run.pull_requests[0].number }}
with:
script: |
- const response = await github.rest.pulls.requestReviewers({
+ await github.rest.pulls.requestReviewers({
pull_number: process.env.PR_NUMBER,
owner: context.repo.owner,
repo: context.repo.repo,
reviewers: [],
team_reviewers: ['grafana/plugins-platform-frontend']
- })
-
- console.log(response)
+ });
- name: Remove "grafana/plugins-platform-frontend" from the list of reviewers
- if: ${{ steps.breaking-changes.outputs.is_breaking == 0 }}
+ if: ${{ steps.levitate-run.outputs.exit_code == 0 }}
uses: actions/github-script@v5
env:
- PR_NUMBER: ${{ steps.finder.outputs.pr }}
+ PR_NUMBER: ${{ github.event.workflow_run.pull_requests[0].number }}
with:
script: |
- const response = await github.rest.pulls.removeRequestedReviewers({
+ await github.rest.pulls.removeRequestedReviewers({
pull_number: process.env.PR_NUMBER,
owner: context.repo.owner,
repo: context.repo.repo,
reviewers: [],
team_reviewers: ['grafana/plugins-platform-frontend']
- })
-
- console.log(response)
+ });
- name: Exit
- run: exit ${{ steps.breaking-changes.outputs.is_breaking }}
+ run: exit ${{ steps.levitate-run.outputs.exit_code }}
shell: bash
diff --git a/.github/workflows/scripts/get-workflow-run-artifact.js b/.github/workflows/scripts/get-workflow-run-artifact.js
new file mode 100644
index 00000000000..a59276ed1d8
--- /dev/null
+++ b/.github/workflows/scripts/get-workflow-run-artifact.js
@@ -0,0 +1,45 @@
+module.exports = async ({ github, context, core, runId, artifactName }) => {
+ try {
+ const AdmZip = require('adm-zip');
+ const fs = require('fs');
+
+ const { owner, repo } = context.repo;
+ const { data } = await github.rest.actions.listWorkflowRunArtifacts({
+ owner,
+ repo,
+ run_id: runId,
+ });
+
+ const artifact = data.artifacts.find(a => a.name === artifactName);
+
+ if (!artifact) {
+ throw new Error(`Could not find artifact ${artifactName} in workflow (${runId})`);
+ }
+
+ const zip = await github.rest.actions.downloadArtifact({
+ owner,
+ repo,
+ artifact_id: artifact.id,
+ archive_format: "zip",
+ });
+
+ const dir = `./tmp/${artifactName}`;
+ await mkdirRecursive(fs, dir);
+
+ const admZip = new AdmZip(Buffer.from(zip.data));
+ admZip.extractAllTo(dir, true);
+
+ return dir;
+ } catch (error) {
+ core.restFailed(error.message);
+ }
+}
+
+async function mkdirRecursive(fs, path) {
+ return new Promise((resolve, reject) => {
+ fs.mkdir(path, { recursive: true }, (error) => {
+ if (error) return reject(error);
+ return resolve();
+ });
+ });
+}
\ No newline at end of file
diff --git a/.github/workflows/scripts/json-file-to-job-output.js b/.github/workflows/scripts/json-file-to-job-output.js
new file mode 100644
index 00000000000..0f6dd1e65ff
--- /dev/null
+++ b/.github/workflows/scripts/json-file-to-job-output.js
@@ -0,0 +1,27 @@
+module.exports = async ({ core, filePath }) => {
+ try {
+ const fs = require('fs');
+ const content = await readFile(fs, filePath);
+ const result = JSON.parse(content);
+
+ core.startGroup('Parsing json file...');
+
+ for (const property in result) {
+ core.info(`${property} <- ${result[property]}`);
+ core.setOutput(property, result[property]);
+ }
+
+ core.endGroup();
+ } catch (error) {
+ core.restFailed(error.message);
+ }
+}
+
+async function readFile(fs, path) {
+ return new Promise((resolve, reject) => {
+ fs.readFile(path, (error, data) => {
+ if (error) return reject(error);
+ return resolve(data);
+ });
+ });
+}
\ No newline at end of file
diff --git a/.github/workflows/scripts/pr-get-job-link.js b/.github/workflows/scripts/pr-get-job-link.js
new file mode 100644
index 00000000000..a4e6bc2f645
--- /dev/null
+++ b/.github/workflows/scripts/pr-get-job-link.js
@@ -0,0 +1,9 @@
+
+module.exports = async ({ github, context, core }) => {
+ const { owner, repo } = context.repo;
+ const url = `https://api.github.com/repos/${owner}/${repo}/actions/runs/${context.runId}/jobs`
+ const result = await github.request(url)
+ const link = `https://github.com/grafana/grafana/runs/${result.data.jobs[0].id}?check_suite_focus=true`;
+
+ core.setOutput('link', link);
+}
\ No newline at end of file
diff --git a/scripts/check-breaking-changes.sh b/scripts/check-breaking-changes.sh
index a57b763f2f8..70460b9be58 100755
--- a/scripts/check-breaking-changes.sh
+++ b/scripts/check-breaking-changes.sh
@@ -1,10 +1,11 @@
#!/usr/bin/env bash
+# Find existing packages using Lerna
PACKAGES=$(lerna list -p -l)
EXIT_CODE=0
GITHUB_MESSAGE=""
-# Loop through packages
+# Loop through the packages
while IFS= read -r line; do
# Read package info
@@ -16,7 +17,6 @@ while IFS= read -r line; do
PREV="$PACKAGE_NAME@canary"
CURRENT="$PACKAGE_PATH/dist/"
-
# Temporarily skipping @grafana/toolkit, as it doesn't have any exposed static typing
if [[ "$PACKAGE_NAME" == '@grafana/toolkit' ]]; then
continue
@@ -39,7 +39,7 @@ while IFS= read -r line; do
if [ $STATUS -gt 0 ]
then
EXIT_CODE=1
- GITHUB_MESSAGE="${GITHUB_MESSAGE}**\`${PACKAGE_NAME}\`** has possible breaking changes ([more info](${GITHUB_JOB_LINK}#step:11:1))
"
+ GITHUB_MESSAGE="${GITHUB_MESSAGE}**\`${PACKAGE_NAME}\`** has possible breaking changes ([more info](${GITHUB_JOB_LINK}#step:${GITHUB_STEP_NUMBER}:1))
"
fi
done <<< "$PACKAGES"