Zum Hauptinhalt springen
tsecurity.de LIVE
Echtzeit-Radar & Feeds
Alle RSS Feeds
👥 Community & Social
Sichere ProgrammierungBreeze TTS 2 vs ElevenLabs: Open Source TTS Verdict(23.09.2026 um 05:44 Uhr)
Sichere ProgrammierungAgentic AI vs Generative AI: The 2026 Verdict(23.09.2026 um 05:44 Uhr)
Sichere ProgrammierungI made my agent prove every quote against the source document(23.09.2026 um 05:45 Uhr)
Sichere Programmierung8mb.video Alternative: Skip the Line, Skip the Upsell(23.09.2026 um 05:47 Uhr)
Sichere ProgrammierungBuilding a GTA 6 JSON API for entities and current status(23.09.2026 um 05:52 Uhr)
Sichere ProgrammierungEvery filter needs a documented exception(23.09.2026 um 06:01 Uhr)
Sichere ProgrammierungBreeze TTS 2 vs ElevenLabs: Open Source TTS Verdict(23.09.2026 um 05:44 Uhr)
Sichere ProgrammierungAgentic AI vs Generative AI: The 2026 Verdict(23.09.2026 um 05:44 Uhr)
Sichere ProgrammierungI made my agent prove every quote against the source document(23.09.2026 um 05:45 Uhr)
Sichere Programmierung8mb.video Alternative: Skip the Line, Skip the Upsell(23.09.2026 um 05:47 Uhr)
Sichere ProgrammierungBuilding a GTA 6 JSON API for entities and current status(23.09.2026 um 05:52 Uhr)
Sichere ProgrammierungEvery filter needs a documented exception(23.09.2026 um 06:01 Uhr)
Intelligence View
⚡ tsecurity.de Intelligence

Your Pull Requests Are Being Ignored. Fix It with This Simple Bot

Pull requests don’t get stuck because they’re hard. They get stuck because everyone forgets due to various reasons. So instead of relying on memory, I built a small bot using Rapidforge that: finds stale PRs posts a clean reminder to Sl…

0
↗ Quelle (dev.to)
Reagiere als Erste:r — dein Feedback zählt!

Pull requests don’t get stuck because they’re hard.



They get stuck because everyone forgets due to various reasons.



So instead of relying on memory, I built a small bot using Rapidforge that:




  • finds stale PRs

  • posts a clean reminder to Slack

  • avoids spamming the same alerts






What is RapidForge?



RapidForge is a self hosted platform enabling users to turn small scripts into tools you can actually run and reuse. Its super easy to setup and use.






 What we’re building



We’re going to create a small bot that:




  • Connects to GitHub using a GitHub App

  • Finds pull requests that haven’t been updated in a few days

  • Sends a single, clean reminder to Slack

  • Avoids repeating the same reminders using a KV store



All of this runs as a single scheduled task with one Lua script.






Step 1: Create a GitHub App



Create a new GitHub App from your GitHub settings.



Make sure to:




  • Enable user authorization (OAuth)

  • Install the app on the account or organization that owns your repository

  • Give it read access to Pull Requests

  • Limit repository access to only what you need



GitHub App tokens are scoped by both the app and the user, which keeps things nicely secure and avoids over permissioned integrations.






 Step 2: Save the GitHub credential in RapidForge



In RapidForge, create a new OAuth credential with the following values:



Name: GITHUB_PR_BOT

Client ID: your GitHub App client ID

Client Secret: your GitHub App client secret

Scope: leave empty

Authorization URL: https://github.com/login/oauth/authorize

Token URL: https://github.com/login/oauth/access_token



Oauth app parameters for Rapidforge to save access key



You can watch a video here to see how to create oauth apps in Rapidforge



RapidForge will give you a callback URL. Copy that into your GitHub App settings.



Once authorized, Rapidforge will inject access token via environment variable:



CRED_GITHUB_PR_BOT



Don't worry editor has auto complete to aid you.





 Step 3: Save the Slack webhook



Create an incoming webhook in Slack and store it as a text credential in RapidForge:



Name: SLACK_WEBHOOK



This will be available in your script as: CRED_SLACK_WEBHOOK





 Step 4: Create the periodic task



Lets create periodic task with following parameters



Periodic task creation ui



A good starting schedule (weekday mornings) is:



0 9 * * 1-5



Add these environment variables:



GITHUB_OWNER=your-org

GITHUB_REPO=your-repo

STALE_DAYS=3

REMINDER_COOLDOWN_HOURS=24

