diff --git a/.github/workflows/test-terms-of-service-run.yml b/.github/workflows/test-terms-of-service-acceptance-run.yml similarity index 100% rename from .github/workflows/test-terms-of-service-run.yml rename to .github/workflows/test-terms-of-service-acceptance-run.yml diff --git a/README.md b/README.md index c97e951..51dcc74 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,81 @@ A collection of composite Github Actions -## terms-of-service-acceptance/run +## Publish Build Scans® from forked repositories + +### Description +When submitting a pull request, a Github workflow that validates the change is usually triggered, however the Develocity Build Scans® can’t be published for 2 reasons: +- The Develocity Terms of Service have not been agreed to by the contributor +- Workflows from forked repositories do not have access to secrets although an access token is required to publish a Build Scan® + +This repository contains some actions which can be combined together to solve this. + +### Architecture +![Architecture](./doc/architecture.png) + +### Usage + +**Usage**: + +Insert the `Save Build Scan` step after each Maven execution step in the Github workflow called to validate a pull-request (`Build with Maven` here). + +```yaml +[...] + - name: Build with Maven + run: mvn clean package + - name: Save Build Scan + uses: gradle/github-actions/maven-build-scan/save@v1.0 +[...] +``` + +Add a workflow to publish the Build Scans® saved during the previous step + +_Note:_ +Some parameters need to be adjusted here: +- The workflow name (here `Build`) triggered when a pull-request is submitted +- The build workflow filename (here `build.yml`) has to be adjusted to the filename of the workflow using `maven-build-scan/save` +- The Develocity URL (here `https://`) +- The secret name holding the Develocity access key (here ``) + +```yaml +name: Upload Build Scans + +on: + workflow_run: + workflows: [ "Build" ] + types: [ completed ] + issue_comment: + types: [ created ] + +jobs: + + publish-build-scans: + runs-on: ubuntu-latest + permissions: + contents: write + pull-requests: write + steps: + - name: Load data + id: load + uses: gradle/github-actions/maven-build-scan/load@v1.0 + with: + build-workflow-filename: 'build.yml' + - name: Verify Terms of Service acceptance + uses: gradle/github-actions/terms-of-service-acceptance/run@v1.0 + with: + tos-location: 'https://foo.bar/tos.html' + pr-number: ${{ steps.load.outputs.pr-number }} + - name: Publish Maven Build Scans + uses: gradle/github-actions/maven-build-scan/publish@v1.0 + with: + develocity-url: 'https://' + develocity-access-key: ${{ secrets. }} + pr-number: ${{ steps.load.outputs.pr-number }} +``` + +### Implementation details + +#### terms-of-service-acceptance/run A composite action to verify that Develocity Terms of Service have been accepted. @@ -19,22 +93,21 @@ See the [cla-assistant-lite documentation](https://github.com/marketplace/action **Event Triggers**: This action should be configured to respond to the following event triggers: -- `pull_request_target`: to check if the user has previously accepted the Terms of Service when submitting the pull-request. -- `issue-comment`: to check if any new pull-request comment is accepting the Terms of Service. +- `workflow_run`: to check if the user has previously accepted the Terms of Service before publishing a Build Scan®. +- `issue_comment`: to check if any new pull-request comment is accepting the Terms of Service. **Permissions**: The following permissions are required for this action to operate: - `contents: write`: to create/edit the signature file - `pull-requests: write`: to comment the pull-request -- `actions: write`: to update the pull-request status check -- `statuses: write`: to update the pull-request status check **Action inputs**: | Name | Description | Default | |------------------------------------------|------------------------------------------------------------------------------------------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------| | `tos-location` | Terms Of Service location (URL) | | +| `pr-number` | pull-request number | | | `signature-branch` | *Optional*: Git branch where the signature file will be stored | `${{ github.event.repository.default_branch }}` | | `signature-location` | *Optional*: Signature file location | `.github/develocity-tos.json` | | `pr-comment-tos-acceptance-missing` | *Optional*: pull-request comment added when Terms of Service have not previously been accepted | `Please accept [Develocity Terms Of Service]({0}) to get your pull-request Build Scan published by commenting this pull-request with the following message:` | @@ -45,43 +118,21 @@ The following permissions are required for this action to operate: **Usage**: -```yaml -name: Gradle - Terms of Service acceptance verification - -on: - # issue_comment event is triggered when a pull-request is commented - issue_comment: - types: [ created ] - pull_request_target: +_Note:_ +Some parameters need to be adjusted here: +- The pull-request number (here `steps.load.outputs.pr-number`) has to be adjusted to the value set in the context -jobs: - run-terms-of-service-acceptance: - runs-on: ubuntu-latest - permissions: - # required to update signature file - contents: write - # required to comment pull-request - pull-requests: write - # required to update pull-request status check - actions: write - statuses: write - steps: - - name: Run Terms of Service acceptance verification +```yaml +[...] + - name: Verify Terms of Service acceptance uses: gradle/github-actions/terms-of-service-acceptance/run@v1.0 with: - # tos-location can also point to a file in a Github repository with this syntax: ///blob//tos.html tos-location: 'https://foo.bar/tos.html' - # Optional inputs - #pr-comment-tos-acceptance-missing: 'Please accept [Develocity Terms Of Service]({0}) to get your pull-request Build Scan published by commenting this pull-request with the following message:' - #pr-comment-tos-acceptance-request: 'I have read Develocity Terms Of Service and I hereby accept the Terms' - #pr-comment-tos-acceptance-validation: 'All Contributors have accepted Develocity Terms Of Service.' - #signature-branch: 'main' - #signature-location: '.github/develocity-tos.json' - #white-list: 'bot1,bot2' - #github-token: ${{ secrets.MY_PAT }} + pr-number: ${{ steps.load.outputs.pr-number }} +[...] ``` -## maven-build-scan/save +#### maven-build-scan/save A Composite action to save an unpublished Maven Build Scan®. The action saves unpublished Build Scan® data as a workflow artifact with name `maven-build-scan-data`, which can then be published in a dependent workflow. @@ -115,24 +166,74 @@ Insert the `Save Build Scan` step after each Maven execution step in the Github [...] ``` -## maven-build-scan/publish +#### maven-build-scan/load +A Composite action to load artifacts saved by `maven-build-scan/save`. + +Use this action in a separate workflow to prepare the Build Scan® publication. + +**Dependencies**: + +- [dawidd6/action-download-artifact](https://github.com/marketplace/actions/download-workflow-artifact) + +**Event Triggers**: + +This action should be configured to respond to the following event trigger (see `maven-build-scan/publish` for more details): +- `workflow_run`: to run after the pull-request workflow. +- `issue_comment`: to run after the pull-request is commented. + +The action fails for any other event trigger, or if the comment is different than `recheck` or `I have read Develocity Terms Of Service and I hereby accept the Terms` (can be overridden). + +**Action inputs**: + +| Name | Description | Default | +|-------------------------------------|----------------------------------------------------------------------------------------------|-------------------------------------------------------------------------| +| `build-workflow-filename` | Filename of the workflow using `maven-build-scan/save` (called upon pull-request submission) | | +| `pr-comment-tos-acceptance-request` | *Optional*: pull-request comment to accept the Terms of Service | `I have read Develocity Terms Of Service and I hereby accept the Terms` | + +**Action outputs**: + +| Name | Description | +|--------------|--------------------------------------------------------------| +| `pr-number` | pull-request number saved by `maven-build-scan/save` action | + +**Usage**: + +_Note:_ +Some parameters need to be adjusted here: +- The build workflow filename (here `build.yml`) has to be adjusted to the filename of the workflow using `maven-build-scan/save` + +```yaml +[...] + - name: Load Build Scan data + id: load + uses: gradle/github-actions/maven-build-scan/load@v1.0 + with: + build-workflow-filename: 'build.yml' +[...] +``` + +#### maven-build-scan/publish This action will publish all Maven Build Scans® that have been saved as workflow artifacts by the `maven-build-scan/save` action. -Use this action in a separate workflow with a `workflow_run` event trigger, that will run after an existing pull-request workflow has completed. The action will download any saved Build Scan® and publish them to Develocity. -This event allows access to the repository secrets (_Develocity Access Key_) which is required to publish a Build Scan® to Gradle Enterprise when authentication is enabled. +Use this action in a separate workflow with: +- a `workflow_run` event trigger, that will run after an existing pull-request workflow has completed. +- a `issue_comment` event trigger, that will run after a comment accepting the Terms of Service is added to the pull-request +These event allows access to the repository secrets (_Develocity Access Key_) which is required to publish a Build Scan® to Gradle Enterprise when authentication is enabled. + +The action will download any saved Build Scan® and publish them to Develocity. -The Build Scan® publication requires the Gradle Terms of Service to be accepted, this can be achieved by adding a workflow using the `terms-of-service-acceptance/run` action. -The `terms-of-service-acceptance/verify` action is used to ensure this workflow passed successfully. +The Build Scan® publication requires the Gradle Terms of Service to be accepted, this can be achieved by adding a previous step using the `terms-of-service-acceptance/run` action. **Dependencies**: -- [dawidd6/action-download-artifact](https://github.com/marketplace/actions/download-workflow-artifact) +N/A **Event Triggers**: This action should be configured to respond to the following event trigger: - `workflow_run`: to run after the pull-request workflow. +- `issue_comment`: to run after the pull-request is commented. **Permissions**: @@ -141,44 +242,28 @@ The following permissions are required for this action to operate: **Action inputs**: -| Name | Description | Default | -|-------------------------------|-----------------------------------------------|-----------------------| -| `develocity-url` | Develocity URL | | -| `develocity-access-key` | *Optional*: Develocity access key | | -| `develocity-allow-untrusted` | *Optional*: Develocity allow-untrusted flag | `false` | -| `github-token` | *Optional*: Github token | `${{ github.token }}` | +| Name | Description | Default | +|--------------------------------|---------------------------------------------|-----------------------| +| `develocity-url` | Develocity URL | | +| `pr-number` | pull-request number | | +| `develocity-access-key` | *Optional*: Develocity access key | | +| `develocity-allow-untrusted` | *Optional*: Develocity allow-untrusted flag | `false` | +| `github-token` | *Optional*: Github token | `${{ github.token }}` | **Usage**: _Note:_ Some parameters need to be adjusted here: -- The workflow name (here `PR Check`) has to be adjusted to the `name` used in the workflow run to validate pull-requests -- The workflow-job-name (here `run-terms-of-service-acceptance`) has to be adjusted to the job `name` used in the workflow to verify the Terms of Service approval. - The Develocity URL (here `https://`) - The secret name holding the Develocity access key (here ``) ```yaml -name: Publish Maven Build Scans - -on: - workflow_run: - workflows: [ "PR Check" ] - types: [ completed ] - -jobs: - - publish-build-scans: - runs-on: ubuntu-latest - permissions: - pull-requests: write - steps: - - name: Verify Terms of Service acceptance job passed - uses: gradle/github-actions/terms-of-service-acceptance/verify@v1.0 - with: - terms-of-service-acceptance-workflow-job-name: 'run-terms-of-service-acceptance' +[...] - name: Publish Maven Build Scans uses: gradle/github-actions/maven-build-scan/publish@v1.0 with: develocity-url: 'https://' develocity-access-key: ${{ secrets. }} + pr-number: ${{ steps.load.outputs.pr-number }} +[...] ``` diff --git a/doc/architecture.png b/doc/architecture.png new file mode 100644 index 0000000..26d0dd0 Binary files /dev/null and b/doc/architecture.png differ diff --git a/maven-build-scan/load/action.yml b/maven-build-scan/load/action.yml new file mode 100644 index 0000000..1161db8 --- /dev/null +++ b/maven-build-scan/load/action.yml @@ -0,0 +1,68 @@ +name: Load Maven Build Scans +description: Load Maven Build Scans + +inputs: + build-workflow-filename: + description: 'Filename of the workflow where the maven-build-scan/save action was triggered' + required: true + pr-comment-tos-acceptance-request: + description: 'pull-request comment to accept the Terms of Service' + default: 'I have read Develocity Terms of Service and I hereby accept the Terms' + +outputs: + pr-number: + description: "pull-request number" + value: ${{ steps.pr.outputs.PR_NUMBER }} + +runs: + using: 'composite' + steps: + - name: Check event trigger + if: | + (github.event_name != 'issue_comment' + || ( + github.event.comment.body != 'recheck' + && github.event.comment.body != inputs.pr-comment-tos-acceptance-request + ) + ) + && github.event_name != 'workflow_run' + run: | + echo "Skipping Github event" + exit 1 + shell: bash + - name: Download Build Metadata after PR Build + if: github.event_name == 'workflow_run' + uses: dawidd6/action-download-artifact@v2 + env: + ARTIFACT_NAME: 'maven-build-scan-data' + with: + run_id: ${{ github.event.workflow_run.id }} + name: ${{ env.ARTIFACT_NAME }} + path: ${{ env.ARTIFACT_NAME }} + - name: Download Build Metadata after PR Comment + if: github.event_name == 'issue_comment' + env: + ARTIFACT_NAME: 'maven-build-scan-data' + uses: dawidd6/action-download-artifact@v2 + with: + pr: ${{ github.event.issue.number }} + workflow_conclusion: success + workflow: ${{ inputs.build-workflow-filename }} + name: ${{ env.ARTIFACT_NAME }} + path: ${{ env.ARTIFACT_NAME }} + - name: Restore Build Scans + env: + ARTIFACT_NAME: 'maven-build-scan-data' + BUILD_SCAN_DIR: '~/.m2/.gradle-enterprise/build-scan-data/' + run: | + mkdir -p ${{ env.BUILD_SCAN_DIR }} + cp -r ${{ env.ARTIFACT_NAME }}/* ${{ env.BUILD_SCAN_DIR }} + shell: bash + - name: Collect pull-request number + id: pr + env: + BUILD_SCAN_DIR: '~/.m2/.gradle-enterprise/build-scan-data/' + run: | + source $(find ${{ env.BUILD_SCAN_DIR }} -type f -name "pr-number.properties") + echo "PR_NUMBER=$PR_NUMBER" >> $GITHUB_OUTPUT + shell: bash diff --git a/maven-build-scan/publish/action.yml b/maven-build-scan/publish/action.yml index a2d9a83..1b89639 100644 --- a/maven-build-scan/publish/action.yml +++ b/maven-build-scan/publish/action.yml @@ -15,34 +15,13 @@ inputs: description: 'The token used for Github API requests' default: ${{ github.token }} required: false + pr-number: + description: 'PR number' + required: true runs: using: 'composite' steps: - - name: Download Build Scans - uses: dawidd6/action-download-artifact@v2 - env: - ARTIFACT_NAME: 'maven-build-scan-data' - with: - run_id: ${{ github.event.workflow_run.id }} - name: ${{ env.ARTIFACT_NAME }} - path: ${{ env.ARTIFACT_NAME }} - - name: Restore Build Scans - env: - ARTIFACT_NAME: 'maven-build-scan-data' - BUILD_SCAN_DIR: '~/.m2/.gradle-enterprise/build-scan-data/' - run: | - mkdir -p ${{ env.BUILD_SCAN_DIR }} - cp -r ${{ env.ARTIFACT_NAME }}/* ${{ env.BUILD_SCAN_DIR }} - shell: bash - - name: Collect pull-request number - id: pr - env: - BUILD_SCAN_DIR: '~/.m2/.gradle-enterprise/build-scan-data/' - run: | - source $(find ${{ env.BUILD_SCAN_DIR }} -type f -name "pr-number.properties") - echo "PR_NUMBER=$PR_NUMBER" >> $GITHUB_OUTPUT - shell: bash - name: Create Maven Project Structure env: PROJECT_DIR: 'maven-build-scan-publisher' @@ -128,7 +107,7 @@ runs: - name: Comment pull-request with Build Scan links uses: actions/github-script@v6 env: - PR: ${{ steps.pr.outputs.PR_NUMBER }} + PR: ${{ inputs.pr-number }} SCAN_LINKS: ${{ steps.publish.outputs.SCAN_LINKS }} with: github-token: ${{ inputs.github-token }} diff --git a/terms-of-service-acceptance/run/action.yml b/terms-of-service-acceptance/run/action.yml index 7a881cc..34684a9 100644 --- a/terms-of-service-acceptance/run/action.yml +++ b/terms-of-service-acceptance/run/action.yml @@ -5,6 +5,9 @@ inputs: tos-location: description: 'Terms of Service location as an URL (https://foo.com/tos.html) or a Github repository file (///blob//tos.html)' required: true + pr-number: + description: 'pull-request number' + required: true pr-comment-tos-acceptance-missing: description: 'pull-request comment added when Terms of Service are not accepted ({0} in the value will be replaced by tos-location input)' default: 'Please accept [Develocity Terms of Service]({0}) to get your pull-request Build Scan published by commenting this pull-request with the following message:' @@ -32,8 +35,9 @@ runs: using: 'composite' steps: - name: Run Terms of Service acceptance - if: (github.event.comment.body == 'recheck' || github.event.comment.body == ${{ inputs.pr-comment-tos-acceptance-request }}) || github.event_name == 'pull_request_target' || github.event_name == 'pull_request' - uses: contributor-assistant/github-action@v2.3.0 +# uses: contributor-assistant/github-action@v2.3.0 + id: check + uses: jprinet/check-terms-of-service@v1 env: GITHUB_TOKEN: ${{ inputs.github-token }} with: @@ -45,3 +49,4 @@ runs: allowlist: ${{ inputs.white-list }} path-to-document: 'unused' lock-pullrequest-aftermerge: false + pr-number: ${{ inputs.pr-number }} diff --git a/terms-of-service-acceptance/verify/action.yml b/terms-of-service-acceptance/verify/action.yml deleted file mode 100644 index 20b7c9b..0000000 --- a/terms-of-service-acceptance/verify/action.yml +++ /dev/null @@ -1,41 +0,0 @@ -name: Verify Terms of Service acceptance -description: Verify that the Terms of Service acceptance workflow has completed successfully - -inputs: - terms-of-service-acceptance-workflow-job-name: - description: 'The name of the workflow job that checks for Terms of Service acceptance' - required: true - github-token: - description: 'The token used for Github API requests' - default: ${{ github.token }} - required: false - -runs: - using: 'composite' - steps: - - name: Verify Terms of Service acceptance - uses: actions/github-script@v6 - env: - sha: ${{ github.event.workflow_run.head_sha }} - with: - github-token: ${{ inputs.github-token }} - result-encoding: string - script: | - // returns most recent check runs first by default - const checkRuns = await github.paginate('GET /repos/${{ github.repository }}/commits/{ref}/check-runs', { - ref: process.env.sha, - per_page: 50 - }); - for await (const cr of checkRuns) { - // check only last execution of the workflow - console.log('Checking execution of ' + cr.name); - if(cr.name == '${{ inputs.terms-of-service-acceptance-workflow-job-name }}') { - console.log('Found execution of ${{ inputs.terms-of-service-acceptance-workflow-job-name }} at ' + cr.completed_at); - if(cr.conclusion == 'success') { - return; - } else { - throw new Error('Found failed execution of ${{ inputs.terms-of-service-acceptance-workflow-job-name }} at ' + cr.completed_at); - } - } - } - throw new Error('No execution found for ${{ inputs.terms-of-service-acceptance-workflow-job-name }}');