Skip to content

Commit

Permalink
Overhaul mavenLicenseCheck workflow
Browse files Browse the repository at this point in the history
  • Loading branch information
Thomas Neidhart committed Sep 9, 2024
1 parent 36a6914 commit 669ec67
Show file tree
Hide file tree
Showing 2 changed files with 165 additions and 73 deletions.
20 changes: 11 additions & 9 deletions .github/actions/maven-license-check-action/action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -29,20 +29,22 @@ runs:
shell: bash {0} # do not fail-fast
run: |
mvnArgs="-U -B -ntp org.eclipse.dash:license-tool-plugin:license-check -Ddash.fail=true -Dtycho.target.eager=true --settings $GITHUB_ACTION_PATH/licenseCheckMavenSettings.xml"
if [[ ${{ inputs.project-id }} != "" ]]; then
mvnArgs+=" -Ddash.repo=https://github.com/${{ github.repository }}"
if [[ "${{ inputs.project-id }}" != "" ]]; then
mvnArgs+=" -Ddash.projectId=${{ inputs.project-id }}"
fi
if [ ${{ inputs.request-review }} ]; then
if [ "${{ inputs.request-review }}" != "" ]; then
mvn ${mvnArgs} -Ddash.iplab.token=$GITLAB_API_TOKEN
if [[ $? == 0 ]]; then # All licenses are vetted
echo "build-succeeded=1" >> $GITHUB_OUTPUT
else
echo "build-succeeded=0" >> $GITHUB_OUTPUT
fi
else
mvn ${mvnArgs}
if [[ $? != 0 ]]; then
fi
if [[ $? == 0 ]]; then # All licenses are vetted
echo "build-succeeded=1" >> $GITHUB_OUTPUT
else
if [[ "${{ inputs.request-review }}" = "" ]]; then
echo "Committers can request a review by commenting '/request-license-review'"
exit 1
fi
echo "build-succeeded=0" >> $GITHUB_OUTPUT
fi
218 changes: 154 additions & 64 deletions .github/workflows/mavenLicenseCheck.yml
Original file line number Diff line number Diff line change
Expand Up @@ -50,29 +50,43 @@ on:
required: false

jobs:
check-licenses:
if: github.event_name != 'issue_comment' || ( github.event.issue.pull_request != '' && (github.event.comment.body == '/request-license-review') )
check-request:
# Run on all non-comment events specified by the calling workflow and for comments on PRs that have a corresponding body.
if: >
github.event_name != 'issue_comment' ||
(github.event.issue.pull_request &&
(contains(github.event.comment.body, '/request-license-review') ||
contains(github.event.comment.body, '/license-check')))
runs-on: ubuntu-latest
permissions:
pull-requests: write
outputs:
request-review: ${{ steps.request-review.outputs.request-review }}
license-check: ${{ steps.license-check.outputs.license-check }}
steps:

- name: Check dependabot PR
run: echo "isDependabotPR=1" >> $GITHUB_ENV
- name: Check dependabot PR
if: >
github.event_name == 'pull_request' && (github.event.action == 'opened' || github.event.action == 'synchronize' || github.event.action == 'reopened')
github.event_name == 'pull_request'
&& (github.event.action == 'opened' || github.event.action == 'synchronize' || github.event.action == 'reopened')
&& github.actor == 'dependabot[bot]' && github.actor_id == '49699333'
# For 'issue_comment'-events this job only runs if a comment was added to a PR with body specified above
run: echo "isDependabotPR=1" >> $GITHUB_ENV

# For 'issue_comment'-events this job only runs if a comment was added to a PR with body specified above
- name: Set review request
run: echo "request-review=1" >> $GITHUB_ENV
if: github.event_name == 'issue_comment' || env.isDependabotPR
# For 'issue_comment'-events this job only runs if a comment was added to a PR with body specified above
id: request-review
if: (github.event_name == 'issue_comment' && contains(github.event.comment.body, '/request-license-review')) || env.isDependabotPR
run: |
echo "request-review=1" >> "$GITHUB_OUTPUT"
- name: Set license check
id: license-check
if: (github.event_name == 'issue_comment' && contains(github.event.comment.body, '/license-check')) || env.isDependabotPR
run: |
echo "license-check=1" >> "$GITHUB_OUTPUT"
- name: Process license-vetting request
if: env.request-review && (!env.isDependabotPR)
uses: actions/github-script@v7
if: |
(steps.request-review.outputs.request-review || steps.license-check.outputs.license-check)
&& (!env.isDependabotPR)
uses: actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea # v7.0.1
with:
script: |
const payload = await github.rest.repos.getCollaboratorPermissionLevel({
Expand All @@ -90,27 +104,40 @@ jobs:
...context.repo, comment_id: context.payload?.comment?.id, content: reaction
});
# By default the git-ref checked out for events triggered by comments to PRs is 'refs/heads/master'
check-licenses:
needs: check-request
if: ${{needs.check-request.outputs.license-check == ''}}
runs-on: ubuntu-latest
permissions:
pull-requests: write
env:
request-review: ${{ needs.check-request.outputs.request-review }}
license-check: ${{ needs.check-request.outputs.license-check }}
comment-header: '<!-- tag-license-comment -->'
steps:
# By default, the git-ref checked out for events triggered by comments to PRs is 'refs/heads/master'
# and for events triggered by PR creation/updates the ref is 'refs/pull/<PR-number>/merge'.
# So by default only the master-branch would be considered when requesting license-reviews, but we want the PR's state.
# Unless the PR is closed, then we want the master-branch, which allows subsequent license review requests.
- uses: actions/checkout@v4
- uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
# use default ref 'refs/pull/<PR-number>/merge' for PR-events and 'refs/heads/master' for comments if the PR is closed
if: github.event.issue.pull_request == '' || github.event.issue.state != 'open'
with:
submodules: ${{ inputs.submodules }}
- uses: actions/checkout@v4

- uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
if: github.event.issue.pull_request != '' && github.event.issue.state == 'open'
with:
ref: 'refs/pull/${{ github.event.issue.number }}/merge'
submodules: ${{ inputs.submodules }}
if: github.event.issue.pull_request != '' && github.event.issue.state == 'open'

- uses: actions/setup-java@v4
- uses: actions/setup-java@2dfa2011c5b2a0f1489bf9e433881c92c1631f88 # v4.3.0
with:
java-version: ${{ inputs.javaVersion }}
distribution: 'temurin'

- name: Cache local Maven repository
uses: actions/cache@v4
uses: actions/cache@0c45773b623bea8c8e75f6c82b208c3cf94ea4f9 # v4.0.2
with:
path: ~/.m2/repository
# re-cache on changes in the pom and target files
Expand All @@ -124,8 +151,8 @@ jobs:
maven-version: ${{ inputs.mavenVersion }}

- name: Prepare for license check
run: ${{ inputs.setupScript }}
if: inputs.setupScript !=''
run: ${{ inputs.setupScript }}

- name: Check license vetting status (and ask for review if requested)
id: check-license-vetting
Expand All @@ -137,62 +164,125 @@ jobs:
GITLAB_API_TOKEN: ${{ secrets.gitlabAPIToken }}

