From 3c0cf0bd25ca6ba50c9d3777eb9df458c0fc1635 Mon Sep 17 00:00:00 2001
From: Jan Was <jan.was@starburstdata.com>
Date: Wed, 1 Dec 2021 13:34:14 +0100
Subject: [PATCH] Annotate workflow jobs

---
 .github/problem-matcher.json   |  18 +++++
 .github/workflows/annotate.yml |  58 +++++++++++++++
 .github/workflows/ci.yml       | 130 +++++++++++++++++++++++++++++++--
 .github/workflows/docs.yml     |  34 +++++++++
 4 files changed, 234 insertions(+), 6 deletions(-)
 create mode 100644 .github/problem-matcher.json
 create mode 100644 .github/workflows/annotate.yml

diff --git a/.github/problem-matcher.json b/.github/problem-matcher.json
new file mode 100644
index 000000000000..f60049a1f38e
--- /dev/null
+++ b/.github/problem-matcher.json
@@ -0,0 +1,18 @@
+{
+  "problemMatcher": [
+    {
+      "owner": "Maven - Error Prone and Checkstyle",
+      "pattern": [
+        {
+          "regexp": "^.*\\[(ERROR|WARN(?:ING)?)\\]\\s+(.*):\\[(\\d+),(\\d+)\\] (?:error: )?[\\[\\(](.*)[\\]\\)] (.*)$",
+          "severity": 1,
+          "file": 2,
+          "line": 3,
+          "column": 4,
+          "message": 6,
+          "code": 5
+        }
+      ]
+    }
+  ]
+}
diff --git a/.github/workflows/annotate.yml b/.github/workflows/annotate.yml
new file mode 100644
index 000000000000..f41e9e7f6612
--- /dev/null
+++ b/.github/workflows/annotate.yml
@@ -0,0 +1,58 @@
+name: Annotate checks
+
+on:
+  workflow_run:
+    workflows: ["ci", "docs"]
+    types:
+      - completed
+
+jobs:
+  annotate:
+    if: github.repository_owner == 'trinodb'
+    runs-on: ubuntu-latest
+    steps:
+      - name: 'Download artifact'
+        uses: actions/github-script@v5
+        with:
+          script: |
+            const fs = require('fs');
+            const opts = github.rest.actions.listWorkflowRunArtifacts.endpoint.merge({
+               owner: context.repo.owner,
+               repo: context.repo.repo,
+               run_id: ${{github.event.workflow_run.id }},
+            });
+            const artifacts = await github.paginate(opts);
+            for (const artifact of artifacts) {
+              if (!artifact.name.startsWith('test report ')) {
+                continue;
+              }
+              const download = await github.rest.actions.downloadArtifact({
+                 owner: context.repo.owner,
+                 repo: context.repo.repo,
+                 artifact_id: artifact.id,
+                 archive_format: 'zip',
+              });
+              fs.writeFileSync('${{github.workspace}}/' + artifact.name + '.zip', Buffer.from(download.data));
+            }
+      - run: |
+          set -xeuo pipefail
+          pwd
+          ls
+          for archive in *.zip; do
+            name=$(basename "$archive" .zip)
+            mkdir "$name"
+            (cd "$name" && unzip ../"$archive")
+          done
+      # Process unit and integration test reports
+      - uses: scacap/action-surefire-report@v1
+        with:
+          # this workflow should never fail, as it is not a quality gateway
+          fail_if_no_tests: false
+          commit: ${{github.event.workflow_run.head_sha}}
+      # Process Product Test reports
+      - uses: starburstdata/action-testng-report@v1.0.3
+        with:
+          # this workflow should never fail, as it is not a quality gateway
+          fail_if_empty: false
+          commit: ${{github.event.workflow_run.head_sha}}
+          github_token: ${{ github.token }}
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index 9f2b80549d64..d85200c07506 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -24,6 +24,7 @@ env:
   # the Docker daemon only downloads 3 layers concurrently which prevents the other pull from making any progress.
   # This value should be greater than the time taken for the longest image pull.
   TESTCONTAINERS_PULL_PAUSE_TIMEOUT: 600
+  TEST_REPORT_RETENTION_DAYS: 5
 
 # Cancel previous PR builds.
 concurrency:
