Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Trigger AWS Lambda tests on label #2538

Merged
merged 14 commits into from
Nov 30, 2023
72 changes: 72 additions & 0 deletions .github/workflows/scripts/trigger_tests_on_label.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
#!/usr/bin/env python3
import argparse
import json
import os
from urllib.parse import quote
from urllib.request import Request, urlopen

LABEL = "Trigger: tests"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would maybe make this more explicit that it's sensitive tests requiring secrets

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Changed to "Trigger: tests using secrets" (open to better names)



def _has_write(repo_id: int, username: str, *, token: str) -> bool:
req = Request(
f"https://api.github.com/repositories/{repo_id}/collaborators/{username}/permission",
headers={"Authorization": f"token {token}"},
)
contents = json.load(urlopen(req, timeout=10))

return contents["permission"] in {"admin", "write"}


def _remove_label(repo_id: int, pr: int, label: str, *, token: str) -> None:
quoted_label = quote(label)
req = Request(
f"https://api.github.com/repositories/{repo_id}/issues/{pr}/labels/{quoted_label}",
method="DELETE",
headers={"Authorization": f"token {token}"},
)
urlopen(req)


def main() -> int:
parser = argparse.ArgumentParser()
parser.add_argument("--repo-id", type=int, required=True)
parser.add_argument("--pr", type=int, required=True)
parser.add_argument("--event", required=True)
parser.add_argument("--username", required=True)
parser.add_argument("--label-names", type=json.loads, required=True)
args = parser.parse_args()

token = os.environ["GITHUB_TOKEN"]

write_permission = _has_write(args.repo_id, args.username, token=token)

if (
not write_permission
# `reopened` is included here due to close => push => reopen
and args.event in {"synchronize", "reopened"}
and LABEL in args.label_names
):
print(f"Invalidating label [{LABEL}] due to code change...")
_remove_label(args.repo_id, args.pr, LABEL, token=token)
args.label_names.remove(LABEL)

if write_permission or LABEL in args.label_names:
print("Permissions passed!")
print(f"- has write permission: {write_permission}")
print(f"- has [{LABEL}] label: {LABEL in args.label_names}")
return 0
else:
print("Permissions failed!")
print(f"- has write permission: {write_permission}")
print(f"- has [{LABEL}] label: {LABEL in args.label_names}")
print(f"- args.label_names: {args.label_names}")
print(
f"Please have a collaborator add the [{LABEL}] label once they "
f"have reviewed the code to trigger tests."
)
return 1


