| name: Tests |
| |
| # This file implements the protection strategy laid out in |
| # go/protobuf-gha-protected-resources. Pull requests from branches within this |
| # repository are considered safe and will immediately start running tests on |
| # every commit. Pull requests from forked repositories are unsafe, and leave |
| # us vulnerable to PWN requests and stolen resources. In these cases, we |
| # require a special "safe for tests" tag to be added to the pull request before |
| # we start testing. This will be immediately removed, so that further commits |
| # require their own stamp to test. |
| |
| on: |
| # continuous |
| schedule: |
| # Run every hour |
| - cron: "0 * * * *" |
| |
| # postsubmit |
| push: |
| branches: |
| - main |
| - '[0-9]+.x' |
| # For testing purposes so we can stage this on the `gha` branch. |
| - gha |
| |
| # safe presubmit |
| pull_request: |
| branches: |
| - main |
| - '[0-9]+.x' |
| # For testing purposes so we can stage this on the `gha` branch. |
| - gha |
| |
| # unsafe presubmit |
| pull_request_target: |
| branches: |
| - main |
| - '[0-9]+.x' |
| # For testing purposes so we can stage this on the `gha` branch. |
| - gha |
| types: [labeled, opened, reopened, synchronize] |
| |
| # manual |
| workflow_dispatch: |
| |
| permissions: |
| contents: read |
| |
| concurrency: |
| group: ${{ github.event_name }}-${{ github.workflow }}-${{ github.head_ref || github.ref }} |
| cancel-in-progress: ${{ contains(fromJSON('["pull_request", "pull_request_target", "workflow_dispatch", "schedule"]'), github.event_name) }} |
| |
| jobs: |
| set-vars: |
| name: Set Variables |
| |
| # Avoid running tests twice on PR updates. If the PR is coming from our |
| # repository, it's safe and we can use `pull_request`. Otherwise, we should |
| # use `pull_request_target`. |
| if: | |
| (github.event_name != 'pull_request' && |
| github.event_name != 'pull_request_target' && |
| github.event.repository.full_name == 'protocolbuffers/protobuf') || |
| (github.event_name == 'pull_request' && |
| github.event.pull_request.head.repo.full_name == 'protocolbuffers/protobuf') || |
| (github.event_name == 'pull_request_target' && |
| github.event.pull_request.head.repo.full_name != 'protocolbuffers/protobuf') |
| |
| runs-on: ubuntu-latest |
| outputs: |
| # Store the sha for checkout so we can easily use it later. For safe |
| # events, this will be blank and use the defaults. |
| checkout-sha: ${{ steps.safe-checkout.outputs.sha }} |
| # Stores a string to be used as a boolean denoting whether this is a |
| # continuous run. An empty string denotes that the run is on presubmit, |
| # otherwise we are in a continuous run. This helps us determine which |
| # tests to block on. |
| continuous-run: ${{ steps.set-test-type-vars.outputs.continuous-run }} |
| # Stores a string that will serve as the prefix for all continuous tests. |
| # Either way we prepend "(Continuous)" but in the case that we are in |
| # a presubmit run, we should also mark them "[SKIPPED]" |
| continuous-prefix: ${{ steps.set-test-type-vars.outputs.continuous-prefix }} |
| steps: |
| - name: Check |
| # Trivially pass for safe PRs, and explicitly error for unsafe ones |
| # unless this is specifically an event for adding the safe label. |
| run: > |
| ${{ github.event_name != 'pull_request_target' || github.event.label.name == ':a: safe for tests' }} || |
| (echo "This pull request is from an unsafe fork and hasn't been approved to run tests." && |
| echo "A protobuf team member will need to review the PR and add the 'safe for tests' tag." && |
| exit 1) |
| |
| - name: Cache safe commit |
| id: safe-checkout |
| run: > |
| ${{ github.event_name != 'pull_request_target' }} || |
| echo "sha=${{ github.event.pull_request.head.sha }}" >> $GITHUB_OUTPUT |
| |
| - name: Set Test Type Variables |
| id: set-test-type-vars |
| run: | |
| if ([ "${{ github.event_name }}" == 'pull_request' ] || [ "${{ github.event_name }}" == 'pull_request_target' ]) && ${{ !contains(toJson(github.event.pull_request.body), '\n#test-continuous') }}; then |
| echo "continuous-run=" >> "$GITHUB_OUTPUT" |
| echo "continuous-prefix=[SKIPPED] (Continuous)" >> "$GITHUB_OUTPUT" |
| else |
| echo "continuous-run=continuous" >> "$GITHUB_OUTPUT" |
| echo "continuous-prefix=(Continuous)" >> "$GITHUB_OUTPUT" |
| fi |
| |
| remove-tag: |
| name: Remove safety tag |
| needs: [set-vars] |
| if: github.event.action == 'labeled' |
| runs-on: ubuntu-latest |
| permissions: |
| pull-requests: write |
| steps: |
| - uses: actions-ecosystem/action-remove-labels@2ce5d41b4b6aa8503e285553f75ed56e0a40bae0 # v1.3.0 |
| with: |
| fail_on_error: true |
| labels: ':a: safe for tests' |
| |
| validate-yaml: |
| name: Validate YAML |
| needs: [set-vars] |
| uses: ./.github/workflows/test_yaml.yml |
| with: |
| safe-checkout: ${{ needs.set-vars.outputs.checkout-sha }} |
| |
| # Note: this pattern of passing the head sha is vulnerable to PWN requests for |
| # pull_request_target events. We carefully limit those workflows to require a |
| # human stamp before continuing. |
| bazel: |
| name: Bazel |
| needs: [set-vars] |
| uses: ./.github/workflows/test_bazel.yml |
| with: |
| continuous-run: ${{ needs.set-vars.outputs.continuous-run }} |
| safe-checkout: ${{ needs.set-vars.outputs.checkout-sha }} |
| continuous-prefix: ${{ needs.set-vars.outputs.continuous-prefix }} |
| secrets: inherit |
| |
| cpp: |
| name: C++ |
| needs: [set-vars] |
| uses: ./.github/workflows/test_cpp.yml |
| with: |
| continuous-run: ${{ needs.set-vars.outputs.continuous-run }} |
| safe-checkout: ${{ needs.set-vars.outputs.checkout-sha }} |
| continuous-prefix: ${{ needs.set-vars.outputs.continuous-prefix }} |
| secrets: inherit |
| |
| java: |
| name: Java |
| needs: [set-vars] |
| uses: ./.github/workflows/test_java.yml |
| with: |
| continuous-run: ${{ needs.set-vars.outputs.continuous-run }} |
| safe-checkout: ${{ needs.set-vars.outputs.checkout-sha }} |
| continuous-prefix: ${{ needs.set-vars.outputs.continuous-prefix }} |
| secrets: inherit |
| |
| python: |
| name: Python |
| needs: [set-vars] |
| uses: ./.github/workflows/test_python.yml |
| with: |
| continuous-run: ${{ needs.set-vars.outputs.continuous-run }} |
| safe-checkout: ${{ needs.set-vars.outputs.checkout-sha }} |
| continuous-prefix: ${{ needs.set-vars.outputs.continuous-prefix }} |
| secrets: inherit |
| |
| ruby: |
| name: Ruby |
| needs: [set-vars] |
| uses: ./.github/workflows/test_ruby.yml |
| with: |
| continuous-run: ${{ needs.set-vars.outputs.continuous-run }} |
| safe-checkout: ${{ needs.set-vars.outputs.checkout-sha }} |
| continuous-prefix: ${{ needs.set-vars.outputs.continuous-prefix }} |
| secrets: inherit |
| |
| php: |
| name: PHP |
| needs: [set-vars] |
| uses: ./.github/workflows/test_php.yml |
| with: |
| continuous-run: ${{ needs.set-vars.outputs.continuous-run }} |
| safe-checkout: ${{ needs.set-vars.outputs.checkout-sha }} |
| continuous-prefix: ${{ needs.set-vars.outputs.continuous-prefix }} |
| secrets: inherit |
| |
| php-ext: |
| name: PHP Extension |
| needs: [set-vars] |
| uses: ./.github/workflows/test_php_ext.yml |
| with: |
| continuous-run: ${{ needs.set-vars.outputs.continuous-run }} |
| safe-checkout: ${{ needs.set-vars.outputs.checkout-sha }} |
| continuous-prefix: ${{ needs.set-vars.outputs.continuous-prefix }} |
| secrets: inherit |
| |
| csharp: |
| name: C# |
| needs: [set-vars] |
| uses: ./.github/workflows/test_csharp.yml |
| with: |
| safe-checkout: ${{ needs.set-vars.outputs.checkout-sha }} |
| secrets: inherit |
| |
| objectivec: |
| name: Objective-C |
| needs: [set-vars] |
| uses: ./.github/workflows/test_objectivec.yml |
| with: |
| continuous-run: ${{ needs.set-vars.outputs.continuous-run }} |
| safe-checkout: ${{ needs.set-vars.outputs.checkout-sha }} |
| continuous-prefix: ${{ needs.set-vars.outputs.continuous-prefix }} |
| secrets: inherit |
| |
| rust: |
| name: Rust |
| needs: [set-vars] |
| uses: ./.github/workflows/test_rust.yml |
| with: |
| safe-checkout: ${{ needs.set-vars.outputs.checkout-sha }} |
| secrets: inherit |
| |
| upb: |
| name: μpb |
| needs: [set-vars] |
| uses: ./.github/workflows/test_upb.yml |
| with: |
| continuous-run: ${{ needs.set-vars.outputs.continuous-run }} |
| safe-checkout: ${{ needs.set-vars.outputs.checkout-sha }} |
| continuous-prefix: ${{ needs.set-vars.outputs.continuous-prefix }} |
| secrets: inherit |
| |
| staleness: |
| name: Staleness |
| needs: [set-vars] |
| uses: ./.github/workflows/staleness_check.yml |
| # Staleness tests have scheduled runs during off-hours to avoid race conditions. |
| if: ${{ github.event_name != 'schedule' }} |
| with: |
| continuous-run: ${{ needs.set-vars.outputs.continuous-run }} |
| safe-checkout: ${{ needs.set-vars.outputs.checkout-sha }} |
| secrets: inherit |
| |
| # This test depends on all blocking tests and indicates whether they all suceeded. |
| all-blocking-tests: |
| name: All Blocking Tests${{ github.event_name == 'pull_request_target' && ' (fork)' || ''}} |
| needs: [set-vars, validate-yaml, bazel, cpp, java, python, ruby, php, php-ext, csharp, objectivec, rust, upb, staleness] |
| runs-on: ubuntu-latest |
| steps: |
| - name: Check test results |
| run: "${{ !contains(join(needs.*.result, ' '), 'failure') && !contains(join(needs.*.result, ' '), 'cancelled') }}" |
| # This workflow must run even if one or more of the dependent workflows |
| # failed. |
| if: always() |