blob: 1f7c26fbc8bff8129c904647d705d2ae99d71d9c [file] [log] [blame]
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()