Skip to content

Commit

Permalink
Merge branch 'main' into renovate/click-8.x
Browse files Browse the repository at this point in the history
  • Loading branch information
arturo-seijas authored Jan 23, 2025
2 parents fa1aa1e + 745e644 commit b436804
Show file tree
Hide file tree
Showing 15 changed files with 125 additions and 48 deletions.
6 changes: 4 additions & 2 deletions .github/workflows/integration_test.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,10 @@ jobs:
with:
juju-channel: 3.5/stable
channel: 1.28-strict/stable
self-hosted-runner: true
self-hosted-runner-label: "edge"
runs-on: ubuntu-24.04
self-hosted-runner: false # we need a noble runner for python 3.12 but there is currently no edge runner with noble base available, so we choose gh hosted ones
self-hosted-runner-image: 'noble'
self-hosted-runner-label: "large"
rockcraft-channel: latest/edge
charmcraft-channel: latest/edge
test-tox-env: charm-integration-test
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/tests.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ on:

jobs:
tests:
runs-on: ubuntu-latest
runs-on: ubuntu-24.04
steps:
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4
- name: Install tox
Expand Down
2 changes: 2 additions & 0 deletions .trivyignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,5 @@
CVE-2024-34156

Check notice on line 2 in .trivyignore

View workflow job for this annotation

GitHub Actions / charm-integration-test / Scan Image (ghcr.io-canonical-repo-policy-compliance-52b748385913d1e81a90a2b1073c8379a7405507-_1.11.0_amd64.tar)

CVE-2024-34156 not present anymore, can be safely removed.
# Vulnerability in golang.org/x/crypto introduced by statsd-exporter. We have to wait until it is fixed upstream: https://github.com/prometheus/statsd_exporter/blob/master/go.mod
CVE-2024-45337

Check notice on line 4 in .trivyignore

View workflow job for this annotation

GitHub Actions / charm-integration-test / Scan Image (ghcr.io-canonical-repo-policy-compliance-52b748385913d1e81a90a2b1073c8379a7405507-_1.11.0_amd64.tar)

CVE-2024-45337 not present anymore, can be safely removed.
# Vulnerability in golang.org/x/net introduced by statsd-exporter. We have to wait until it is fixed upstream: https://github.com/prometheus/statsd_exporter/blob/master/go.mod
CVE-2024-45338
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

[tool.poetry]
name = "repo-policy-compliance"
version = "1.10.5"
version = "1.11.0"
description = "Checks GitHub repository settings for compliance with policy"
authors = ["Canonical IS DevOps <launchpad.net/~canonical-is-devops>"]
license = "Apache 2.0"
Expand Down
22 changes: 13 additions & 9 deletions repo_policy_compliance/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,12 @@ class UsedPolicy(Enum):
"""Sentinel to indicate which policy to use.
Attributes:
ALL: Use all policies.
PULL_REQUEST_ALLOW_FORK: Use policy that lets forked repositories run jobs (default).
PULL_REQUEST_DISALLOW_FORK: Use policy that only blocks disallowed forks.
"""

ALL = 1
PULL_REQUEST_ALLOW_FORK = 2
PULL_REQUEST_ALLOW_FORK = 1
PULL_REQUEST_DISALLOW_FORK = 2


class PullRequestInput(BaseModel):
Expand Down Expand Up @@ -151,7 +151,8 @@ class BranchInput(BaseModel):

@log.call
def workflow_dispatch(
input_: WorkflowDispatchInput, policy_document: dict | UsedPolicy = UsedPolicy.ALL
input_: WorkflowDispatchInput,
policy_document: dict | UsedPolicy = UsedPolicy.PULL_REQUEST_DISALLOW_FORK,
) -> check.Report:
"""Run all the checks for workflow dispatch jobs.
Expand Down Expand Up @@ -189,7 +190,9 @@ def workflow_dispatch(


@log.call
def push(input_: PushInput, policy_document: dict | UsedPolicy = UsedPolicy.ALL) -> check.Report:
def push(
input_: PushInput, policy_document: dict | UsedPolicy = UsedPolicy.PULL_REQUEST_DISALLOW_FORK
) -> check.Report:
"""Run all the checks for on push jobs.
Args:
Expand Down Expand Up @@ -227,7 +230,8 @@ def push(input_: PushInput, policy_document: dict | UsedPolicy = UsedPolicy.ALL)