@@ -49,6 +50,9 @@ jobs:
           distribution: 'zulu'
           java-version: ${{ matrix.java-version }}
           cache: 'maven'
+      - name: Configure Problem Matchers
+        run: |
+          echo "::add-matcher::.github/problem-matcher.json"
       - name: Maven Checks
         run: |
           export MAVEN_OPTS="${MAVEN_INSTALL_OPTS}"
@@ -75,6 +79,9 @@ jobs:
           distribution: 'zulu'
           java-version: 11
           cache: 'maven'
+      - name: Configure Problem Matchers
+        run: |
+          echo "::add-matcher::.github/problem-matcher.json"
       - name: Maven Install
         run: |
           export MAVEN_OPTS="${MAVEN_INSTALL_OPTS}"
@@ -108,6 +115,9 @@ jobs:
           distribution: 'zulu'
           java-version: 11
           cache: 'maven'
+      - name: Configure Problem Matchers
+        run: |
+          echo "::add-matcher::.github/problem-matcher.json"
       - name: Maven Install
         run: |
           export MAVEN_OPTS="${MAVEN_INSTALL_OPTS}"
@@ -117,6 +127,26 @@ jobs:
       - name: Test current JDBC vs old server
         if: always()
         run: $MAVEN test ${MAVEN_TEST} -pl :trino-test-jdbc-compatibility-old-server
+      - name: Upload test results
+        uses: actions/upload-artifact@v2
+        # Upload all test reports only on failure, because the artifacts are large
+        if: failure()
+        with:
+          name: result ${{ github.job }}
+          path: |
+            **/target/surefire-reports
+            **/target/checkstyle-*
+      - name: Upload test report
+        uses: actions/upload-artifact@v2
+        # Always upload the test report for the annotate.yml workflow,
+        # but only the single XML file to keep the artifact small
+        if: always()
+        with:
+          # Name prefix is checked in the `Annotate checks` workflow
+          name: test report ${{ github.job }}
+          path: |
+            **/surefire-reports/TEST-*.xml
+          retention-days: ${{ env.TEST_REPORT_RETENTION_DAYS }}
 
   hive-tests:
     runs-on: ubuntu-latest
@@ -136,6 +166,9 @@ jobs:
           distribution: 'zulu'
           java-version: 11
           cache: 'maven'
+      - name: Configure Problem Matchers
+        run: |
+          echo "::add-matcher::.github/problem-matcher.json"
       - name: Install Hive Module
         run: |
           export MAVEN_OPTS="${MAVEN_INSTALL_OPTS}"
@@ -217,12 +250,24 @@ jobs:
             plugin/trino-hive-hadoop2/bin/run_hive_alluxio_tests.sh
       - name: Upload test results
         uses: actions/upload-artifact@v2
+        # Upload all test reports only on failure, because the artifacts are large
         if: failure()
         with:
-          name: result hive-tests
+          name: result ${{ github.job }}
           path: |
             **/target/surefire-reports
             **/target/checkstyle-*
+      - name: Upload test report
+        uses: actions/upload-artifact@v2
+        # Always upload the test report for the annotate.yml workflow,
+        # but only the single XML file to keep the artifact small
+        if: always()
+        with:
+          # Name prefix is checked in the `Annotate checks` workflow
+          name: test report ${{ github.job }} (${{ matrix.config }})
+          path: |
+            **/surefire-reports/TEST-*.xml
+          retention-days: ${{ env.TEST_REPORT_RETENTION_DAYS }}
 
   test-other-modules:
     runs-on: ubuntu-latest
@@ -234,6 +279,9 @@ jobs:
           distribution: 'zulu'
           java-version: 11
           cache: 'maven'
+      - name: Configure Problem Matchers
+        run: |
+          echo "::add-matcher::.github/problem-matcher.json"
       - name: Maven Install
         run: |
           export MAVEN_OPTS="${MAVEN_INSTALL_OPTS}"
@@ -260,12 +308,24 @@ jobs:
             !:trino-bigquery'
       - name: Upload test results
         uses: actions/upload-artifact@v2
+        # Upload all test reports only on failure, because the artifacts are large
         if: failure()
         with:
-          name: result test-other-modules
+          name: result ${{ github.job }}
           path: |
             **/target/surefire-reports
             **/target/checkstyle-*