if __name__ == "__main__":
raise SystemExit(main())
31 changes: 30 additions & 1 deletion .github/workflows/test-integration-aws_lambda.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,22 +4,49 @@ on:
branches:
- master
- release/**
pull_request:
# XXX: We are using `pull_request_target` instead of `pull_request` because we want
# this to run on forks with access to the secrets necessary to run the test suite.
# Prefer to use `pull_request` when possible.
pull_request_target:
types: [labeled, opened, reopened, synchronize]
# Cancel in progress workflows on pull_requests.
# https://docs.github.com/en/actions/using-jobs/using-concurrency#example-using-a-fallback-value
concurrency:
group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }}
cancel-in-progress: true
permissions:
contents: read
# `write` is needed to remove the `Trigger: tests` label
pull-requests: write
env:
SENTRY_PYTHON_TEST_AWS_ACCESS_KEY_ID: ${{ secrets.SENTRY_PYTHON_TEST_AWS_ACCESS_KEY_ID }}
SENTRY_PYTHON_TEST_AWS_SECRET_ACCESS_KEY: ${{ secrets.SENTRY_PYTHON_TEST_AWS_SECRET_ACCESS_KEY }}
BUILD_CACHE_KEY: ${{ github.sha }}
CACHED_BUILD_PATHS: |
${{ github.workspace }}/dist-serverless
jobs:
check-permissions:
name: permissions check
runs-on: ubuntu-20.04
steps:
- uses: actions/checkout@93ea575cb5d8a053eaa0ac8fa3b40d7e05a33cc8 # v3.1.0
with:
persist-credentials: false
- name: permissions
run: |
python3 -uS .github/workflows/scripts/trigger_tests_on_label.py \
--repo-id ${{ github.event.repository.id }} \
--pr ${{ github.event.number }} \
--event ${{ github.event.action }} \
--username "$ARG_USERNAME" \
--label-names "$ARG_LABEL_NAMES"
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
# these can contain special characters
ARG_USERNAME: ${{ github.event.pull_request.user.login }}
ARG_LABEL_NAMES: ${{ toJSON(github.event.pull_request.labels.*.name) }}
test-pinned:
needs: check-permissions
timeout-minutes: 30
name: aws_lambda pinned, python ${{ matrix.python-version }}, ${{ matrix.os }}
runs-on: ${{ matrix.os }}
Expand All @@ -34,6 +61,8 @@ jobs:
os: [ubuntu-20.04]
steps:
- uses: actions/checkout@v4
with:
ref: ${{ github.event.pull_request.head.sha || github.ref }}
- uses: actions/setup-python@v4
with:
python-version: ${{ matrix.python-version }}
Expand Down
5 changes: 5 additions & 0 deletions scripts/split-tox-gh-actions/split-tox-gh-actions.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,10 @@
"aws_lambda",
]

FRAMEWORKS_NEEDING_GITHUB_SECRETS = [
"aws_lambda",
]

ENV = Environment(
loader=FileSystemLoader(TEMPLATE_DIR),
)
Expand Down Expand Up @@ -152,6 +156,7 @@ def render_template(framework, py_versions_pinned, py_versions_latest):
"needs_aws_credentials": framework in FRAMEWORKS_NEEDING_AWS,
"needs_clickhouse": framework in FRAMEWORKS_NEEDING_CLICKHOUSE,
"needs_postgres": framework in FRAMEWORKS_NEEDING_POSTGRES,
"needs_github_secrets": framework in FRAMEWORKS_NEEDING_GITHUB_SECRETS,
"py_versions": {
# formatted for including in the matrix
"pinned": [f'"{v}"' for v in py_versions_pinned if v != "2.7"],
Expand Down
16 changes: 16 additions & 0 deletions scripts/split-tox-gh-actions/templates/base.jinja
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,15 @@ on:
- master
- release/**

{% if needs_github_secrets %}
# XXX: We are using `pull_request_target` instead of `pull_request` because we want
# this to run on forks with access to the secrets necessary to run the test suite.
# Prefer to use `pull_request` when possible.
pull_request_target:
types: [labeled, opened, reopened, synchronize]
{% else %}
pull_request:
{% endif %}

# Cancel in progress workflows on pull_requests.
# https://docs.github.com/en/actions/using-jobs/using-concurrency#example-using-a-fallback-value
Expand All @@ -16,6 +24,10 @@ concurrency:

permissions:
contents: read
{% if needs_github_secrets %}
# `write` is needed to remove the `Trigger: tests` label
sentrivana marked this conversation as resolved.
Show resolved Hide resolved
pull-requests: write
{% endif %}

env:
{% if needs_aws_credentials %}
Expand All @@ -29,6 +41,10 @@ env:
{% raw %}${{ github.workspace }}/dist-serverless{% endraw %}

jobs:
{% if needs_github_secrets %}
{% include "check_permissions.jinja" %}
{% endif %}

{% if py_versions.pinned %}
{% with category="pinned", versions=py_versions.pinned %}
{% include "test.jinja" %}
Expand Down
25 changes: 25 additions & 0 deletions scripts/split-tox-gh-actions/templates/check_permissions.jinja
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
check-permissions:
name: permissions check
runs-on: ubuntu-20.04
steps:
- uses: actions/checkout@93ea575cb5d8a053eaa0ac8fa3b40d7e05a33cc8 # v3.1.0
with:
persist-credentials: false

- name: permissions
run: |
{% raw %}
python3 -uS .github/workflows/scripts/trigger_tests_on_label.py \
--repo-id ${{ github.event.repository.id }} \
--pr ${{ github.event.number }} \
--event ${{ github.event.action }} \
--username "$ARG_USERNAME" \
--label-names "$ARG_LABEL_NAMES"
{% endraw %}
env:
{% raw %}
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
# these can contain special characters
ARG_USERNAME: ${{ github.event.pull_request.user.login }}
ARG_LABEL_NAMES: ${{ toJSON(github.event.pull_request.labels.*.name) }}
{% endraw %}
9 changes: 9 additions & 0 deletions scripts/split-tox-gh-actions/templates/test.jinja
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
test-{{ category }}:
{% if needs_github_secrets %}
needs: check-permissions
{% endif %}
timeout-minutes: 30
{% if category == "py27" %}
name: {{ framework }} {{ category }}, python 2.7
Expand Down Expand Up @@ -41,6 +44,12 @@

steps:
- uses: actions/checkout@v4
{% if needs_github_secrets %}
{% raw %}
with:
ref: ${{ github.event.pull_request.head.sha || github.ref }}
{% endraw %}
{% endif %}
{% if category != "py27" %}
- uses: actions/setup-python@v4
with:
Expand Down