From fc31e1be7343a59e59deb8889eafaef3c067e229 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rg=20Thalheim?= Date: Thu, 16 Nov 2023 14:31:39 +0100 Subject: [PATCH 1/5] allow all org members to automerge --- modules/web01/clan-merge.nix | 12 +---------- pkgs/clan-merge/clan_merge/__init__.py | 30 +++++++++++++++----------- pkgs/clan-merge/tests/test_cli.py | 19 ++++++++-------- 3 files changed, 29 insertions(+), 32 deletions(-) diff --git a/modules/web01/clan-merge.nix b/modules/web01/clan-merge.nix index 9e117aa..9efe37b 100644 --- a/modules/web01/clan-merge.nix +++ b/modules/web01/clan-merge.nix @@ -14,17 +14,7 @@ while sleep 10; do ${self.packages.${pkgs.system}.clan-merge}/bin/clan-merge \ --bot-name clan-bot \ - --allowed-users \ - clan-bot \ - hsjobeki \ - DavHau \ - lassulus \ - Mic92 \ - Qubasa \ - --repos\ - clan-infra \ - clan-core \ - clan-homepage + --repos clan-infra clan-core clan-homepage done ''; }; diff --git a/pkgs/clan-merge/clan_merge/__init__.py b/pkgs/clan-merge/clan_merge/__init__.py index d76330f..6f765aa 100644 --- a/pkgs/clan-merge/clan_merge/__init__.py +++ b/pkgs/clan-merge/clan_merge/__init__.py @@ -1,6 +1,7 @@ import argparse import json import urllib.request +import urllib.error from os import environ from typing import Optional @@ -37,11 +38,23 @@ def is_ci_green(pr: dict) -> bool: return False return True +def is_org_member(user: str, token: str) -> bool: + url = "https://git.clan.lol/api/v1/orgs/clan/members/" + user + f"?token={token}" + try: + urllib.request.urlopen(url) + return True + except urllib.error.HTTPError as e: + if e.code == 404: + return False + else: + raise -def decide_merge(pr: dict, allowed_users: list[str], bot_name: str) -> bool: + + +def merge_allowed(pr: dict, bot_name: str, token: str) -> bool: assignees = pr["assignees"] if pr["assignees"] else [] if ( - pr["user"]["login"] in allowed_users + is_org_member(pr["user"]["login"], token) and pr["mergeable"] is True and not pr["title"].startswith("WIP:") and pr["state"] == "open" @@ -61,10 +74,10 @@ def list_prs(repo: str) -> list: return data -def list_prs_to_merge(prs: list, allowed_users: list[str], bot_name: str) -> list: +def list_prs_to_merge(prs: list, bot_name: str, gitea_token: str) -> list: prs_to_merge = [] for pr in prs: - if decide_merge(pr, allowed_users, bot_name) is True: + if merge_allowed(pr, bot_name, gitea_token): prs_to_merge.append(pr) return prs_to_merge @@ -72,12 +85,6 @@ def list_prs_to_merge(prs: list, allowed_users: list[str], bot_name: str) -> lis def parse_args() -> argparse.Namespace: parser = argparse.ArgumentParser(description="Merge PRs on clan.lol") # parse a list of allowed users - parser.add_argument( - "--allowed-users", - nargs="+", - help="list of users allowed to merge", - required=True, - ) # option for bot-name parser.add_argument( "--bot-name", @@ -107,13 +114,12 @@ def clan_merge( gitea_token = load_token() if args is None: args = parse_args() - allowed_users = args.allowed_users repos = args.repos dry_run = args.dry_run bot_name = args.bot_name for repo in repos: prs = list_prs(repo) - prs_to_merge = list_prs_to_merge(prs, allowed_users, bot_name) + prs_to_merge = list_prs_to_merge(prs, bot_name, gitea_token) for pr in prs_to_merge: url = ( "https://git.clan.lol/api/v1/repos/clan/" diff --git a/pkgs/clan-merge/tests/test_cli.py b/pkgs/clan-merge/tests/test_cli.py index a2b0ae9..74e3ab9 100644 --- a/pkgs/clan-merge/tests/test_cli.py +++ b/pkgs/clan-merge/tests/test_cli.py @@ -13,7 +13,7 @@ def test_no_args(capsys: pytest.CaptureFixture) -> None: def test_decide_merge_allowed(monkeypatch: pytest.MonkeyPatch) -> None: monkeypatch.setattr(clan_merge, "is_ci_green", lambda x: True) - allowed_users = ["foo"] + monkeypatch.setattr(clan_merge, "is_org_member", lambda y, x: True) bot_name = "some-bot-name" pr = dict( id=1, @@ -23,12 +23,12 @@ def test_decide_merge_allowed(monkeypatch: pytest.MonkeyPatch) -> None: state="open", assignees=[dict(login=bot_name)], ) - assert clan_merge.decide_merge(pr, allowed_users, bot_name=bot_name) is True + assert clan_merge.merge_allowed(pr, bot_name=bot_name, token="test") is True def test_decide_merge_not_allowed(monkeypatch: pytest.MonkeyPatch) -> None: monkeypatch.setattr(clan_merge, "is_ci_green", lambda x: True) - allowed_users = ["foo"] + monkeypatch.setattr(clan_merge, "is_org_member", lambda y, x: True) pr1 = dict( id=1, user=dict(login="bar"), @@ -69,15 +69,16 @@ def test_decide_merge_not_allowed(monkeypatch: pytest.MonkeyPatch) -> None: state="open", assignees=[dict(login="clan-bot")], ) - assert clan_merge.decide_merge(pr1, allowed_users, bot_name="some-bot") is False - assert clan_merge.decide_merge(pr2, allowed_users, bot_name="some-bot") is False - assert clan_merge.decide_merge(pr3, allowed_users, bot_name="some-bot") is False - assert clan_merge.decide_merge(pr4, allowed_users, bot_name="some-bot") is False - assert clan_merge.decide_merge(pr5, allowed_users, bot_name="some-bot") is False + assert not clan_merge.merge_allowed(pr1, bot_name="some-bot", token="test") + assert not clan_merge.merge_allowed(pr2, bot_name="some-bot", token="test") + assert not clan_merge.merge_allowed(pr3, bot_name="some-bot", token="test") + assert not clan_merge.merge_allowed(pr4, bot_name="some-bot", token="test") + assert not clan_merge.merge_allowed(pr5, bot_name="some-bot", token="test") def test_list_prs_to_merge(monkeypatch: pytest.MonkeyPatch) -> None: monkeypatch.setattr(clan_merge, "is_ci_green", lambda x: True) + monkeypatch.setattr(clan_merge, "is_org_member", lambda user, x: user == "foo") bot_name = "some-bot-name" prs = [ dict( @@ -111,4 +112,4 @@ def test_list_prs_to_merge(monkeypatch: pytest.MonkeyPatch) -> None: assignees=[dict(login=bot_name)], ), ] - assert clan_merge.list_prs_to_merge(prs, ["foo"], bot_name=bot_name) == [prs[0]] + assert clan_merge.list_prs_to_merge(prs, bot_name=bot_name, gitea_token="test") == [prs[0]] From 540515d10fa8277e5a3bad0b6557ee09b11c74f1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rg=20Thalheim?= Date: Thu, 16 Nov 2023 14:48:46 +0100 Subject: [PATCH 2/5] rotate bot tokens --- sops/secrets/clan-bot-gitea-token/secret | 8 ++++---- sops/secrets/merge-bot-gitea-token/secret | 8 ++++---- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/sops/secrets/clan-bot-gitea-token/secret b/sops/secrets/clan-bot-gitea-token/secret index a1b38fa..bf7e366 100644 --- a/sops/secrets/clan-bot-gitea-token/secret +++ b/sops/secrets/clan-bot-gitea-token/secret @@ -1,5 +1,5 @@ { - "data": "ENC[AES256_GCM,data:JPpo0Pg3v7SuwfbQITVDuxju05NCgMbf1NxxLN00GYGsw86lpJRBVKg=,iv:4GUI+PRE2tan3fJqnJGvKe8L6o2+2G5uZhm0yafkWOE=,tag:9kKvlkeK3uvlSYBzwZLBWA==,type:str]", + "data": "ENC[AES256_GCM,data:sP9gs+/oRZiArQUHrHOYkd3GdrmBGzdreNhcR24OOrFOLzrK2EMl7+o=,iv:SE/wO2VWePHqyTM55paLLPRBWGXxN9Z1M9C9wfmePZs=,tag:mn3dQfNqc6/wLDl6tkIbAg==,type:str]", "sops": { "kms": null, "gcp_kms": null, @@ -27,10 +27,10 @@ "enc": "-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSAxSFJyQlM0aGNqb0VZUmp0\nUndtTGJiR3lTQ0xSZG1KZWFKaE9qZjlaUXpVCjROUzA5NzZQNTJ5K1huekk2Z0Er\naUsrOStXVlJXOWJKbE1ISzhycDZDdHMKLS0tIFd4OTV1dU9Ya05KOUo4dktSMGJ2\nWXhMNHB5aVRGZFJqZUEvQWdvdmFBSjAKz3fZcUjBDbzrWnAZcS0naFb+4X8LB3vY\nJogBV7lPCo/1H/ZJZPPNXWl0wuiePHB/Rt7fuHAn2PEOilP7tCkkYA==\n-----END AGE ENCRYPTED FILE-----\n" } ], - "lastmodified": "2023-08-09T10:59:21Z", - "mac": "ENC[AES256_GCM,data:2L0I52HpklPTnWl2rQkK8PLEJjss/PMeqWGudxiIZt6u5RDdRycia6NZKKt7iCwUoHyvQQVMUDmSLjc4r+xDCL3EyORWoX3UMBDdn7yZHVH4VogW4t6c3RG/r2kuxS23xWTwnV70tQzXZ4YeR6/JyR0pc7+qOhwB318HBBfiIdE=,iv:cjTV9o38KcAoa4tm/Wh/uJpRSxA5MUIeNrPiWsCmTJs=,tag:MD1bcma7T4cJOr+thUvlCA==,type:str]", + "lastmodified": "2023-11-16T13:52:56Z", + "mac": "ENC[AES256_GCM,data:zXKoEYd+qo9rpFfo5S1HmjOrp8rJTg9CM+Y4vUoiBPG9LtTWWTpImRGjR2wjHZquO75cnupgRNV/RwDBxUjcIdkpPg0AdXLTIX+rjb/6e8Wifsj+uOwJKyAOOI8dz6Aq5IyD2d3b0m+iadOeo20rU/B65nnpN8l2BUPyq1YNOHE=,iv:OhH0BCZWm9vtwvjmT4GvVJXn7ekCpwSKofVF58gOStU=,tag:ZNFKnU7EcH58bw/iOTIN/w==,type:str]", "pgp": null, "unencrypted_suffix": "_unencrypted", - "version": "3.7.3" + "version": "3.8.1" } } \ No newline at end of file diff --git a/sops/secrets/merge-bot-gitea-token/secret b/sops/secrets/merge-bot-gitea-token/secret index 891a12a..be338bd 100644 --- a/sops/secrets/merge-bot-gitea-token/secret +++ b/sops/secrets/merge-bot-gitea-token/secret @@ -1,5 +1,5 @@ { - "data": "ENC[AES256_GCM,data:bEu3iLvQfNmAnpKOYLHViFJkxa9QYr5sX941Y2uiUHZXyK+kld7UDrA=,iv:qOFwSzInoCD0ctChHGpplX8Fo2PwvGSd8xewxiqwzDs=,tag:SvghYrsfSt/rNdYPGjg2Ug==,type:str]", + "data": "ENC[AES256_GCM,data:9np4k4rwmHU85dEAmzBbDTewQdo/qfZKAl1sh6L22VvB5aFFr6Mcbvs=,iv:gKKzr0VuwIvoU1KP+trN7pDb3ZPiFqBpygVdW7hSywo=,tag:/+zOagOtsHcBBk5N0sEY7g==,type:str]", "sops": { "kms": null, "gcp_kms": null, @@ -27,10 +27,10 @@ "enc": "-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBNVXFhN1V3YkRvdkRJQnN0\ndVNOY09DVmc2T25mdFJkUjQraVF1MFQrMGlnCjZqZ2Q0WG1YeTF5ZCtHNXhUS2x5\nV0hadkZZanZwYXV1MHBOKzJHOWFyQW8KLS0tIHRCeDFyZUgwRWgwUG45THZtMFpx\nZjhDcEVCVXVPQnVWOGJaWnl5NFVDUFUKD0fJ62m+7KUK9tsWRulCUINm6VXjzkne\nMpfM/OQuR97ohBYY4BXgJCC1KAduEjonEMkP/0j12p3XRU9/ZlT4gA==\n-----END AGE ENCRYPTED FILE-----\n" } ], - "lastmodified": "2023-08-09T10:59:21Z", - "mac": "ENC[AES256_GCM,data:v996pu7bI6rPcTpq3L3HsOAQenrJml1sR4j4WbzTubHePNsJNXJ2He5e1nFYLP4inU6Edtu6/KIJFpz6FkdcQVSW+2izByzh87bG26FpCqRQKpbN7wvLwBE5d12n1yX8Ck23oI0Bm3hc2wk11e0ngQg2Ngfa6MDinGvcnXUSJtQ=,iv:6Kx2OObbDW4h2NGoGjE/nlYAvdGzu3nD+L3FpKhcHDw=,tag:hnK10FS5h7sMiggJmv5qjw==,type:str]", + "lastmodified": "2023-11-16T13:44:37Z", + "mac": "ENC[AES256_GCM,data:tSxb17SZhN5dTw7R7PwHUpdNXqKOqt3/V+bJamvSGAjvfoxY0OUnFFwUNR8Cr7IRUcl2m4Y288fmQ74YcyXQd9emkpTppauybf5AobNsTht6BxyPOFPXAk2V70WmvM75Mt6vm6Xq319YNAF9n8kTQJuwVYfxQxCn8slQNL/eiS0=,iv:MFvDKLE/2zq5lZmwZ+IxPGmHzWWmmIzOLIg5oUoYcjU=,tag:pqJmOgrIDoVc3kj5t6zyZA==,type:str]", "pgp": null, "unencrypted_suffix": "_unencrypted", - "version": "3.7.3" + "version": "3.8.1" } } \ No newline at end of file From 5f078a336c32e10a1dc055732bf5e63eea559306 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rg=20Thalheim?= Date: Thu, 16 Nov 2023 15:02:26 +0100 Subject: [PATCH 3/5] fix website deployment --- modules/web01/homepage.nix | 1 + 1 file changed, 1 insertion(+) diff --git a/modules/web01/homepage.nix b/modules/web01/homepage.nix index 80d7fef..84b36f0 100644 --- a/modules/web01/homepage.nix +++ b/modules/web01/homepage.nix @@ -11,6 +11,7 @@ "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIMxZ3Av30M6Sh6NU1mnCskB16bYtNP8vskc/+ud0AU1C ssh-homepage-key" ]; isSystemUser = true; + shell = "/run/current-system/sw/bin/bash"; group = "www"; }; users.groups.www = { }; From ea808bfc9c1be9575ec5635cd102fb90417df430 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rg=20Thalheim?= Date: Thu, 16 Nov 2023 15:05:58 +0100 Subject: [PATCH 4/5] only build with nix-fast-build --- .gitea/workflows/check.yaml | 11 ----------- .gitea/workflows/checks.yaml | 2 +- 2 files changed, 1 insertion(+), 12 deletions(-) delete mode 100644 .gitea/workflows/check.yaml diff --git a/.gitea/workflows/check.yaml b/.gitea/workflows/check.yaml deleted file mode 100644 index 12e47f0..0000000 --- a/.gitea/workflows/check.yaml +++ /dev/null @@ -1,11 +0,0 @@ -name: build -on: - pull_request: - push: - branches: main -jobs: - test: - runs-on: nix - steps: - - uses: actions/checkout@v3 - - run: nix flake check -L diff --git a/.gitea/workflows/checks.yaml b/.gitea/workflows/checks.yaml index 6705af0..a90c8e6 100644 --- a/.gitea/workflows/checks.yaml +++ b/.gitea/workflows/checks.yaml @@ -8,4 +8,4 @@ jobs: runs-on: nix steps: - uses: actions/checkout@v3 - - run: nix run --refresh github:Mic92/nix-fast-build/ae50c356c2f9e790f3d9d8e00bfa9f4b54f49bdd + - run: nix run --refresh github:Mic92/nix-fast-build -- --no-nom From 26f050d412b32ed719a8247c9dc6e726de1fc298 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rg=20Thalheim?= Date: Thu, 16 Nov 2023 15:41:13 +0100 Subject: [PATCH 5/5] harmonia: trust our binary caches --- modules/web01/harmonia.nix | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/modules/web01/harmonia.nix b/modules/web01/harmonia.nix index 87c033c..7eda587 100644 --- a/modules/web01/harmonia.nix +++ b/modules/web01/harmonia.nix @@ -9,6 +9,10 @@ }; }; + # trust our own cache + nix.settings.trusted-substituters = [ "https://cache.clan.lol" ]; + nix.settings.trusted-public-keys = [ "cache.clan.lol-1:3KztgSAB5R1M+Dz7vzkBGzXdodizbgLXGXKXlcQLA28=" ]; + services.nginx.virtualHosts."cache.clan.lol" = { forceSSL = true; enableACME = true;