SKIP_DRAFTS=true





Step 5: Add the Lua script



Rapidforge allows you to write logic in Bash or Lua. However, if you are more confortable with another language you can always use it with shebang. (I.e #!/usr/bin/node) Just make sure host machine has the interpreter installed in that case. Lua is embeded into Rapidforge so it does not required to be installed




local json = require("json")
local http = require("http")

local token = os.getenv("CRED_GITHUB_PR_BOT")
local slackWebhook = os.getenv("CRED_SLACK_WEBHOOK")
local owner = os.getenv("GITHUB_OWNER")
local repo = os.getenv("GITHUB_REPO")
local rapidforgeBin = os.getenv("RAPIDFORGE_BIN") or "./rapidforge"

local staleDays = tonumber(os.getenv("STALE_DAYS") or "3")
local reminderCooldownHours = tonumber(os.getenv("REMINDER_COOLDOWN_HOURS") or "24")
local skipDrafts = (os.getenv("SKIP_DRAFTS") or "true") == "true"

local function fail(message)
io.stderr:write(message .. "\n")
os.exit(1)
end

if not token or token == "" then fail("Missing CRED_GITHUB_PR_BOT") end
if not slackWebhook or slackWebhook == "" then fail("Missing CRED_SLACK_WEBHOOK") end
if not owner or owner == "" then fail("Missing GITHUB_OWNER") end
if not repo or repo == "" then fail("Missing GITHUB_REPO") end

local function trim(value)
return (value:gsub("^%s+", ""):gsub("%s+$", ""))
end

local function shell(command)
local handle = io.popen(command)
if not handle then
return nil
end

local output = handle:read("*a") or ""
local ok, _, code = handle:close()

return trim(output), ok, code
end

local function shellQuote(value)
return string.format("%q", tostring(value))
end

local function kvGet(key)
local command = string.format(
"%s kv get %s 2>/dev/null",
shellQuote(rapidforgeBin),
shellQuote(key)
)
local result = shell(command)

if not result or result == "" then
return nil
end

return result
end

local function kvSet(key, value)
local command = string.format(
"%s kv set %s %s",
shellQuote(rapidforgeBin),
shellQuote(key),
shellQuote(value)
)
local _, ok = shell(command)

if not ok then
fail("Failed to store reminder state in RapidForge KV")
end
end

local function parseGithubTime(value)
local year, month, day, hour, min, sec = value:match("^(%d+)%-(%d+)%-(%d+)T(%d+):(%d+):(%d+)Z$")
if not year then
return nil
end

return os.time({
year = tonumber(year),
month = tonumber(month),
day = tonumber(day),
hour = tonumber(hour),
min = tonumber(min),
sec = tonumber(sec)
})
end

local function hoursSince(timestamp)
return math.floor((os.time() - timestamp) / 3600)
end

local function githubGet(path)
local body, status = http.get(
"https://api.github.com" .. path,
{
["Accept"] = "application/vnd.github+json",
["Authorization"] = "Bearer " .. token,
["X-GitHub-Api-Version"] = "2022-11-28",
["User-Agent"] = "rapidforge-pr-reminder"
}
)

if status ~= 200 then
fail("GitHub API request failed with status " .. tostring(status) .. ": " .. tostring(body))
end

return json.decode(body)
end

local function sendSlackMessage(text)
local payload = json.encode({ text = text })
local body, status = http.post(
slackWebhook,
payload,
{ ["Content-Type"] = "application/json" }
)

if status < 200 or status >= 300 then
fail("Slack webhook failed with status " .. tostring(status) .. ": " .. tostring(body))
end
end

local pulls = githubGet(string.format("/repos/%s/%s/pulls?state=open&per_page=100", owner, repo))
local stalePulls = {}

for _, pr in ipairs(pulls) do
if (not skipDrafts) or (pr.draft ~= true) then
local updatedAt = parseGithubTime(pr.updated_at)
if updatedAt then
local inactiveHours = hoursSince(updatedAt)
local staleHours = staleDays * 24

if inactiveHours >= staleHours then
local reminderKey = string.format("pr-reminder:%s:%s:%s", owner, repo, pr.number)
local lastReminder = tonumber(kvGet(reminderKey) or "0")
local cooldownSeconds = reminderCooldownHours * 3600

if lastReminder == 0 or (os.time() - lastReminder) >= cooldownSeconds then
table.insert(stalePulls, {
number = pr.number,
title = pr.title,
url = pr.html_url,
author = pr.user and pr.user.login or "unknown",
inactiveHours = inactiveHours,
reminderKey = reminderKey
})
end
end
end
end
end

if #stalePulls == 0 then
print("No stale pull requests found")
return
end

table.sort(stalePulls, function(a, b)
return a.inactiveHours > b.inactiveHours
end)

local lines = {
string.format("Open pull requests without updates for %d+ days in %s/%s:", staleDays, owner, repo),
""
}

for _, pr in ipairs(stalePulls) do
local inactiveDays = math.floor(pr.inactiveHours / 24)
table.insert(lines, string.format("• #%d %s — %s days idle — %s", pr.number, pr.title, inactiveDays, pr.url))
end

sendSlackMessage(table.concat(lines, "\n"))

local now = tostring(os.time())
for _, pr in ipairs(stalePulls) do
kvSet(pr.reminderKey, now)
end

print("Sent Slack reminder for " .. tostring(#stalePulls) .. " pull request(s)")






Optional: Failure alerts



Rapidforge allows you to add failure hook to notify Slack if something breaks:




ERROR_MSG="${FAILURE_ERROR:-$FAILURE_OUTPUT}"
ERROR_TRUNC=$(printf "%s" "$ERROR_MSG" | head -c 1800)

if [ -n "$CRED_SLACK_WEBHOOK" ]; then
curl -X POST -H 'Content-type: application/json' \
--data "{\"text\":\"❌ GitHub PR reminder failed\nTask ID: ${TASK_ID}\nExit code: ${FAILURE_EXIT_CODE}\n\n${ERROR_TRUNC}\"}" \
"$CRED_SLACK_WEBHOOK"
fi






That’s it. Hopefully this gives you a practical way to keep pull requests from going quiet without adding more manual work. If you’re interested in building similar small automations, you can check out RapidForge. There are a few more use cases there that follow the same idea of turning simple scripts into useful tools.

Ähnliche Beiträge
🔍 Verwandte News

Auch interessante Nachrichten Your Pull Requests Are Being Ignored. Fix It with This Simple Bot

Thematisch verwandte Begriffe: Your, Pull, Requests, Being · 6 Treffer

Laden...

Videos werden geladen ...

Laden...

Beiträge werden geladen ...

Laden...

Videos werden geladen ...

Laden...

Beiträge werden geladen ...

Laden...

Videos werden geladen ...

Laden...

Beiträge werden geladen ...

Laden...

Videos werden geladen ...

Laden...

Beiträge werden geladen ...

Laden...

Videos werden geladen ...

Zum Aktualisieren ziehen
ZERO-DAY CVE-2026-18163 | IBM Financial Transaction Manager (FTM) for RedHat OpenShift could allow…
Advisory →
TTS Reader • tsecurity.de Voice
tsecurity.de Icon
tsecurity.de App
Offline-Lesen, Eilmeldungen & 0ms Ladezeit

Installiere tsecurity.de direkt auf deinen Home-Bildschirm für das ultimative Vollbild-Magazinerlebnis ohne Browser-Leisten.

Nächster Beitrag
Themen-Radar & Intelligence Matrix
Echtzeit-Taxonomie nach Angriffsvektoren & Plattformen

tsecurity.de Live Threat Radar

🔴 LIVE RADAR
MONITORING
AKTIV
CVE-DATENBANK
LIVE
🔍
Community Radar & Live Chat
Sentinel Bot online • Live-Stream
Dein Cluster: Security Explorer
Match:
lädt…
Verbindung zum Community-Stream wird aufgebaut...
Bearbeitungsmodus — Senden überschreibt deine Nachricht
Community-Puls — was gerade passiert
lädt…
Aktivitäten deiner Analysten
lädt…
Neues Thema oder Eilmeldung einreichen

Reiche interessante Links, Zero-Days oder Debatten ein. Die Community entscheidet per Upvote über die Veröffentlichung.

Heiß diskutierte Einreichungen
🔖 Gespeicherte Artikel
📂 Keine gespeicherten Artikel vorhanden.
Zurück Ziehen Vor
Links: vorheriger Artikel Rechts: nächster Artikel unten: schließen
News NIS-2 Frühwarnung Tier-1 Intel ⏱️ 3 Min vor 10 Min
Artikeldaten werden geladen...

Zurück: vorheriger Vor: nächster
↗ Original-Quelle
Social Reaktionen Deine Reaktion zählt
Einstufung & Relevanz-Poll 0 Stimmen
In sozialen Netzwerken teilen 1-Klick