From ba937f1b835f9e824dc64db206b2162310e66bc9 Mon Sep 17 00:00:00 2001 From: Adam Moussa <166072409+amoussa1229@users.noreply.github.com> Date: Mon, 11 May 2026 18:46:25 -0400 Subject: [PATCH] Add autodiscovery and token refresh crons MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Autodiscovery runs hourly — creates Forgejo mirrors for new GitHub org repos. Token refresh runs daily — propagates the current PAT from Secrets Manager to all mirror git remotes. --- lib/forgejo-stack.ts | 92 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 92 insertions(+) diff --git a/lib/forgejo-stack.ts b/lib/forgejo-stack.ts index 3996c1f..3e6195c 100644 --- a/lib/forgejo-stack.ts +++ b/lib/forgejo-stack.ts @@ -52,6 +52,13 @@ export class ForgejoStack extends cdk.Stack { ], }); + role.addToPolicy(new iam.PolicyStatement({ + actions: ["secretsmanager:GetSecretValue"], + resources: [ + `arn:aws:secretsmanager:us-east-1:328440206208:secret:forgejo/*`, + ], + })); + const backupBucket = new s3.Bucket(this, "BackupBucket", { bucketName: "forgejo-backups-328440206208", encryption: s3.BucketEncryption.S3_MANAGED, @@ -161,6 +168,91 @@ export class ForgejoStack extends cdk.Stack { "", "echo '0 5 * * * root /usr/local/bin/forgejo-backup.sh >> /var/log/forgejo-backup.log 2>&1' > /etc/cron.d/forgejo-backup", "chmod 644 /etc/cron.d/forgejo-backup", + "", + "cat > /usr/local/bin/forgejo-autodiscover.sh << 'ADEOF'", + "#!/bin/bash", + "set -euo pipefail", + "GH_PAT=$(aws secretsmanager get-secret-value --secret-id forgejo/github-pat --query SecretString --output text --region us-east-1)", + "FORGEJO_TOKEN=$(aws secretsmanager get-secret-value --secret-id forgejo/api-token --query SecretString --output text --region us-east-1)", + "FORGEJO_URL=https://forgejo.seahaven.com/api/v1", + "GH_ORG=Sea-Haven-Industries", + "", + "gh_repos=$(curl -sf -H \"Authorization: token $GH_PAT\" \"https://api.github.com/orgs/$GH_ORG/repos?per_page=100&type=all\" | python3 -c \"", + "import sys, json", + "for r in json.load(sys.stdin):", + " print(f\\\"{r['name']}\\\\t{r['archived']}\\\")", + "\")", + "", + "forgejo_repos=$(curl -sf -H \"Authorization: token $FORGEJO_TOKEN\" \"$FORGEJO_URL/repos/search?limit=100\" | python3 -c \"", + "import sys, json", + "data = json.load(sys.stdin)", + "repos = data.get('data', data) if isinstance(data, dict) else data", + "for r in repos:", + " print(r['name'])", + "\")", + "", + "while IFS=$'\\t' read -r name archived; do", + " if ! echo \"$forgejo_repos\" | grep -qx \"$name\"; then", + " mirror=true", + " [ \"$archived\" = \"True\" ] && mirror=false", + " echo \"$(date -Is) Discovering: $name (mirror=$mirror)\"", + " curl -sf -X POST \"$FORGEJO_URL/repos/migrate\" \\", + " -H \"Authorization: token $FORGEJO_TOKEN\" \\", + " -H \"Content-Type: application/json\" \\", + " -d \"{", + " \\\"clone_addr\\\": \\\"https://github.com/$GH_ORG/${name}.git\\\",", + " \\\"auth_token\\\": \\\"${GH_PAT}\\\",", + " \\\"repo_name\\\": \\\"${name}\\\",", + " \\\"repo_owner\\\": \\\"adam\\\",", + " \\\"service\\\": \\\"github\\\",", + " \\\"mirror\\\": ${mirror},", + " \\\"issues\\\": true,", + " \\\"labels\\\": true,", + " \\\"milestones\\\": true,", + " \\\"pull_requests\\\": true,", + " \\\"releases\\\": true,", + " \\\"wiki\\\": true", + " }\" > /dev/null", + " fi", + "done <<< \"$gh_repos\"", + "ADEOF", + "chmod +x /usr/local/bin/forgejo-autodiscover.sh", + "", + "cat > /usr/local/bin/forgejo-refresh-tokens.sh << 'RTEOF'", + "#!/bin/bash", + "set -euo pipefail", + "GH_PAT=$(aws secretsmanager get-secret-value --secret-id forgejo/github-pat --query SecretString --output text --region us-east-1)", + "FORGEJO_TOKEN=$(aws secretsmanager get-secret-value --secret-id forgejo/api-token --query SecretString --output text --region us-east-1)", + "FORGEJO_URL=https://forgejo.seahaven.com/api/v1", + "REPO_ROOT=/var/lib/forgejo/data/repositories/adam", + "", + "export GIT_CONFIG_COUNT=1", + "export GIT_CONFIG_KEY_0=safe.directory", + "export GIT_CONFIG_VALUE_0='*'", + "", + "mirrors=$(curl -sf -H \"Authorization: token $FORGEJO_TOKEN\" \"$FORGEJO_URL/repos/search?limit=100\" | python3 -c \"", + "import sys, json", + "data = json.load(sys.stdin)", + "repos = data.get('data', data) if isinstance(data, dict) else data", + "for r in repos:", + " if r.get('mirror', False):", + " print(r['name'])", + "\")", + "", + "while read -r repo_name; do", + " [ -z \"$repo_name\" ] && continue", + " repo_dir=\"$REPO_ROOT/${repo_name}.git\"", + " if [ -d \"$repo_dir\" ]; then", + " new_url=\"https://${GH_PAT}@github.com/Sea-Haven-Industries/${repo_name}.git\"", + " git -C \"$repo_dir\" remote set-url origin \"$new_url\" 2>/dev/null && echo \"$(date -Is) Refreshed: $repo_name\"", + " fi", + "done <<< \"$mirrors\"", + "RTEOF", + "chmod +x /usr/local/bin/forgejo-refresh-tokens.sh", + "", + "printf '%s\\n' '0 * * * * root /usr/local/bin/forgejo-autodiscover.sh >> /var/log/forgejo-autodiscover.log 2>&1' > /etc/cron.d/forgejo-autodiscover", + "printf '%s\\n' '30 4 * * * root /usr/local/bin/forgejo-refresh-tokens.sh >> /var/log/forgejo-refresh-tokens.log 2>&1' > /etc/cron.d/forgejo-refresh-tokens", + "chmod 644 /etc/cron.d/forgejo-autodiscover /etc/cron.d/forgejo-refresh-tokens", ); const instance = new ec2.Instance(this, "Instance", {