- name: Process license check results
if: env.request-review
uses: actions/github-script@v7
id: process-results
if: always()
uses: actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea # v7.0.1
with:
result-encoding: string
script: |
const fs = require('fs')
const licenesVetted = ${{ steps.check-license-vetting.outputs.licenses-vetted }}
let commentBody = ''
// if context.payload.comment is empty, this is an explicit review-request through a comment, if not an automated one, e.g. for dependabot PRs
if ( context.payload.comment ) {
commentBody += '> ' + context.payload.comment.body + '\n\n'
} else if ( licenesVetted ){
core.info('License review request made automatically but all licenses are already vetted.')
return; // Don't create a comment in this case, the checks in the UI indicate the state already.
} else {
// This run encountered pending reviews, which have been requested automatically, e.g. for dependabot PRs
core.setFailed("Some dependencies must be vetted and their review was requested. Rerun this check once these reviews succeeded.")
}
if( licenesVetted ) {
commentBody += ':heavy_check_mark: All licenses already successfully vetted.\n'
const reviewRequested = ${{ env.request-review || false }}
const updateRequested = reviewRequested || ${{ env.license-check || false }}
const licensesVetted = ${{ steps.check-license-vetting.outputs.licenses-vetted }}
let commentBody = "### License summary\n"
if (licensesVetted) {
if (updateRequested) {
commentBody += ':heavy_check_mark: All licenses already successfully vetted.\n'
} else {
// Do not comment if all licenses are vetted and no update was requested
core.info('All licenses are already vetted.')
return;
}
} else {
const reviewSummaryFile = process.env.GITHUB_WORKSPACE + '/target/dash/review-summary'
core.info("Read review summary at " + reviewSummaryFile)
// Print dependency info
const dependencySummaryFile = 'target/dash/summary'
core.info("Read dependency summary at " + dependencySummaryFile)
let content = "";
if ( fs.existsSync( reviewSummaryFile )) {
content = fs.readFileSync( reviewSummaryFile, {encoding: 'utf8'}).trim();
if (fs.existsSync(dependencySummaryFile)) {
content = fs.readFileSync(dependencySummaryFile, { encoding: 'utf8' }).trim();
}
if ( content ) { // not empty
commentBody += 'License review requests:\n'
if (content) { // not empty
commentBody += ":x: Not yet vetted dependencies:\n"
commentBody += "| Dependency | License | Status | Ticket |\n"
commentBody += "|------------|---------|--------|--------|\n"
const lines = content.split('\n')
for(var line = 0; line < lines.length; line++){
commentBody += ('- ' + lines[line] + '\n')
let notVettedDependencies = 0
for (const line of lines) {
if (line.includes('restricted')) {
commentBody += `| ${line.split(", ").join(" | ")} |\n`
notVettedDependencies++
}
}
core.setFailed(`${notVettedDependencies} dependencies are not vetted yet.`)
} else {
commentBody += ':warning: Failed to process summary.\n'
core.setFailed('Failed to process dash summary')
}
if (reviewRequested) {
const reviewSummaryFile = "target/dash/review-summary"
let reviews = "";
if (fs.existsSync(reviewSummaryFile)) {
reviews = fs.readFileSync(reviewSummaryFile, { encoding: 'utf8' }).trim();
}
if (reviews) { // not empty
commentBody += "\n### :rocket: Requested reviews:\n"
const lines = reviews.split('\n')
for (const line of lines) {
commentBody += `- ${line}\n`
}
} else {
core.setFailed("License vetting build failed, but no reviews are created")
commentBody += ':warning: Failed to request review of not vetted licenses.\n'
}
commentBody += '\n'
commentBody += 'After all reviews have concluded, re-run the license-vetting check from the Github Actions web-interface to update its status.\n'
} else {
core.setFailed("License vetting build failed, but no reviews are created")
commentBody += ':warning: Failed to request review of not vetted licenses.\n'
commentBody += '\n\n- Committers can request a license review via by commenting `/request-license-review`.\n- After all reviews have concluded, Committers can re-run the license-vetting check by commenting `/license-check`\n'
}
}
commentBody += '\n'
commentBody += 'Workflow run (with attached summary files):\n'
commentBody += context.serverUrl + "/" + process.env.GITHUB_REPOSITORY + "/actions/runs/" + context.runId
github.rest.issues.createComment({
issue_number: context.issue.number, ...context.repo, body: commentBody
})
- uses: actions/upload-artifact@v4
if: always() && env.request-review
commentBody += `\nWorkflow run (with attached summary files):\n${context.serverUrl}/${process.env.GITHUB_REPOSITORY}/actions/runs/${context.runId}`
return commentBody
- name: Adding comment to job summary
if: always()
run: |
echo '${{steps.process-results.outputs.result}}' >> $GITHUB_STEP_SUMMARY
# Adjust the comment header based on the requested action to ensure that request review comments
# do not get hidden by license checks.
- name: Determine comment header
if: ${{env.request-review}}
run: echo "comment-header='<!-- tag-review-request-comment -->'" >> "$GITHUB_ENV"

# Add the process result as comment to the PR if an update has been requested
# or if the PR is not coming from a fork (in which case we don't have write tokens)
- name: Adding comment to PR
uses: marocchino/sticky-pull-request-comment@331f8f5b4215f0445d3c07b4967662a32a2d3e31 # v2.9.0
if: |
always()
&& (github.event_name == 'issue_comment' || github.event.pull_request.head.repo.full_name == github.repository)
with:
header: ${{env.comment-header}}
hide_and_recreate: true
hide_classify: "OUTDATED"
number: ${{github.event.issue.number}}
message: |
${{steps.process-results.outputs.result}}
- uses: actions/upload-artifact@50769540e7f4bd5e21e526ee35c689e35e0d6874 # v4.4.0
if: always()
with:
name: '${{ inputs.projectId }}-license-vetting-summary'
path: |
target/dash/review-summary
target/dash/summary
# If a rerun is requested, trigger a rerun of the check for the HEAD SHA of the PR
# The reason we do that is because only workflows runs with trigger "pull_request"
# are displayed in the checks tab of a PR.
rerun-check:
needs: check-request
if: ${{needs.check-request.outputs.license-check == '1'}}
runs-on: ubuntu-latest
permissions:
actions: write
steps:
- name: Rerun license check
run: |
HEAD_SHA=$(gh api repos/${{ github.repository }}/pulls/${{ github.event.issue.number }} | jq -r '.head | .sha')
RUNID=$(gh api repos/${{ github.repository }}/commits/${HEAD_SHA}/check-runs | jq -r '.check_runs[] | select(.name | endswith("check-licenses")) | .html_url | capture("/runs/(?<number>[0-9]+)/job") | .number' | sed 's/"//g' | head -n 1)
gh run rerun ${RUNID} --repo ${{ github.repository }}
env:
GH_TOKEN: ${{ github.token }}

0 comments on commit 669ec67

Please sign in to comment.