Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
161 changes: 161 additions & 0 deletions .github/workflows/close_dependabot_pr_if_ha_older.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,161 @@
name: Close Dependabot PR if HA older

# yamllint disable-line rule:truthy
on:
pull_request_target:
types: [opened, reopened, synchronize, edited]

permissions:
contents: read
issues: write
pull-requests: write

jobs:
close_pr_if_ha_uses_older_version:
if: github.actor == 'dependabot[bot]'
runs-on: ubuntu-latest
steps:
- name: Parse dependency and target version
id: parse
uses: actions/github-script@v8
with:
script: |
const title = context.payload.pull_request.title || "";
if (!title.startsWith("Bump ")) {
core.info(`Skipping PR with unsupported title format: ${title}`);
core.setOutput("dependency", "");
core.setOutput("new_version", "");
return;
}

const rest = title.slice("Bump ".length);
const toIndex = rest.lastIndexOf(" to ");
const fromIndex = toIndex === -1 ? -1 : rest.lastIndexOf(" from ", toIndex - 1);

if (fromIndex === -1 || toIndex === -1) {
core.info(`Skipping PR with unsupported title format: ${title}`);
core.setOutput("dependency", "");
core.setOutput("new_version", "");
return;
}

core.setOutput("dependency", rest.slice(0, fromIndex));
core.setOutput("new_version", rest.slice(toIndex + " to ".length));

- name: Compare with Home Assistant dependency version
id: compare
env:
DEPENDENCY: ${{ steps.parse.outputs.dependency }}
TARGET_VERSION: ${{ steps.parse.outputs.new_version }}
run: |
python -m pip install --disable-pip-version-check packaging
python - <<'PY'
Comment on lines +50 to +52
import os
import re
import urllib.error
import urllib.request
from packaging.version import InvalidVersion, Version

dependency = os.environ.get("DEPENDENCY", "").strip()
target_version_text = os.environ.get("TARGET_VERSION", "").strip()
output_file = os.environ["GITHUB_OUTPUT"]

def write_output(name: str, value: str) -> None:
with open(output_file, "a", encoding="utf-8") as handle:
handle.write(f"{name}={value}\n")

def main() -> None:
if not dependency or not target_version_text:
write_output("should_close", "false")
write_output("ha_version", "")
return

try:
target_version = Version(target_version_text.lstrip("v"))
except InvalidVersion:
write_output("should_close", "false")
write_output("ha_version", "")
return

requirements_url = (
"https://raw.githubusercontent.com/home-assistant/core/dev/"
"requirements_all.txt"
)
try:
with urllib.request.urlopen(requirements_url, timeout=30) as response:
requirements = response.read().decode("utf-8")
except urllib.error.HTTPError as err:
print(
f"Unable to fetch Home Assistant requirements: HTTP {err.code} {err.reason}"
)
write_output("should_close", "false")
write_output("ha_version", "")
return
except (OSError, urllib.error.URLError) as err:
print(f"Unable to fetch Home Assistant requirements: network error: {err}")
write_output("should_close", "false")
write_output("ha_version", "")
return

normalized_dependency = re.sub(r"[-_.]+", "-", dependency).lower()
ha_version = None

for line in requirements.splitlines():
line = line.strip()
if not line or line.startswith("#"):
continue

# Match: package-name[extras] == version (and similar operator forms).
match = re.match(
r"^([A-Za-z0-9_.\-]+)(?:\[[^]]+\])?\s*([<>=!~]{1,3})\s*([^;,\s]+)",
line,
)
if not match:
continue

package_name, operator, version_text = match.groups()
if re.sub(r"[-_.]+", "-", package_name).lower() != normalized_dependency:
continue

if operator != "==":
continue

try:
ha_version = Version(version_text)
except InvalidVersion:
ha_version = None
break

if ha_version is None:
write_output("should_close", "false")
write_output("ha_version", "")
return

write_output("ha_version", str(ha_version))
write_output("should_close", "true" if ha_version < target_version else "false")

main()
PY

- name: Close pull request
if: steps.compare.outputs.should_close == 'true'
uses: actions/github-script@v8
env:
DEPENDENCY: ${{ steps.parse.outputs.dependency }}
TARGET_VERSION: ${{ steps.parse.outputs.new_version }}
HA_VERSION: ${{ steps.compare.outputs.ha_version }}
with:
script: |
await github.rest.issues.createComment({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: context.issue.number,
body: `Closing this Dependabot PR because it proposes ${process.env.DEPENDENCY}==${process.env.TARGET_VERSION}, which is newer than the version currently used by Home Assistant (${process.env.HA_VERSION}).`
});

await github.rest.pulls.update({
owner: context.repo.owner,
repo: context.repo.repo,
pull_number: context.issue.number,
state: "closed",
});
Loading