mirror of
https://github.com/alexbelgium/hassio-addons.git
synced 2026-09-14 21:59:09 +02:00
Compare commits
18 Commits
create-pul
...
d31ccfa21c
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d31ccfa21c | ||
|
|
9c277876ff | ||
|
|
7e59aa8803 | ||
|
|
360fd669fa | ||
|
|
7bf77c8558 | ||
|
|
a195d3ac39 | ||
|
|
14834d4063 | ||
|
|
f5caafd62c | ||
|
|
fd61631ccd | ||
|
|
578a7f8368 | ||
|
|
5115dcb93a | ||
|
|
fa5e890c4c | ||
|
|
addb0ca66f | ||
|
|
16e112b21f | ||
|
|
040a4e0f2f | ||
|
|
f72f7bef0f | ||
|
|
c18f45d822 | ||
|
|
abf3d76873 |
2
.github/workflows/daily_ai_fix.yaml
vendored
2
.github/workflows/daily_ai_fix.yaml
vendored
@@ -125,7 +125,7 @@ jobs:
|
||||
|
||||
- name: Analyse and fix
|
||||
if: steps.batch.outputs.count != '0'
|
||||
uses: anthropics/claude-code-action@a874e9ecd7bb36efdad65429c6b35815f5a08f10 # v1
|
||||
uses: anthropics/claude-code-action@d75b94d5ad426cb8546e6628b6f5f19b84e5cce1 # v1
|
||||
with:
|
||||
claude_code_oauth_token: ${{ secrets.CLAUDE_CODE_OAUTH_TOKEN }}
|
||||
# Skip the OIDC -> Claude App token exchange. The scheduled path
|
||||
|
||||
2
.github/workflows/on_claude_mention.yml
vendored
2
.github/workflows/on_claude_mention.yml
vendored
@@ -64,7 +64,7 @@ jobs:
|
||||
fetch-depth: 1
|
||||
|
||||
- name: Run Claude Code
|
||||
uses: anthropics/claude-code-action@a874e9ecd7bb36efdad65429c6b35815f5a08f10 # v1
|
||||
uses: anthropics/claude-code-action@d75b94d5ad426cb8546e6628b6f5f19b84e5cce1 # v1
|
||||
with:
|
||||
claude_code_oauth_token: ${{ secrets.CLAUDE_CODE_OAUTH_TOKEN }}
|
||||
# AI_PR_TOKEN, not GITHUB_TOKEN, so a PR Claude opens triggers CI.
|
||||
|
||||
2
.github/workflows/on_issue_approved.yaml
vendored
2
.github/workflows/on_issue_approved.yaml
vendored
@@ -135,7 +135,7 @@ jobs:
|
||||
|
||||
- name: Execute the plan
|
||||
if: steps.bundle.outputs.has_plan == 'true'
|
||||
uses: anthropics/claude-code-action@a874e9ecd7bb36efdad65429c6b35815f5a08f10 # v1
|
||||
uses: anthropics/claude-code-action@d75b94d5ad426cb8546e6628b6f5f19b84e5cce1 # v1
|
||||
with:
|
||||
claude_code_oauth_token: ${{ secrets.CLAUDE_CODE_OAUTH_TOKEN }}
|
||||
# Skip the OIDC -> Claude App token exchange, which 401s whenever
|
||||
|
||||
2
.github/workflows/on_issues_ai_triage.yaml
vendored
2
.github/workflows/on_issues_ai_triage.yaml
vendored
@@ -166,7 +166,7 @@ jobs:
|
||||
id: classify
|
||||
if: github.event_name != 'issue_comment' || steps.claim.outputs.go == 'true'
|
||||
continue-on-error: true
|
||||
uses: anthropics/claude-code-action@a874e9ecd7bb36efdad65429c6b35815f5a08f10 # v1
|
||||
uses: anthropics/claude-code-action@d75b94d5ad426cb8546e6628b6f5f19b84e5cce1 # v1
|
||||
with:
|
||||
claude_code_oauth_token: ${{ secrets.CLAUDE_CODE_OAUTH_TOKEN }}
|
||||
# Without this the action falls back to the OIDC -> Claude App token
|
||||
|
||||
2
.github/workflows/on_pr_coderabbit.yml
vendored
2
.github/workflows/on_pr_coderabbit.yml
vendored
@@ -79,7 +79,7 @@ jobs:
|
||||
|
||||
- name: Address CodeRabbit comments
|
||||
if: steps.claim.outputs.go == 'true'
|
||||
uses: anthropics/claude-code-action@a874e9ecd7bb36efdad65429c6b35815f5a08f10 # v1
|
||||
uses: anthropics/claude-code-action@d75b94d5ad426cb8546e6628b6f5f19b84e5cce1 # v1
|
||||
with:
|
||||
claude_code_oauth_token: ${{ secrets.CLAUDE_CODE_OAUTH_TOKEN }}
|
||||
# Skip the OIDC -> Claude App token exchange, which 401s whenever
|
||||
|
||||
@@ -1,3 +1,21 @@
|
||||
## 20260909.5 (09-09-2026)
|
||||
- Minor bugs fixed
|
||||
## 20260909.4 (09-09-2026)
|
||||
- Minor bugs fixed
|
||||
## 20260909.3 (09-09-2026)
|
||||
- Minor bugs fixed
|
||||
## 20260909.2 (09-09-2026)
|
||||
- Minor bugs fixed
|
||||
## 20260909 (09-09-2026)
|
||||
- Minor bugs fixed
|
||||
## 20260908.2 (08-09-2026)
|
||||
- Minor bugs fixed
|
||||
## 20260908.1 (08-09-2026)
|
||||
- Synced with upstream birdnet-go (4 commits); re-merges the open fork PRs, adding fork PR #62 (reanalyze a clip with every loaded model + one-click correction)
|
||||
## 20260908 (08-09-2026)
|
||||
- Synced with upstream birdnet-go (7 commits); re-merges the open fork PRs
|
||||
## 20260907 (07-09-2026)
|
||||
- Rebuild: re-merges the open fork PRs, picking up the updated fork PR #57
|
||||
## 20260901.4 (01-09-2026)
|
||||
- Minor bugs fixed
|
||||
## 20260901.3 (01-09-2026)
|
||||
|
||||
@@ -127,5 +127,5 @@ slug: birdnet-go-dev
|
||||
udev: true
|
||||
url: https://github.com/alexbelgium/hassio-addons
|
||||
usb: true
|
||||
version: "20260901.4"
|
||||
version: "20260909.5"
|
||||
video: true
|
||||
|
||||
@@ -11,6 +11,15 @@
|
||||
# stamping) is written to the directory given as $1 so the Docker build can
|
||||
# compile it.
|
||||
#
|
||||
# With --check the script does not build anything: it performs the exact same
|
||||
# merge sequence, skips (instead of failing on) every conflicting PR, and prints
|
||||
# one "!!! CONFLICT pr=#N conflicts-with=... files=... " line per offender before
|
||||
# exiting 2. Use it to find conflicts *before* a build burns on them. This is a
|
||||
# different question from GitHub's `mergeable` field, which compares a PR against
|
||||
# its own base ref - for a stacked PR that base is another feature branch (often
|
||||
# stale, sometimes belonging to a closed PR), so GitHub can report CLEAN for a PR
|
||||
# that does not merge onto main at all.
|
||||
#
|
||||
# Environment:
|
||||
# BIRDNET_FORK owner/repo of the fork (default alexbelgium/birdnet-go)
|
||||
# BIRDNET_UPSTREAM owner/repo of the upstream (default tphakala/birdnet-go)
|
||||
@@ -19,7 +28,26 @@
|
||||
#
|
||||
set -euo pipefail
|
||||
|
||||
TARGET_DIR="${1:?usage: merge-prs.sh <target-dir>}"
|
||||
CHECK_ONLY="${MERGE_PRS_CHECK:-0}"
|
||||
TARGET_DIR=""
|
||||
while [ "$#" -gt 0 ]; do
|
||||
case "$1" in
|
||||
--check) CHECK_ONLY=1 ;;
|
||||
-*) echo "unknown option: $1" >&2; exit 64 ;;
|
||||
*)
|
||||
# Last-one-wins would silently clone into the wrong directory if a caller ever
|
||||
# appended an argument; the pre-flag script used "${1}", so refuse rather than
|
||||
# quietly change which operand counts.
|
||||
if [ -n "${TARGET_DIR}" ]; then
|
||||
echo "usage: merge-prs.sh [--check] <target-dir>" >&2
|
||||
exit 64
|
||||
fi
|
||||
TARGET_DIR="$1"
|
||||
;;
|
||||
esac
|
||||
shift
|
||||
done
|
||||
: "${TARGET_DIR:?usage: merge-prs.sh [--check] <target-dir>}"
|
||||
|
||||
FORK="${BIRDNET_FORK:-alexbelgium/birdnet-go}"
|
||||
UPSTREAM="${BIRDNET_UPSTREAM:-tphakala/birdnet-go}"
|
||||
@@ -33,6 +61,52 @@ GH_TOKEN="${GH_TOKEN:-${GITHUB_TOKEN:-}}"
|
||||
|
||||
log() { echo ">>> $*"; }
|
||||
|
||||
# Conflicting PRs collected in --check mode: "number|scope|files|title".
|
||||
conflicting=()
|
||||
|
||||
LOCKFILE="frontend/package-lock.json"
|
||||
|
||||
# The single place that decides whether a conflicted merge is still acceptable.
|
||||
# package-lock.json is generated content and stacked PRs can carry an older copy even when
|
||||
# their source changes merge cleanly, so keep the lockfile already assembled on the base side
|
||||
# — but only when it is the sole conflict. Any source conflict stays fatal.
|
||||
# Returns 0 when it resolved and committed such a merge, 1 when the conflict is real.
|
||||
# BOTH the real merge and the --check probe must go through here: when only the real merge
|
||||
# applied the policy, the probe called a PR "conflicts-with=main" that the build would have
|
||||
# merged fine, and printed the opposite remediation to the true one.
|
||||
resolve_sole_lockfile() {
|
||||
local dir="$1"
|
||||
local -a conflicted
|
||||
mapfile -t conflicted < <(git -C "${dir}" diff --name-only --diff-filter=U)
|
||||
if [ "${#conflicted[@]}" -ne 1 ] || [ "${conflicted[0]}" != "${LOCKFILE}" ]; then
|
||||
return 1
|
||||
fi
|
||||
log "Resolving generated ${LOCKFILE} conflict using the base tree"
|
||||
git -C "${dir}" checkout --ours -- "${LOCKFILE}" || return 1
|
||||
git -C "${dir}" add "${LOCKFILE}" || return 1
|
||||
git -C "${dir}" commit --no-edit > /dev/null || return 1
|
||||
}
|
||||
|
||||
# Does ${1} merge cleanly onto the pristine upstream-synced main? Probed in a
|
||||
# throwaway worktree so the accumulated tree is left untouched. Tells apart a PR
|
||||
# that is simply stale against main (fixable inside that PR's own branch) from
|
||||
# one that only clashes with another open PR (needs a cross-PR decision).
|
||||
merges_onto_main() {
|
||||
local sha="$1" tmpdir probe rc=0
|
||||
tmpdir="$(mktemp -d)"
|
||||
probe="${tmpdir}/probe"
|
||||
git worktree add --quiet --detach "${probe}" "${MAIN_SYNCED}"
|
||||
if ! git -C "${probe}" merge --no-edit --no-ff -m probe "${sha}" > /dev/null 2>&1; then
|
||||
# Same policy as the real merge, or this misclassifies a lockfile-only clash.
|
||||
resolve_sole_lockfile "${probe}" > /dev/null 2>&1 || rc=1
|
||||
fi
|
||||
git worktree remove --force "${probe}" > /dev/null 2>&1 || true
|
||||
# worktree remove only takes the child back; without this the mktemp parent is left behind
|
||||
# on every checked conflict.
|
||||
rmdir "${tmpdir}" > /dev/null 2>&1 || true
|
||||
return "${rc}"
|
||||
}
|
||||
|
||||
git config --global user.email "addon-builder@users.noreply.github.com"
|
||||
git config --global user.name "BirdNET-Go Addon Builder"
|
||||
git config --global advice.detachedHead false
|
||||
@@ -47,6 +121,7 @@ git remote add upstream "${UPSTREAM_URL}"
|
||||
git fetch --no-tags upstream main
|
||||
# --no-ff keeps an explicit sync commit; a no-op when main is already current.
|
||||
git merge --no-edit --no-ff upstream/main
|
||||
MAIN_SYNCED="$(git rev-parse HEAD)"
|
||||
|
||||
log "Querying open non-draft PRs from ${FORK}"
|
||||
auth_header=()
|
||||
@@ -79,27 +154,43 @@ for entry in "${prs[@]}"; do
|
||||
if ! git merge --no-edit --no-ff -m "Merge PR #${number}: ${title}" "${sha}"; then
|
||||
mapfile -t conflicted_files < <(git diff --name-only --diff-filter=U)
|
||||
|
||||
# package-lock.json is generated content and stacked PRs can carry an
|
||||
# older copy even when their source changes merge cleanly. Keep the
|
||||
# lockfile already assembled from upstream and earlier PRs, but only
|
||||
# when it is the sole conflict. Any source conflict remains fatal.
|
||||
if [ "${#conflicted_files[@]}" -eq 1 ] \
|
||||
&& [ "${conflicted_files[0]}" = "frontend/package-lock.json" ]; then
|
||||
log "Resolving generated frontend/package-lock.json conflict using the accumulated tree"
|
||||
git checkout --ours -- frontend/package-lock.json
|
||||
git add frontend/package-lock.json
|
||||
git commit --no-edit
|
||||
if resolve_sole_lockfile .; then
|
||||
: # generated lockfile only - the merge is committed and the build continues
|
||||
else
|
||||
echo "!!! Merge conflict while merging PR #${number} (${title})." >&2
|
||||
if [ "${#conflicted_files[@]}" -gt 0 ]; then
|
||||
printf '!!! Conflicting file: %s\n' "${conflicted_files[@]}" >&2
|
||||
fi
|
||||
echo "!!! Resolve the conflict in the fork or pause this PR, then rebuild." >&2
|
||||
git merge --abort || true
|
||||
|
||||
if [ "${CHECK_ONLY}" = "1" ]; then
|
||||
scope="accumulated"
|
||||
merges_onto_main "${sha}" || scope="main"
|
||||
conflicting+=("${number}|${scope}|${conflicted_files[*]:-}|${title}")
|
||||
log "check mode: skipping PR #${number}, continuing with the rest"
|
||||
continue
|
||||
fi
|
||||
|
||||
echo "!!! Resolve the conflict in the fork or pause this PR, then rebuild." >&2
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
done
|
||||
|
||||
if [ "${CHECK_ONLY}" = "1" ]; then
|
||||
if [ "${#conflicting[@]}" -eq 0 ]; then
|
||||
log "CHECK OK: every open non-draft PR merges into the combined build tree"
|
||||
exit 0
|
||||
fi
|
||||
echo "!!! CHECK FAILED: ${#conflicting[@]} PR(s) would break the add-on build" >&2
|
||||
for entry in "${conflicting[@]}"; do
|
||||
IFS='|' read -r number scope files title <<<"${entry}"
|
||||
echo "!!! CONFLICT pr=#${number} conflicts-with=${scope} files=${files} title=${title}" >&2
|
||||
done
|
||||
echo "!!! conflicts-with=main -> the PR is stale against main; merge main into its branch and resolve there." >&2
|
||||
echo "!!! conflicts-with=accumulated -> the PR only clashes with another open PR; decide which one owns the hunk." >&2
|
||||
exit 2
|
||||
fi
|
||||
|
||||
log "Merged HEAD: $(git rev-parse --short HEAD)"
|
||||
log "Source tree ready at ${TARGET_DIR}"
|
||||
|
||||
Reference in New Issue
Block a user