@log.call
def schedule(
input_: ScheduleInput, policy_document: dict | UsedPolicy = UsedPolicy.ALL
input_: ScheduleInput,
policy_document: dict | UsedPolicy = UsedPolicy.PULL_REQUEST_DISALLOW_FORK,
) -> check.Report:
"""Run all the checks for on schedule jobs.
Expand Down Expand Up @@ -275,10 +279,10 @@ def _retrieve_policy_document(
Returns:
Mapped policy document.
"""
if policy_document == UsedPolicy.ALL:
return policy.ALL
if policy_document == UsedPolicy.PULL_REQUEST_ALLOW_FORK:
return policy.ALLOW_FORK
return policy.ENABLE_EXCEPT_FORK
if policy_document == UsedPolicy.PULL_REQUEST_DISALLOW_FORK:
return policy.DISABLE_EXCEPT_FORK
# Guaranteed to be a dict due to initial if statements
policy_document = cast(dict, policy_document)
if not (policy_report := policy.check(document=policy_document)).result:
Expand Down
2 changes: 1 addition & 1 deletion repo_policy_compliance/blueprint.py
Original file line number Diff line number Diff line change
Expand Up @@ -177,7 +177,7 @@ def _get_policy_document() -> dict | UsedPolicy:
).lower() == "true"
if not pull_request_disallow_fork:
return UsedPolicy.PULL_REQUEST_ALLOW_FORK
return UsedPolicy.ALL
return UsedPolicy.PULL_REQUEST_DISALLOW_FORK