+      - name: Upload test report
+        uses: actions/upload-artifact@v2
+        # Always upload the test report for the annotate.yml workflow,
+        # but only the single XML file to keep the artifact small
+        if: always()
+        with:
+          # Name prefix is checked in the `Annotate checks` workflow
+          name: test report ${{ github.job }}
+          path: |
+            **/surefire-reports/TEST-*.xml
+          retention-days: ${{ env.TEST_REPORT_RETENTION_DAYS }}
 
   test:
     runs-on: ubuntu-latest
@@ -298,6 +358,9 @@ jobs:
           distribution: 'zulu'
           java-version: 11
           cache: 'maven'
+      - name: Configure Problem Matchers
+        run: |
+          echo "::add-matcher::.github/problem-matcher.json"
       - name: Maven Install
         run: |
           export MAVEN_OPTS="${MAVEN_INSTALL_OPTS}"
@@ -314,12 +377,24 @@ jobs:
           echo "ARTIFACT_NAME=$name" >> $GITHUB_ENV
       - name: Upload test results
         uses: actions/upload-artifact@v2
+        # Upload all test reports only on failure, because the artifacts are large
         if: failure()
         with:
           name: result ${{ env.ARTIFACT_NAME }}
           path: |
             **/target/surefire-reports
             **/target/checkstyle-*
+      - name: Upload test report
+        uses: actions/upload-artifact@v2
+        # Always upload the test report for the annotate.yml workflow,
+        # but only the single XML file to keep the artifact small
+        if: always()
+        with:
+          # Name prefix is checked in the `Annotate checks` workflow
+          name: test report ${{ github.job }} (${{ env.ARTIFACT_NAME }})
+          path: |
+            **/surefire-reports/TEST-*.xml
+          retention-days: ${{ env.TEST_REPORT_RETENTION_DAYS }}
 
   test-memsql:
     runs-on: ubuntu-latest
@@ -331,6 +406,9 @@ jobs:
           distribution: 'zulu'
           java-version: 11
           cache: 'maven'
+      - name: Configure Problem Matchers
+        run: |
+          echo "::add-matcher::.github/problem-matcher.json"
       - name: Cleanup node
         # This is required as a virtual environment update 20210219.1 left too little space for MemSQL to work
         run: .github/bin/cleanup-node.sh
@@ -347,12 +425,24 @@ jobs:
           fi
       - name: Upload test results
         uses: actions/upload-artifact@v2
+        # Upload all test reports only on failure, because the artifacts are large
         if: failure()
         with:
-          name: result test-memsql
+          name: result ${{ github.job }}
           path: |
             **/target/surefire-reports
             **/target/checkstyle-*
+      - name: Upload test report
+        uses: actions/upload-artifact@v2
+        # Always upload the test report for the annotate.yml workflow,
+        # but only the single XML file to keep the artifact small
+        if: always()
+        with:
+          # Name prefix is checked in the `Annotate checks` workflow
+          name: test report ${{ github.job }}
+          path: |
+            **/surefire-reports/TEST-*.xml
+          retention-days: ${{ env.TEST_REPORT_RETENTION_DAYS }}
 
   test-bigquery:
     runs-on: ubuntu-latest
@@ -364,6 +454,9 @@ jobs:
           distribution: 'zulu'
           java-version: 11
           cache: 'maven'
+      - name: Configure Problem Matchers
+        run: |
+          echo "::add-matcher::.github/problem-matcher.json"
       - name: Maven Install
         run: |
           export MAVEN_OPTS="${MAVEN_INSTALL_OPTS}"
@@ -386,15 +479,29 @@ jobs:
           fi
       - name: Upload test results
         uses: actions/upload-artifact@v2
+        # Upload all test reports only on failure, because the artifacts are large
         if: failure()
         with:
-          name: result test-bigquery
+          name: result ${{ github.job }}
           path: |
             **/target/surefire-reports
             **/target/checkstyle-*
+      - name: Upload test report
+        uses: actions/upload-artifact@v2
+        # Always upload the test report for the annotate.yml workflow,
+        # but only the single XML file to keep the artifact small
+        if: always()
+        with:
+          # Name prefix is checked in the `Annotate checks` workflow
+          name: test report ${{ github.job }}
+          path: |
+            **/surefire-reports/TEST-*.xml
+          retention-days: ${{ env.TEST_REPORT_RETENTION_DAYS }}
 
   pt:
     runs-on: ubuntu-latest
