diff --git a/birdnet-pi/Dockerfile b/birdnet-pi/Dockerfile index 9acd339dc..9ebcdf178 100644 --- a/birdnet-pi/Dockerfile +++ b/birdnet-pi/Dockerfile @@ -36,6 +36,8 @@ ADD "https://raw.githubusercontent.com/alexbelgium/hassio-addons/master/.templat ARG CONFIGLOCATION="/config" RUN chmod 744 /ha_lsio.sh && if grep -qr "lsio" /etc; then /ha_lsio.sh "$CONFIGLOCATION"; fi && rm /ha_lsio.sh +COPY merge_open_prs.sh /merge_open_prs.sh + SHELL ["/bin/bash", "-o", "pipefail", "-c"] # hadolint ignore=DL3015,SC2016 RUN \ @@ -70,6 +72,11 @@ RUN \ # Download installer curl -f -L -s -S "https://raw.githubusercontent.com/alexbelgium/BirdNET-Pi/main/newinstaller.sh" -o /newinstaller.sh && \ chmod 777 /newinstaller.sh && \ + chmod +x /merge_open_prs.sh && \ + /merge_open_prs.sh && \ + chown -R 1000:1000 $HOME && \ + chmod 777 $HOME/BirdNET-Pi/scripts/*.sh && \ + sed -i "/CURRENT_TIMEZONE/s/$/ || true/" $HOME/BirdNET-Pi/scripts/install_birdnet.sh && \ \ # Use installer to modify other scripts ####################################### @@ -86,18 +93,9 @@ RUN \ ################## # Use my repository sed -i "s|Nachtzuster|alexbelgium|g" /newinstaller.sh && \ - # Install open PR - sed -i '/^git clone/a for pr in $(curl -s https://api.github.com/repos/alexbelgium/BirdNET-Pi/pulls?state=open | jq -r ".[].number"); do echo "Merging PR #$pr" && git fetch origin pull/$pr/merge:pr-$pr && git merge --no-ff -m "Merge PR #$pr" pr-$pr || { echo "Skipping PR #$pr"; git merge --abort || true; }; done' /newinstaller.sh && \ - # Avoid rebooting at end of installation + sed -i '/git clone -b \$branch --depth=1/d' /newinstaller.sh && \ sed -i "/reboot/d" /newinstaller.sh && \ - # Use apt-get as without user action sed -i "s|apt |apt-get |g" /newinstaller.sh && \ - # Ensure chmod - sed -i "/git clone/a chown -R 1000:1000 $HOME" /newinstaller.sh && \ - sed -i "/git clone/a chmod 777 \$HOME/BirdNET-Pi/scripts/*.sh" /newinstaller.sh && \ - # Disable datetimectl - sed -i '/git clone/a sed -i "/CURRENT_TIMEZONE/s/$/ || true/" $HOME/BirdNET-Pi/scripts/install_birdnet.sh' /newinstaller.sh && \ - # Remove all instances of sudo from the newinstaller sed -i -e "s|== 0|== 7|g" -e "s|sudo -n true|true|g" -e "s|sudo -K|true|g" /newinstaller.sh && \ \ # Execute installer diff --git a/birdnet-pi/merge_open_prs.sh b/birdnet-pi/merge_open_prs.sh new file mode 100644 index 000000000..b6e81cc20 --- /dev/null +++ b/birdnet-pi/merge_open_prs.sh @@ -0,0 +1,81 @@ +#!/bin/bash +set -e +update=yes +if [[ "$update" = "yes" ]]; then + repo="https://github.com/alexbelgium/BirdNET-Pi.git" + # repo="https://github.com/Nachtzuster/BirdNET-Pi.git" + branch="main" + echo "Update with $branch of $repo" + + temp_dir="$(mktemp -d)" + target_dir="/home/${USER}/BirdNET-Pi" + + # Parse owner/repo from the URL + _url_no_git="${repo%.git}" + _path="${_url_no_git#https://github.com/}" + owner="${_path%%/*}" + reponame="${_path#*/}" + + # --- helper: list open PRs via GitHub API (unauthenticated) ---------------- + list_open_prs() { + # prints PR numbers, one per line; returns non-zero if none or curl missing + command -v curl >/dev/null 2>&1 || return 1 + local page=1 per_page=100 out + local -a all=() chunk=() + while :; do + out="$(curl -fsSL "https://api.github.com/repos/${owner}/${reponame}/pulls?state=open&per_page=${per_page}&page=${page}")" || break + [[ -z "$out" || "$out" == "[]" ]] && break + if command -v jq >/dev/null 2>&1; then + mapfile -t chunk < <(printf '%s' "$out" | jq -r '.[] | select(.draft == false) | .number') + else + # Fallback JSON scraping if jq is unavailable + mapfile -t chunk < <(printf '%s' "$out" | grep -o '"number":[[:space:]]*[0-9]\+' | grep -o '[0-9]\+') + fi + ((${#chunk[@]}==0)) && break + all+=("${chunk[@]}") + ((${#chunk[@]} < per_page)) && break + ((page++)) + done + ((${#all[@]}==0)) && return 1 + printf '%s\n' "${all[@]}" + } + + # --- clone base ------------------------------------------------------------ + git clone --quiet --branch "$branch" "$repo" "$temp_dir" + pushd "$temp_dir" >/dev/null + git fetch --quiet origin + git config user.name "Local PR Aggregator" + git config user.email "local@example.invalid" + git checkout -B with-open-prs "origin/${branch}" + + # --- fetch & merge only OPEN PRs ------------------------------------------- + mapfile -t prs < <(list_open_prs || true) + if ((${#prs[@]})); then + # Sort numerically (oldest first) + IFS=$'\n' prs=($(sort -n <<<"${prs[*]}")); unset IFS + echo "Open PR(s): ${prs[*]}" + + for pr in "${prs[@]}"; do + echo "Fetching PR #${pr}…" + if git fetch --quiet origin "pull/${pr}/head:pr-${pr}"; then + echo "Merging PR #${pr} into with-open-prs…" + if git merge --no-ff -X theirs --no-edit "pr-${pr}"; then + echo "✓ merged PR #${pr}" + else + echo "! Conflict merging PR #${pr}; aborting and skipping." + git merge --abort || true + git reset --hard + git checkout with-open-prs + fi + else + echo "! Could not fetch refs for PR #${pr}; skipping." + fi + done + else + echo "No open PRs detected (API unavailable or none open)." + fi + + popd >/dev/null + rm -rf "$target_dir" + mv "$temp_dir" "$target_dir" +fi