# Keeping /check-run pointing to this for backwards compatibility
Expand Down
15 changes: 10 additions & 5 deletions repo_policy_compliance/policy.py
Original file line number Diff line number Diff line change
Expand Up @@ -68,19 +68,24 @@ class BranchJobProperty(str, Enum):
JobType.PUSH: {prop: ENABLED_RULE for prop in PushProperty},
JobType.SCHEDULE: {prop: ENABLED_RULE for prop in ScheduleProperty},
}
ALL = MappingProxyType(
ENABLE_EXCEPT_FORK = MappingProxyType(
{
JobType.PULL_REQUEST: {prop: ENABLED_RULE for prop in PullRequestProperty},
JobType.PULL_REQUEST: {
prop: (ENABLED_RULE if prop != PullRequestProperty.DISALLOW_FORK else DISABLED_RULE)
for prop in PullRequestProperty
},
**_BASE_POLICY_MAP,
}
)
ALLOW_FORK = MappingProxyType(
DISABLE_EXCEPT_FORK = MappingProxyType(
{
JobType.PULL_REQUEST: {
prop: (ENABLED_RULE if prop != PullRequestProperty.DISALLOW_FORK else DISABLED_RULE)
prop: (ENABLED_RULE if prop == PullRequestProperty.DISALLOW_FORK else DISABLED_RULE)
for prop in PullRequestProperty
},
**_BASE_POLICY_MAP,
JobType.WORKFLOW_DISPATCH: {prop: DISABLED_RULE for prop in WorkflowDispatchProperty},
JobType.PUSH: {prop: DISABLED_RULE for prop in PushProperty},
JobType.SCHEDULE: {prop: DISABLED_RULE for prop in ScheduleProperty},
}
)

Expand Down
20 changes: 10 additions & 10 deletions requirements.txt
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
alembic==1.14.0 ; python_full_version >= "3.10.0" and python_full_version < "4.0.0"
alembic==1.14.1 ; python_full_version >= "3.10.0" and python_full_version < "4.0.0"
annotated-types==0.7.0 ; python_full_version >= "3.10.0" and python_full_version < "4.0.0"
attrs==24.2.0 ; python_full_version >= "3.10.0" and python_full_version < "4.0.0"
attrs==24.3.0 ; python_full_version >= "3.10.0" and python_full_version < "4.0.0"
blinker==1.9.0 ; python_full_version >= "3.10.0" and python_full_version < "4.0.0"
certifi==2024.8.30 ; python_full_version >= "3.10.0" and python_full_version < "4.0.0"
certifi==2024.12.14 ; python_full_version >= "3.10.0" and python_full_version < "4.0.0"
cffi==1.17.1 ; python_full_version >= "3.10.0" and python_full_version < "4.0.0"
charset-normalizer==3.4.0 ; python_full_version >= "3.10.0" and python_full_version < "4.0.0"
charset-normalizer==3.4.1 ; python_full_version >= "3.10.0" and python_full_version < "4.0.0"
click==8.1.8 ; python_full_version >= "3.10.0" and python_full_version < "4.0.0"
colorama==0.4.6 ; python_full_version >= "3.10.0" and python_full_version < "4.0.0" and platform_system == "Windows"
cryptography==44.0.0 ; python_full_version >= "3.10.0" and python_full_version < "4.0.0"
Expand All @@ -15,7 +15,7 @@ flask==3.1.0 ; python_full_version >= "3.10.0" and python_full_version < "4.0.0"
greenlet==3.1.1 ; python_version < "3.13" and (platform_machine == "aarch64" or platform_machine == "ppc64le" or platform_machine == "x86_64" or platform_machine == "amd64" or platform_machine == "AMD64" or platform_machine == "win32" or platform_machine == "WIN32") and python_full_version >= "3.10.0"
idna==3.10 ; python_full_version >= "3.10.0" and python_full_version < "4.0.0"
itsdangerous==2.2.0 ; python_full_version >= "3.10.0" and python_full_version < "4.0.0"
jinja2==3.1.4 ; python_full_version >= "3.10.0" and python_full_version < "4.0.0"
jinja2==3.1.5 ; python_full_version >= "3.10.0" and python_full_version < "4.0.0"
jsonschema-specifications==2024.10.1 ; python_full_version >= "3.10.0" and python_full_version < "4.0.0"
jsonschema==4.23.0 ; python_full_version >= "3.10.0" and python_full_version < "4.0.0"
mako==1.3.8 ; python_full_version >= "3.10.0" and python_full_version < "4.0.0"
Expand All @@ -28,11 +28,11 @@ pygithub==2.5.0 ; python_full_version >= "3.10.0" and python_full_version < "4.0
pyjwt[crypto]==2.10.1 ; python_full_version >= "3.10.0" and python_full_version < "4.0.0"
pynacl==1.5.0 ; python_full_version >= "3.10.0" and python_full_version < "4.0.0"
pyyaml==6.0.2 ; python_full_version >= "3.10.0" and python_full_version < "4.0.0"
referencing==0.35.1 ; python_full_version >= "3.10.0" and python_full_version < "4.0.0"
referencing==0.36.1 ; python_full_version >= "3.10.0" and python_full_version < "4.0.0"
requests==2.32.3 ; python_full_version >= "3.10.0" and python_full_version < "4.0.0"
rpds-py==0.22.0 ; python_full_version >= "3.10.0" and python_full_version < "4.0.0"
sqlalchemy==2.0.36 ; python_full_version >= "3.10.0" and python_full_version < "4.0.0"
rpds-py==0.22.3 ; python_full_version >= "3.10.0" and python_full_version < "4.0.0"
sqlalchemy==2.0.37 ; python_full_version >= "3.10.0" and python_full_version < "4.0.0"
typing-extensions==4.12.2 ; python_full_version >= "3.10.0" and python_full_version < "4.0.0"
urllib3==2.2.3 ; python_full_version >= "3.10.0" and python_full_version < "4.0.0"
urllib3==2.3.0 ; python_full_version >= "3.10.0" and python_full_version < "4.0.0"
werkzeug==3.1.3 ; python_full_version >= "3.10.0" and python_full_version < "4.0.0"
wrapt==1.17.0 ; python_full_version >= "3.10.0" and python_full_version < "4.0.0"
wrapt==1.17.2 ; python_full_version >= "3.10.0" and python_full_version < "4.0.0"
2 changes: 1 addition & 1 deletion rockcraft.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

name: repo-policy-compliance
base: [email protected]
version: '1.10.5'
version: '1.11.0'
summary: Check the repository setup for policy compliance
description: |
Used to check whether a GitHub repository complies with expected policies.
Expand Down
2 changes: 1 addition & 1 deletion src-docs/__init__.py.md
Original file line number Diff line number Diff line change
Expand Up @@ -168,8 +168,8 @@ Sentinel to indicate which policy to use.

**Attributes:**

- <b>`ALL`</b>: Use all policies.
- <b>`PULL_REQUEST_ALLOW_FORK`</b>: Use policy that lets forked repositories run jobs (default).
- <b>`PULL_REQUEST_DISALLOW_FORK`</b>: Use policy that only blocks disallowed forks.



Expand Down
6 changes: 3 additions & 3 deletions src-docs/policy.py.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,12 @@ Module for the policy document.
- **ENABLED_KEY**
- **ENABLED_RULE**
- **DISABLED_RULE**
- **ALL**
- **ALLOW_FORK**
- **DISALLOW_FORK**

---

<a href="../repo_policy_compliance/policy.py#L100"><img align="right" style="float:right;" src="https://img.shields.io/badge/-source-cccccc?style=flat-square"></a>
<a href="../repo_policy_compliance/policy.py#L105"><img align="right" style="float:right;" src="https://img.shields.io/badge/-source-cccccc?style=flat-square"></a>

## <kbd>function</kbd> `check`

Expand All @@ -39,7 +39,7 @@ Check that a policy document is valid.

---

<a href="../repo_policy_compliance/policy.py#L120"><img align="right" style="float:right;" src="https://img.shields.io/badge/-source-cccccc?style=flat-square"></a>
<a href="../repo_policy_compliance/policy.py#L125"><img align="right" style="float:right;" src="https://img.shields.io/badge/-source-cccccc?style=flat-square"></a>

## <kbd>function</kbd> `enabled`

Expand Down
72 changes: 64 additions & 8 deletions tests/app/integration/test_blueprint.py
Original file line number Diff line number Diff line change
Expand Up @@ -236,22 +236,40 @@ def test_check_run_missing_data(
"github_branch, collaborators_with_permission",
[
(
f"test-branch/blueprint/pull-request/fail/{uuid4()}",
f"test-branch/blueprint/pull-request/{uuid4()}",
RequestedCollaborator("admin", "admin"),
)
],
indirect=["github_branch", "collaborators_with_permission"],
)
@pytest.mark.parametrize(
"disallow_fork, expected_http_status, expected_message",
[
pytest.param("true", http.HTTPStatus.NO_CONTENT, ""),
pytest.param("false", http.HTTPStatus.FORBIDDEN, "outside collaborators"),
],
)
@pytest.mark.usefixtures("collaborators_with_permission")
def test_pull_request_check_run_fail(
client: FlaskClient, runner_token: str, github_repository: Repository, github_branch: Branch
def test_pull_request_check_run(
client: FlaskClient,
runner_token: str,
github_repository: Repository,
github_branch: Branch,
monkeypatch: pytest.MonkeyPatch,
disallow_fork: str,
expected_http_status: int,
expected_message: str,
):
"""
arrange: given flask application with the blueprint registered and the charm token environment
variable set
act: when pull request check run is requested with a runner token and an invalid run
assert: then 403 is returned.
variable set and whether disallowed forks is enabled or not
act: when pull request check run is requested with a runner token and a run with outside
collaborators
assert: check 204 is returned if disallowed forks (as only forks are checked) or 403 if the env
var for disallow forks is not true.
"""
monkeypatch.setenv("PULL_REQUEST_DISALLOW_FORK", disallow_fork)

response = client.post(
blueprint.PULL_REQUEST_CHECK_RUN_ENDPOINT,
json={
Expand All @@ -264,8 +282,8 @@ def test_pull_request_check_run_fail(
headers={"Authorization": f"Bearer {runner_token}"},
)

assert response.status_code == http.HTTPStatus.FORBIDDEN, response.data
assert_.substrings_in_string(("outside collaborators",), response.data.decode("utf-8"))
assert response.status_code == expected_http_status, response.data
assert_.substrings_in_string((expected_message,), response.data.decode("utf-8"))


@pytest.mark.parametrize(
Expand Down Expand Up @@ -892,3 +910,41 @@ def test_internal_server_error(
"Something went wrong while configuring repository compliance policy check. "
"Please contact the operator" in str(response.data, encoding="utf-8")
)


@pytest.mark.parametrize(
"forked_github_branch",
[f"test-branch/execute-job/no-comment-on-pr/{uuid4()}"],
indirect=["forked_github_branch"],
)
@pytest.mark.usefixtures("pr_from_forked_github_branch", "make_fork_from_non_collaborator")
def test_pull_request_disallow_fork_on_forked_pr_fail(
client: FlaskClient,
runner_token: str,
github_repository: Repository,
forked_github_repository: Repository,
monkeypatch: pytest.MonkeyPatch,
forked_github_branch: Branch,
):
"""
arrange: given flask application with the blueprint registered and the environment
variable set to disallow forks set to true
act: when pull request check run is requested with a runner token and a valid run
assert: then 403 is returned.
"""
monkeypatch.setenv("PULL_REQUEST_DISALLOW_FORK", "true")

response = client.post(
blueprint.PULL_REQUEST_CHECK_RUN_ENDPOINT,
json={
"repository_name": github_repository.full_name,
"source_repository_name": forked_github_repository.full_name,
"target_branch_name": github_repository.default_branch,
"source_branch_name": forked_github_branch.name,
"commit_sha": forked_github_branch.commit.sha,
},
headers={"Authorization": f"Bearer {runner_token}"},
)

assert response.status_code == http.HTTPStatus.FORBIDDEN, response.data
assert_.substrings_in_string(("fork repository",), response.data.decode("utf-8"))
2 changes: 1 addition & 1 deletion tests/app/integration/test_pull_request.py
Original file line number Diff line number Diff line change
Expand Up @@ -292,7 +292,7 @@ def test_execute_job( # pylint: disable=too-many-arguments
pytest.param(
f"test-branch/pull_request/pass/{uuid4()}",
BranchWithProtection(),
{"policy_document": UsedPolicy.ALL},
{"policy_document": UsedPolicy.PULL_REQUEST_DISALLOW_FORK},
id="all policy",
),
],
Expand Down
12 changes: 10 additions & 2 deletions tests/app/unit/test_blueprint.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,9 +31,17 @@
{"test": "content"},
id="policy document & flask env",
),
pytest.param("", {"PULL_REQUEST_DISALLOW_FORK": "true"}, UsedPolicy.ALL, id="env"),
pytest.param(
"", {"FLASK_PULL_REQUEST_DISALLOW_FORK": "true"}, UsedPolicy.ALL, id="flask env"
"",
{"PULL_REQUEST_DISALLOW_FORK": "true"},
UsedPolicy.PULL_REQUEST_DISALLOW_FORK,
id="env",
),
pytest.param(
"",
{"FLASK_PULL_REQUEST_DISALLOW_FORK": "true"},
UsedPolicy.PULL_REQUEST_DISALLOW_FORK,
id="flask env",
),
pytest.param(
"",
Expand Down
6 changes: 3 additions & 3 deletions tox.ini
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ charm_tst_path = {[vars]tst_path}charm/
all_path = {[vars]src_path} {[vars]tst_path}

[testenv]
basepython = python3.10
basepython = python3.12
allowlist_externals=python
setenv =
PYTHONPATH = {toxinidir}:{toxinidir}/lib:{[vars]src_path}
Expand Down Expand Up @@ -74,7 +74,7 @@ commands =
passenv = AUTH_GITHUB_TOKEN, AUTH_GITHUB_APP_ID, AUTH_GITHUB_APP_INSTALLATION_ID, AUTH_GITHUB_APP_PRIVATE_KEY, CI_GITHUB_TOKEN
description = Run tests
deps =
coverage[toml]>=6,<7
coverage[toml]>=7
poetry
commands =
poetry install
Expand All @@ -96,7 +96,7 @@ commands =
[testenv:coverage-report]
description = Create test coverage report
deps =
coverage[toml]>=6,<7
coverage[toml]>=7
commands =
coverage report

Expand Down

0 comments on commit b436804

Please sign in to comment.