+    # explicitly define the name to avoid adding the value of the `ignore exclusion if` matrix item
+    name: pt (${{ matrix.config }}, ${{ matrix.suite }}, ${{ matrix.jdk }})
     strategy:
       fail-fast: false
       matrix:
@@ -501,11 +608,22 @@ jobs:
           testing/bin/ptl suite run \
             --suite ${{ matrix.suite }} --config config-${{ matrix.config }} --bind=off --logs-dir logs/ --timeout 2h \
             --trino-jdk-version zulu_${{ matrix.jdk }}
-      - name: Upload test results
+      - name: Upload test logs and results
         uses: actions/upload-artifact@v2
+        # Upload all test reports only on failure, because the artifacts are large
         if: failure()
         with:
-          name: result pt (${{ matrix.config }}, ${{ matrix.suite }})
+          name: result pt (${{ matrix.config }}, ${{ matrix.suite }}, ${{ matrix.jdk }})
           path: |
             testing/trino-product-tests/target/*
             logs/*
+      - name: Upload test report
+        uses: actions/upload-artifact@v2
+        # Always upload the test report for the annotate.yml workflow,
+        # but only the single XML file to keep the artifact small
+        if: always()
+        with:
+          # Name prefix is checked in the `Annotate checks` workflow
+          name: test report pt (${{ matrix.config }}, ${{ matrix.suite }}, ${{ matrix.jdk }})
+          path: testing/trino-product-tests/target/reports/testng-results.xml
+          retention-days: ${{ env.TEST_REPORT_RETENTION_DAYS }}
diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml
index bd05277937a3..67cf601257d7 100644
--- a/.github/workflows/docs.yml
+++ b/.github/workflows/docs.yml
@@ -50,6 +50,9 @@ jobs:
           distribution: 'zulu'
           java-version: 11
           cache: 'maven'
+      - name: Configure Problem Matchers
+        run: |
+          echo "::add-matcher::.github/problem-matcher.json"
       - name: Maven Checks
         run: |
           $RETRY $MAVEN install -B --strict-checksums -V -T C1 -DskipTests -P ci -am -pl ':trino-docs'
@@ -74,9 +77,40 @@ jobs:
           distribution: 'zulu'
           java-version: 11
           cache: 'maven'
+      - name: Configure Problem Matchers
+        run: |
+          echo "::add-matcher::.github/problem-matcher.json"
       - name: Maven Install
         run: |
           export MAVEN_OPTS="${MAVEN_INSTALL_OPTS}"
           $RETRY $MAVEN install ${MAVEN_FAST_INSTALL} -am -pl $(echo '${{ matrix.modules }}' | cut -d' ' -f1)
       - name: Maven Tests
         run: $MAVEN test ${MAVEN_TEST} -pl ${{ matrix.modules }}
+      - name: Sanitize artifact name
+        if: always()
+        run: |
+          # Generate a valid artifact name and make it available to next steps as
+          # an environment variable ARTIFACT_NAME
+          # ", :, <, >, |, *, ?, \, / are not allowed in artifact names but we only use : so we remove it
+          name=$(echo -n "${{ matrix.modules }}" | sed -e 's/[:]//g')
+          echo "ARTIFACT_NAME=$name" >> $GITHUB_ENV
+      - name: Upload test results
+        uses: actions/upload-artifact@v2
+        # Upload all test reports only on failure, because the artifacts are large
+        if: failure()
+        with:
+          name: result ${{ env.ARTIFACT_NAME }}
+          path: |
+            **/target/surefire-reports
+            **/target/checkstyle-*
+      - name: Upload test report
+        uses: actions/upload-artifact@v2
+        # Always upload the test report for the annotate.yml workflow,
+        # but only the single XML file to keep the artifact small
+        if: always()
+        with:
+          # Name prefix is checked in the `Annotate checks` workflow
+          name: test report ${{ github.job }} (${{ env.ARTIFACT_NAME }})
+          path: |
+            **/surefire-reports/TEST-*.xml
+          retention-days: ${{ env.TEST_REPORT_RETENTION_DAYS }}