mirror of
https://github.com/okxlin/appstore.git
synced 2026-09-26 08:01:04 +00:00
Merge branch 'localApps' into renovate/linuxserver-speedtest-tracker-1.x
This commit is contained in:
@@ -378,3 +378,26 @@ wakapi
|
||||
# Reviewed single-service Renovate candidates (2026-08-01).
|
||||
codex2api
|
||||
opencode
|
||||
|
||||
# Reviewed digest-only Renovate candidates (2026-08-07).
|
||||
podfetch
|
||||
isrvd
|
||||
chromium-kasm
|
||||
filezilla-kasm
|
||||
firefox-kasm
|
||||
insomnia-kasm
|
||||
only-office-kasm
|
||||
postman-kasm
|
||||
signal-kasm
|
||||
slack-kasm
|
||||
vlc-kasm
|
||||
audacity-kasm
|
||||
blender-kasm
|
||||
brave-kasm
|
||||
gimp-kasm
|
||||
inkscape-kasm
|
||||
obsidian-kasm
|
||||
pinta-kasm
|
||||
remmina-kasm
|
||||
sublime-text-kasm
|
||||
vivaldi-kasm
|
||||
|
||||
@@ -811,6 +811,33 @@ class RenovateAppVersionTests(unittest.TestCase):
|
||||
self.assertIn("headRefName,headRepositoryOwner,isCrossRepository", reconcile)
|
||||
self.assertIn('.headRefName | startswith("selfhosted-renovate/")', reconcile)
|
||||
|
||||
def test_automerge_allows_exact_digest_only_updates_without_version_marker(self):
|
||||
workflow = (
|
||||
REPO_ROOT / ".github" / "workflows" / "renovate-automerge.yml"
|
||||
).read_text(encoding="utf-8")
|
||||
|
||||
self.assertIn("def digest_reference(image):", workflow)
|
||||
self.assertIn(
|
||||
're.fullmatch(r"([^@\\s]+)@sha256:([0-9a-fA-F]{64})", image)',
|
||||
workflow,
|
||||
)
|
||||
self.assertIn("old_digest[0] != new_digest[0]", workflow)
|
||||
self.assertIn("old_digest[1] == new_digest[1]", workflow)
|
||||
self.assertIn("filename_is_compose != previous_is_compose", workflow)
|
||||
self.assertIn("digest_only=true", workflow)
|
||||
self.assertIn("steps.shape.outputs.digest_only", workflow)
|
||||
self.assertIn("Digest-only image update; app-version marker is not required", workflow)
|
||||
self.assertIn("Update app version [skip ci]", workflow)
|
||||
|
||||
def test_reconcile_delegates_all_whitelisted_open_prs_to_automerge_gate(self):
|
||||
workflow = (
|
||||
REPO_ROOT / ".github" / "workflows" / "renovate-automerge-reconcile.yml"
|
||||
).read_text(encoding="utf-8")
|
||||
|
||||
self.assertNotIn('index("renovate-auto")', workflow)
|
||||
self.assertNotIn("Update app version [skip ci]", workflow)
|
||||
self.assertIn("gh workflow run renovate-automerge.yml", workflow)
|
||||
|
||||
def test_semantic_entrypoint_blocks_external_host_abort(self):
|
||||
entrypoint = REPO_ROOT / ".github" / "scripts" / "renovate-entrypoint.sh"
|
||||
with tempfile.TemporaryDirectory(prefix="renovate-entrypoint-test-") as tmp:
|
||||
|
||||
@@ -21,7 +21,7 @@ jobs:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
||||
|
||||
- name: Find eligible Renovate PRs missing automerge label
|
||||
- name: Find eligible Renovate PRs
|
||||
id: scan
|
||||
env:
|
||||
GH_TOKEN: ${{ github.token }}
|
||||
@@ -36,7 +36,7 @@ jobs:
|
||||
|
||||
mapfile -t pr_numbers < <(
|
||||
gh pr list --repo "$REPO" --state open --limit 100 \
|
||||
--json number,author,labels,isDraft,baseRefName,headRefName,headRepositoryOwner,isCrossRepository \
|
||||
--json number,author,isDraft,baseRefName,headRefName,headRepositoryOwner,isCrossRepository \
|
||||
--jq '.[]
|
||||
| select(
|
||||
.author.login == "app/renovate" or
|
||||
@@ -51,7 +51,6 @@ jobs:
|
||||
)
|
||||
| select(.isDraft | not)
|
||||
| select(.baseRefName == "localApps")
|
||||
| select(([.labels[].name] | index("renovate-auto")) | not)
|
||||
| .number'
|
||||
)
|
||||
|
||||
@@ -89,19 +88,6 @@ jobs:
|
||||
continue
|
||||
fi
|
||||
|
||||
pull_commits=$(gh api "repos/$REPO/pulls/$pr_number/commits" --paginate --jq '.[].commit.message' || true)
|
||||
base_sha=$(gh pr view "$pr_number" --repo "$REPO" --json baseRefOid --jq '.baseRefOid' || true)
|
||||
head_sha=$(gh pr view "$pr_number" --repo "$REPO" --json headRefOid --jq '.headRefOid' || true)
|
||||
compare_commits=''
|
||||
if [ -n "$base_sha" ] && [ -n "$head_sha" ]; then
|
||||
compare_commits=$(gh api "repos/$REPO/compare/$base_sha...$head_sha" --jq '.commits[].commit.message' || true)
|
||||
fi
|
||||
|
||||
all_commits="$(printf '%s\n%s\n' "$pull_commits" "$compare_commits")"
|
||||
if ! echo "$all_commits" | grep -Fq 'Update app version [skip ci]'; then
|
||||
continue
|
||||
fi
|
||||
|
||||
eligible+=("$pr_number")
|
||||
done
|
||||
|
||||
|
||||
@@ -159,12 +159,21 @@ jobs:
|
||||
reject(f"compose must contain exactly one service: {path}")
|
||||
return data, services
|
||||
|
||||
def digest_reference(image):
|
||||
if not isinstance(image, str):
|
||||
return None
|
||||
match = re.fullmatch(r"([^@\s]+)@sha256:([0-9a-fA-F]{64})", image)
|
||||
if match is None:
|
||||
return None
|
||||
return match.group(1), match.group(2).lower()
|
||||
|
||||
try:
|
||||
with open("/tmp/renovate-pr-files.json", encoding="utf-8") as fh:
|
||||
files = json.load(fh)
|
||||
|
||||
apps = set()
|
||||
compose_files = []
|
||||
digest_only = True
|
||||
|
||||
for file_info in files:
|
||||
filename = file_info["filename"]
|
||||
@@ -178,8 +187,14 @@ jobs:
|
||||
reject(f"changed file outside apps/: {path}")
|
||||
apps.add(match.group(1))
|
||||
|
||||
if filename.endswith("/docker-compose.yml") or (previous and previous.endswith("/docker-compose.yml")):
|
||||
filename_is_compose = filename.endswith("/docker-compose.yml")
|
||||
previous_is_compose = bool(previous and previous.endswith("/docker-compose.yml"))
|
||||
if filename_is_compose or previous_is_compose:
|
||||
compose_files.append((previous or filename, filename))
|
||||
if previous and filename_is_compose != previous_is_compose:
|
||||
digest_only = False
|
||||
else:
|
||||
digest_only = False
|
||||
|
||||
if len(apps) != 1:
|
||||
reject(f"PR must affect exactly one app, got {', '.join(sorted(apps))}")
|
||||
@@ -205,6 +220,16 @@ jobs:
|
||||
if not old_image or not new_image or old_image == new_image:
|
||||
reject(f"compose service image must change: {new_resolved_path}")
|
||||
|
||||
old_digest = digest_reference(old_image)
|
||||
new_digest = digest_reference(new_image)
|
||||
if (
|
||||
old_digest is None
|
||||
or new_digest is None
|
||||
or old_digest[0] != new_digest[0]
|
||||
or old_digest[1] == new_digest[1]
|
||||
):
|
||||
digest_only = False
|
||||
|
||||
old_data.pop("version", None)
|
||||
new_data.pop("version", None)
|
||||
for service in old_services.values():
|
||||
@@ -221,6 +246,11 @@ jobs:
|
||||
checked += 1
|
||||
|
||||
print(f"single-service image-only update verified for {app_name} across {checked} compose file(s)")
|
||||
with open(os.environ["GITHUB_OUTPUT"], "a", encoding="utf-8") as output:
|
||||
if digest_only:
|
||||
output.write("digest_only=true\n")
|
||||
else:
|
||||
output.write("digest_only=false\n")
|
||||
except GateReject as exc:
|
||||
print(str(exc), file=sys.stderr)
|
||||
sys.exit(42)
|
||||
@@ -260,6 +290,12 @@ jobs:
|
||||
env:
|
||||
GH_TOKEN: ${{ github.token }}
|
||||
run: |
|
||||
if [ "${{ steps.shape.outputs.digest_only }}" = "true" ]; then
|
||||
echo "Digest-only image update; app-version marker is not required"
|
||||
echo "found=true" >> "$GITHUB_OUTPUT"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
PR_NUMBER="${{ github.event.pull_request.number || inputs.pr_number }}"
|
||||
REPO="${{ github.repository }}"
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
services:
|
||||
atvloadly:
|
||||
image: "bitxeno/atvloadly:v0.4.6"
|
||||
image: "bitxeno/atvloadly:v0.4.7"
|
||||
container_name: ${CONTAINER_NAME}
|
||||
restart: always
|
||||
networks:
|
||||
@@ -1,6 +1,6 @@
|
||||
services:
|
||||
audacity-kasm:
|
||||
image: "kasmweb/audacity:1.19.0-rolling-weekly@sha256:f2707362ce735267332cc434c78d23d34090c5d7a97d03d5ea4ca053bc268bb1"
|
||||
image: "kasmweb/audacity:1.19.0-rolling-weekly@sha256:64957edcd3516dfc01a0e9bf602ec735d2e07de111a8d0358e9738195927cade"
|
||||
container_name: ${CONTAINER_NAME}
|
||||
restart: unless-stopped
|
||||
networks:
|
||||
|
||||
+1
-1
@@ -3,7 +3,7 @@ networks:
|
||||
external: true
|
||||
services:
|
||||
babybuddy:
|
||||
image: "linuxserver/babybuddy:2.9.2"
|
||||
image: "linuxserver/babybuddy:2.10.0"
|
||||
container_name: ${CONTAINER_NAME}
|
||||
restart: always
|
||||
networks:
|
||||
+1
-1
@@ -3,7 +3,7 @@ networks:
|
||||
external: true
|
||||
services:
|
||||
blade-of-agony:
|
||||
image: "linuxserver/blade-of-agony:3.1.20260730"
|
||||
image: "linuxserver/blade-of-agony:3.1.20260807"
|
||||
container_name: ${CONTAINER_NAME}
|
||||
restart: always
|
||||
networks:
|
||||
@@ -1,6 +1,6 @@
|
||||
services:
|
||||
blender-kasm:
|
||||
image: "kasmweb/blender:1.19.0-rolling-weekly@sha256:c92e7e4ee6074c5aeb8096862d0d2910bfcbceec87038c9d70c3a63b9fdb89d8"
|
||||
image: "kasmweb/blender:1.19.0-rolling-weekly@sha256:a80430080504eacd1092842ea5fc4627b945406bbdab1f85c3e098ef4a048b0d"
|
||||
container_name: ${CONTAINER_NAME}
|
||||
restart: unless-stopped
|
||||
networks:
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
services:
|
||||
brave-kasm:
|
||||
image: "kasmweb/brave:1.19.0-rolling-weekly@sha256:a6683fba210f11b2bb293ccf9c1531e8a52a4070c728b4c31c14db527b1b6beb"
|
||||
image: "kasmweb/brave:1.19.0-rolling-weekly@sha256:646e7849a56109990faa742b91595c2eda970d9b9c8472c08432c0036ae7029a"
|
||||
container_name: ${CONTAINER_NAME}
|
||||
restart: unless-stopped
|
||||
networks:
|
||||
|
||||
+1
-1
@@ -3,7 +3,7 @@ networks:
|
||||
external: true
|
||||
services:
|
||||
brave:
|
||||
image: "linuxserver/brave:1.93.129"
|
||||
image: "linuxserver/brave:1.93.132"
|
||||
container_name: ${CONTAINER_NAME}
|
||||
restart: always
|
||||
networks:
|
||||
+1
-1
@@ -3,7 +3,7 @@ networks:
|
||||
external: true
|
||||
services:
|
||||
calibre:
|
||||
image: "linuxserver/calibre:9.12.0"
|
||||
image: "linuxserver/calibre:9.13.0"
|
||||
container_name: ${CONTAINER_NAME}
|
||||
restart: always
|
||||
networks:
|
||||
@@ -1,6 +1,6 @@
|
||||
services:
|
||||
chromium-kasm:
|
||||
image: "kasmweb/chromium:1.19.0-rolling-weekly@sha256:cda6f157fa4309443f728b42c905533ca4d55b5747302258aace2e06db071f72"
|
||||
image: "kasmweb/chromium:1.19.0-rolling-weekly@sha256:60f34130c6b6485755a3ad37f4e2ac110723c55c090df78cbc60814b6f6c2b45"
|
||||
container_name: ${CONTAINER_NAME}
|
||||
restart: unless-stopped
|
||||
networks:
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
services:
|
||||
claper:
|
||||
image: "ghcr.io/claperco/claper:2.5.1"
|
||||
image: "ghcr.io/claperco/claper:3.0.0@sha256:ebdd932616623d3dba6dcf5ea5d967380db88d507a719eb8c00dbf5d29a6d9c8"
|
||||
container_name: ${CONTAINER_NAME}
|
||||
restart: always
|
||||
networks:
|
||||
@@ -1,6 +1,6 @@
|
||||
services:
|
||||
codex2api:
|
||||
image: "ghcr.io/james-6-23/codex2api:2.7.0@sha256:68e220e9dd981b5dc680cc3ba059cfb3697e2a3a5626b6a6306afb11e6fd6b43"
|
||||
image: "ghcr.io/james-6-23/codex2api:2.7.1@sha256:cc16f8af03e96d146b09950e0fb3e43e0afbc66dcb7c329cbbbec02e95edc582"
|
||||
container_name: ${CONTAINER_NAME}
|
||||
restart: always
|
||||
security_opt:
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
services:
|
||||
cpa-manager-plus:
|
||||
image: "seakee/cpa-manager-plus:v1.11.11"
|
||||
image: "seakee/cpa-manager-plus:v1.11.12"
|
||||
container_name: ${CONTAINER_NAME}
|
||||
ports:
|
||||
- "${PANEL_APP_PORT_HTTP}:18317"
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
services:
|
||||
cpa-usage-keeper:
|
||||
image: ghcr.io/willxup/cpa-usage-keeper:v1.14.2
|
||||
image: ghcr.io/willxup/cpa-usage-keeper:v1.14.3
|
||||
container_name: ${CONTAINER_NAME}
|
||||
ports:
|
||||
- ${PANEL_APP_PORT_HTTP}:8080
|
||||
@@ -19,7 +19,7 @@ services:
|
||||
timeout: 10s
|
||||
retries: 3
|
||||
start_period: 40s
|
||||
image: lissy93/dashy:4.5.5
|
||||
image: lissy93/dashy:4.5.6
|
||||
labels:
|
||||
createdBy: "Apps"
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
services:
|
||||
dbx:
|
||||
image: "t8y2/dbx:0.5.75"
|
||||
image: "t8y2/dbx:0.5.77"
|
||||
container_name: ${CONTAINER_NAME}
|
||||
ports:
|
||||
- "${PANEL_APP_PORT_HTTP}:4224"
|
||||
@@ -7,7 +7,7 @@ services:
|
||||
ports:
|
||||
- "${PANEL_APP_PORT_HTTP}:1188"
|
||||
command: ["/app/deeplx", "-token", "${TOKEN_VAULE}"]
|
||||
image: missuo/deeplx:v1.2.3
|
||||
image: missuo/deeplx:v1.2.4
|
||||
labels:
|
||||
createdBy: "Apps"
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
services:
|
||||
dragonfly:
|
||||
image: "docker.dragonflydb.io/dragonflydb/dragonfly:v1.40.0"
|
||||
image: "docker.dragonflydb.io/dragonflydb/dragonfly:v1.40.1"
|
||||
container_name: ${CONTAINER_NAME}
|
||||
restart: unless-stopped
|
||||
networks:
|
||||
+1
-1
@@ -6,7 +6,7 @@ services:
|
||||
- 1panel-network
|
||||
ports:
|
||||
- "${PANEL_APP_PORT_HTTP}:80"
|
||||
image: vectorim/element-web:v1.12.24
|
||||
image: vectorim/element-web:v1.12.25
|
||||
labels:
|
||||
createdBy: "Apps"
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
services:
|
||||
filerise:
|
||||
image: "error311/filerise-docker:v3.25.0"
|
||||
image: "error311/filerise-docker:v3.26.1"
|
||||
container_name: ${CONTAINER_NAME}
|
||||
restart: unless-stopped
|
||||
networks:
|
||||
@@ -1,6 +1,6 @@
|
||||
services:
|
||||
filezilla-kasm:
|
||||
image: "kasmweb/filezilla:1.19.0-rolling-weekly@sha256:3a4831da8d510417ca7606942d8ae9f6fb48a74d010c6f6107c5798d7976acb8"
|
||||
image: "kasmweb/filezilla:1.19.0-rolling-weekly@sha256:a8a62b7728984357baf9af1d197032c496753175df1e94491ff0e7316b143ae7"
|
||||
container_name: ${CONTAINER_NAME}
|
||||
restart: unless-stopped
|
||||
networks:
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
services:
|
||||
firefox-kasm:
|
||||
image: "kasmweb/firefox:1.19.0-rolling-weekly@sha256:1f6c0d62afee626780134044cbaad6b6442562f0bc3c3f759cb5d3f8437962b2"
|
||||
image: "kasmweb/firefox:1.19.0-rolling-weekly@sha256:a0d12f54ab2a51f2aa70adbe14b68ad8cefdbbb2d71fb41bbc0cbfdfa1e902e4"
|
||||
container_name: ${CONTAINER_NAME}
|
||||
restart: unless-stopped
|
||||
networks:
|
||||
|
||||
+1
-1
@@ -3,7 +3,7 @@ networks:
|
||||
external: true
|
||||
services:
|
||||
flexget:
|
||||
image: "linuxserver/flexget:3.20.0"
|
||||
image: "linuxserver/flexget:3.20.1"
|
||||
container_name: ${CONTAINER_NAME}
|
||||
restart: always
|
||||
networks:
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user