36 Commits

Author SHA1 Message Date
baacb09d1b chore: Update fastapi to 0.141.1 2026-07-30 08:14:14 +00:00
copilotcoder
6db9232f1f ci: retrigger workflow run
Some checks failed
CICD / Build and Push CICD Images (push) Successful in 18m37s
CICD / Build CICD Image Failure Postmortem (push) Has been skipped
CICD / Source Checks (push) Successful in 2m29s
CICD / Source Lanes Failure Postmortem (push) Has been skipped
CICD / Build Tester Images (push) Successful in 4m29s
CICD / Dependency Audits (Informational) (push) Successful in 11m12s
CICD / CICD Tests Complete (push) Successful in 6s
CICD / Build Release Images (push) Failing after 17m29s
CICD / Production Images Complete (push) Failing after 9s
CICD / Runtime Black-Box Integration Tests (push) Has been skipped
CICD / Production Image Failures Postmortem (push) Successful in 17s
CICD / End-to-End Tests (push) Has been skipped
CICD / Integration Tests Failure Postmortem (push) Has been skipped
CICD / Promote Staging Images To Release (push) Has been skipped
CICD / E2E Tests Failure Postmortem (push) Has been skipped
Renovate Dependency Updates / Renovate Dependencies (push) Successful in 5m32s
2026-07-23 07:59:49 -04:00
copilotcoder
a93bd3c274 fix: continue node tarball case lines
Some checks failed
CICD / Build and Push CICD Images (push) Failing after 43m19s
Renovate Dependency Updates / Renovate Dependencies (push) Successful in 3m52s
CICD / Build CICD Image Failure Postmortem (push) Has been cancelled
CICD / Source Checks (push) Has been cancelled
CICD / Dependency Audits (Informational) (push) Has been cancelled
CICD / CICD Tests Complete (push) Has been cancelled
CICD / Build Release Images (push) Has been cancelled
CICD / Build Tester Images (push) Has been cancelled
CICD / Production Images Complete (push) Has been cancelled
CICD / Production Image Failures Postmortem (push) Has been cancelled
CICD / Source Lanes Failure Postmortem (push) Has been cancelled
CICD / Runtime Black-Box Integration Tests (push) Has been cancelled
CICD / Integration Tests Failure Postmortem (push) Has been cancelled
CICD / End-to-End Tests (push) Has been cancelled
CICD / E2E Tests Failure Postmortem (push) Has been cancelled
CICD / Promote Staging Images To Release (push) Has been cancelled
2026-07-22 23:39:45 -04:00
copilotcoder
ae0c0ac857 fix: install node from upstream tarball
Some checks failed
CICD / Build and Push CICD Images (push) Failing after 1m39s
CICD / Source Checks (push) Has been skipped
CICD / Dependency Audits (Informational) (push) Has been skipped
CICD / Build Tester Images (push) Has been skipped
CICD / Build Release Images (push) Has been skipped
CICD / Build CICD Image Failure Postmortem (push) Successful in 12s
CICD / CICD Tests Complete (push) Failing after 7s
CICD / Production Images Complete (push) Failing after 6s
CICD / Runtime Black-Box Integration Tests (push) Has been skipped
CICD / Production Image Failures Postmortem (push) Has been skipped
CICD / End-to-End Tests (push) Has been skipped
CICD / Source Lanes Failure Postmortem (push) Has been skipped
CICD / Integration Tests Failure Postmortem (push) Has been skipped
CICD / E2E Tests Failure Postmortem (push) Has been skipped
CICD / Promote Staging Images To Release (push) Has been skipped
2026-07-22 23:06:48 -04:00
copilotcoder
a6180a187d fix: install npm in cicd base image
Some checks failed
CICD / Build and Push CICD Images (push) Failing after 11m46s
CICD / Source Checks (push) Has been skipped
CICD / Dependency Audits (Informational) (push) Has been skipped
CICD / Build Release Images (push) Has been skipped
CICD / Build Tester Images (push) Has been skipped
CICD / Build CICD Image Failure Postmortem (push) Successful in 18s
CICD / CICD Tests Complete (push) Failing after 55s
CICD / Production Images Complete (push) Failing after 57s
CICD / Runtime Black-Box Integration Tests (push) Has been skipped
CICD / End-to-End Tests (push) Has been skipped
CICD / Production Image Failures Postmortem (push) Has been skipped
CICD / Integration Tests Failure Postmortem (push) Has been skipped
CICD / Source Lanes Failure Postmortem (push) Has been skipped
CICD / Promote Staging Images To Release (push) Has been skipped
CICD / E2E Tests Failure Postmortem (push) Has been skipped
2026-07-22 22:37:31 -04:00
copilotcoder
28bfd275e0 chore: refresh gitea hook status
Some checks failed
CICD / Build and Push CICD Images (push) Failing after 24m7s
CICD / Source Checks (push) Has been skipped
CICD / Dependency Audits (Informational) (push) Has been skipped
CICD / Build Release Images (push) Has been skipped
CICD / Build Tester Images (push) Has been skipped
CICD / Production Images Complete (push) Failing after 4s
CICD / Runtime Black-Box Integration Tests (push) Has been skipped
CICD / Production Image Failures Postmortem (push) Has been skipped
CICD / End-to-End Tests (push) Has been skipped
CICD / Build CICD Image Failure Postmortem (push) Successful in 9s
CICD / Source Lanes Failure Postmortem (push) Has been skipped
CICD / Integration Tests Failure Postmortem (push) Has been skipped
CICD / E2E Tests Failure Postmortem (push) Has been skipped
CICD / Promote Staging Images To Release (push) Has been skipped
CICD / CICD Tests Complete (push) Failing after 46s
2026-07-22 19:31:25 -04:00
copilotcoder
06e5b2e6c2 Getting ubuntu version in the right place.
Signed-off-by: copilotcoder <copilotcoder@darkhelm.org>
2026-07-22 19:26:18 -04:00
copilotcoder
f937f6d3e5 Fixing handling of python version number.
Some checks failed
CICD / Build and Push CICD Images (push) Failing after 12m14s
CICD / Source Checks (push) Has been skipped
CICD / Dependency Audits (Informational) (push) Has been skipped
CICD / Build Release Images (push) Has been skipped
CICD / Build Tester Images (push) Has been skipped
CICD / Build CICD Image Failure Postmortem (push) Successful in 16s
CICD / CICD Tests Complete (push) Failing after 38s
CICD / Production Images Complete (push) Failing after 46s
CICD / Production Image Failures Postmortem (push) Has been skipped
CICD / Runtime Black-Box Integration Tests (push) Has been skipped
CICD / End-to-End Tests (push) Has been skipped
CICD / Source Lanes Failure Postmortem (push) Has been skipped
CICD / Integration Tests Failure Postmortem (push) Has been skipped
CICD / E2E Tests Failure Postmortem (push) Has been skipped
CICD / Promote Staging Images To Release (push) Has been skipped
Signed-off-by: copilotcoder <copilotcoder@darkhelm.org>
2026-07-22 17:58:23 -04:00
copilotcoder
ab0ec0887d Getting rid of repeated version numbers.
Some checks failed
CICD / Build and Push CICD Images (push) Failing after 39s
CICD / Source Checks (push) Has been skipped
CICD / Dependency Audits (Informational) (push) Has been skipped
CICD / Build Release Images (push) Has been skipped
CICD / Build Tester Images (push) Has been skipped
CICD / CICD Tests Complete (push) Failing after 7s
CICD / Build CICD Image Failure Postmortem (push) Successful in 14s
CICD / Production Images Complete (push) Failing after 6s
CICD / Runtime Black-Box Integration Tests (push) Has been skipped
CICD / End-to-End Tests (push) Has been skipped
CICD / Production Image Failures Postmortem (push) Has been skipped
CICD / Source Lanes Failure Postmortem (push) Has been skipped
CICD / Promote Staging Images To Release (push) Has been skipped
CICD / Integration Tests Failure Postmortem (push) Has been skipped
CICD / E2E Tests Failure Postmortem (push) Has been skipped
Signed-off-by: copilotcoder <copilotcoder@darkhelm.org>
2026-07-22 17:51:22 -04:00
copilotcoder
3db1b0676f chore(ci): centralize runtime and image version constants
Some checks failed
CICD / Build CICD Image Failure Postmortem (push) Has been cancelled
CICD / Source Checks (push) Has been cancelled
CICD / Dependency Audits (Informational) (push) Has been cancelled
CICD / CICD Tests Complete (push) Has been cancelled
CICD / Build Release Images (push) Has been cancelled
CICD / Build Tester Images (push) Has been cancelled
CICD / Production Images Complete (push) Has been cancelled
CICD / Production Image Failures Postmortem (push) Has been cancelled
CICD / Source Lanes Failure Postmortem (push) Has been cancelled
CICD / Runtime Black-Box Integration Tests (push) Has been cancelled
CICD / Integration Tests Failure Postmortem (push) Has been cancelled
CICD / End-to-End Tests (push) Has been cancelled
CICD / E2E Tests Failure Postmortem (push) Has been cancelled
CICD / Promote Staging Images To Release (push) Has been cancelled
CICD / Build and Push CICD Images (push) Has been cancelled
2026-07-22 17:38:34 -04:00
copilotcoder
cd19d06680 ci(e2e): align Playwright runtime image to 1.61.1
Some checks failed
CICD / Production Images Complete (push) Blocked by required conditions
CICD / Production Image Failures Postmortem (push) Blocked by required conditions
CICD / Runtime Black-Box Integration Tests (push) Blocked by required conditions
CICD / Integration Tests Failure Postmortem (push) Blocked by required conditions
CICD / End-to-End Tests (push) Blocked by required conditions
CICD / E2E Tests Failure Postmortem (push) Blocked by required conditions
CICD / Promote Staging Images To Release (push) Blocked by required conditions
CICD / Build and Push CICD Images (push) Successful in 37m39s
CICD / Build CICD Image Failure Postmortem (push) Has been skipped
CICD / Dependency Audits (Informational) (push) Successful in 4m13s
CICD / Source Checks (push) Successful in 7m34s
CICD / Source Lanes Failure Postmortem (push) Has been skipped
CICD / CICD Tests Complete (push) Successful in 5s
CICD / Build Release Images (push) Successful in 4m37s
CICD / Build Tester Images (push) Has been cancelled
2026-07-22 16:36:43 -04:00
copilotcoder
f71025ee1c fix(frontend-image): use repo-pinned yarn for immutable install
Some checks failed
CICD / Build and Push CICD Images (push) Successful in 12m19s
CICD / Build CICD Image Failure Postmortem (push) Has been skipped
CICD / Source Checks (push) Successful in 3m42s
CICD / Source Lanes Failure Postmortem (push) Has been skipped
CICD / Dependency Audits (Informational) (push) Successful in 8m20s
CICD / CICD Tests Complete (push) Successful in 5s
CICD / Build Tester Images (push) Successful in 2m54s
CICD / Build Release Images (push) Successful in 11m7s
CICD / Production Image Failures Postmortem (push) Has been skipped
CICD / Production Images Complete (push) Successful in 4s
CICD / Runtime Black-Box Integration Tests (push) Successful in 1m17s
CICD / Integration Tests Failure Postmortem (push) Has been skipped
CICD / End-to-End Tests (push) Failing after 5m14s
CICD / Promote Staging Images To Release (push) Has been skipped
CICD / E2E Tests Failure Postmortem (push) Successful in 9s
2026-07-22 14:26:11 -04:00
copilotcoder
e61b70c4a0 fix(frontend): restore TS6-compatible lint and type checks
Some checks failed
CICD / Build and Push CICD Images (push) Successful in 37m29s
CICD / Build CICD Image Failure Postmortem (push) Has been skipped
CICD / Source Checks (push) Successful in 8m58s
CICD / Dependency Audits (Informational) (push) Successful in 1m26s
CICD / Source Lanes Failure Postmortem (push) Has been skipped
CICD / CICD Tests Complete (push) Successful in 5s
CICD / Build Release Images (push) Failing after 5m45s
CICD / Production Images Complete (push) Has been cancelled
CICD / Production Image Failures Postmortem (push) Has been cancelled
CICD / Runtime Black-Box Integration Tests (push) Has been cancelled
CICD / Integration Tests Failure Postmortem (push) Has been cancelled
CICD / End-to-End Tests (push) Has been cancelled
CICD / E2E Tests Failure Postmortem (push) Has been cancelled
CICD / Promote Staging Images To Release (push) Has been cancelled
CICD / Build Tester Images (push) Has started running
2026-07-22 13:28:30 -04:00
copilotcoder
6c98ee7018 Trying to get all of the version updates in one go.
Some checks failed
CICD / Build and Push CICD Images (push) Successful in 25m14s
CICD / Build CICD Image Failure Postmortem (push) Has been skipped
CICD / Dependency Audits (Informational) (push) Successful in 4m45s
CICD / Source Checks (push) Failing after 13m49s
CICD / Build Release Images (push) Has been skipped
CICD / Build Tester Images (push) Has been skipped
CICD / CICD Tests Complete (push) Failing after 8s
CICD / Production Images Complete (push) Failing after 8s
CICD / Runtime Black-Box Integration Tests (push) Has been skipped
CICD / End-to-End Tests (push) Has been skipped
CICD / Production Image Failures Postmortem (push) Has been skipped
CICD / Integration Tests Failure Postmortem (push) Has been skipped
CICD / Source Lanes Failure Postmortem (push) Successful in 17s
CICD / E2E Tests Failure Postmortem (push) Has been skipped
CICD / Promote Staging Images To Release (push) Has been skipped
Signed-off-by: copilotcoder <copilotcoder@darkhelm.org>
2026-07-22 11:10:05 -04:00
copilotcoder
87f977280c fix(frontend): align zod v4 typings and defaults
Some checks failed
CICD / Build CICD Image Failure Postmortem (push) Has been cancelled
CICD / Build and Push CICD Images (push) Has been cancelled
CICD / Source Checks (push) Has been cancelled
CICD / Dependency Audits (Informational) (push) Has been cancelled
CICD / CICD Tests Complete (push) Has been cancelled
CICD / Build Release Images (push) Has been cancelled
CICD / Build Tester Images (push) Has been cancelled
CICD / Production Images Complete (push) Has been cancelled
CICD / Production Image Failures Postmortem (push) Has been cancelled
CICD / Source Lanes Failure Postmortem (push) Has been cancelled
CICD / Runtime Black-Box Integration Tests (push) Has been cancelled
CICD / Integration Tests Failure Postmortem (push) Has been cancelled
CICD / End-to-End Tests (push) Has been cancelled
CICD / E2E Tests Failure Postmortem (push) Has been cancelled
CICD / Promote Staging Images To Release (push) Has been cancelled
2026-07-22 10:59:55 -04:00
copilotcoder
ff53dec2c2 Trying to make the build and push base image for CICD work.
Some checks failed
CICD / Build and Push CICD Images (push) Successful in 1h7m14s
CICD / Build CICD Image Failure Postmortem (push) Has been skipped
CICD / Source Checks (push) Failing after 22m43s
CICD / Build Release Images (push) Has been skipped
CICD / Build Tester Images (push) Has been skipped
CICD / Production Image Failures Postmortem (push) Has been skipped
CICD / Source Lanes Failure Postmortem (push) Successful in 17s
CICD / Production Images Complete (push) Failing after 31s
CICD / Runtime Black-Box Integration Tests (push) Has been skipped
CICD / End-to-End Tests (push) Has been skipped
CICD / Integration Tests Failure Postmortem (push) Has been skipped
CICD / E2E Tests Failure Postmortem (push) Has been skipped
CICD / Promote Staging Images To Release (push) Has been skipped
CICD / Dependency Audits (Informational) (push) Successful in 31m23s
CICD / CICD Tests Complete (push) Failing after 9s
Signed-off-by: copilotcoder <copilotcoder@darkhelm.org>
2026-07-22 07:52:25 -04:00
2bb73a3f6b chore: Update zod to 4.4.3 (#109)
Some checks failed
CICD / Build and Push CICD Images (push) Failing after 2m8s
CICD / Source Checks (push) Has been skipped
CICD / Dependency Audits (Informational) (push) Has been skipped
CICD / Build Release Images (push) Has been skipped
CICD / Build Tester Images (push) Has been skipped
CICD / Build CICD Image Failure Postmortem (push) Successful in 11s
CICD / Production Image Failures Postmortem (push) Has been skipped
CICD / Source Lanes Failure Postmortem (push) Has been skipped
CICD / Production Images Complete (push) Failing after 26s
CICD / Runtime Black-Box Integration Tests (push) Has been skipped
CICD / End-to-End Tests (push) Has been skipped
CICD / E2E Tests Failure Postmortem (push) Has been skipped
CICD / Integration Tests Failure Postmortem (push) Has been skipped
CICD / Promote Staging Images To Release (push) Has been skipped
CICD / CICD Tests Complete (push) Failing after 33s
Renovate Dependency Updates / Renovate Dependencies (push) Successful in 22m18s
This PR contains the following updates:

| Package | Change | Age | Adoption | Passing | Confidence |
|---|---|---|---|---|---|

---

### Release Notes

### Configuration

📅 **Schedule**:

🚦 **Automerge**: Disabled

♻ **Rebasing**: Not rebasing

👥 **Reviewers**: None

---

*This PR has been generated by [Renovate Bot](https://github.com/renovatebot/renovate).*
<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0MS4xNzMuMSIsInVwZGF0ZWRJblZlciI6IjQxLjE3My4xIiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6WyJtYWpvci11cGRhdGUiXX0=-->

Co-authored-by: Renovate Bot <renovate@darkhelm.org>
Reviewed-on: #109
2026-07-21 22:20:46 -04:00
8ba9d5f5d0 chore: Update ubuntu Docker tag to v26 (#106)
Some checks failed
CICD / Build and Push CICD Images (push) Has started running
CICD / Build CICD Image Failure Postmortem (push) Has been cancelled
CICD / Source Checks (push) Has been cancelled
CICD / Dependency Audits (Informational) (push) Has been cancelled
CICD / CICD Tests Complete (push) Has been cancelled
CICD / Build Release Images (push) Has been cancelled
CICD / Build Tester Images (push) Has been cancelled
CICD / Production Images Complete (push) Has been cancelled
CICD / Production Image Failures Postmortem (push) Has been cancelled
CICD / Source Lanes Failure Postmortem (push) Has been cancelled
CICD / Runtime Black-Box Integration Tests (push) Has been cancelled
CICD / Integration Tests Failure Postmortem (push) Has been cancelled
CICD / End-to-End Tests (push) Has been cancelled
CICD / E2E Tests Failure Postmortem (push) Has been cancelled
CICD / Promote Staging Images To Release (push) Has been cancelled
This PR contains the following updates:

| Package | Change | Age | Adoption | Passing | Confidence |
|---|---|---|---|---|---|

---

### Release Notes

### Configuration

📅 **Schedule**:

🚦 **Automerge**: Disabled

♻ **Rebasing**: Not rebasing

👥 **Reviewers**: None

---

*This PR has been generated by [Renovate Bot](https://github.com/renovatebot/renovate).*
<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0MS4xNzMuMSIsInVwZGF0ZWRJblZlciI6IjQxLjE3My4xIiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6WyJtYWpvci11cGRhdGUiXX0=-->

Co-authored-by: Renovate Bot <renovate@darkhelm.org>
Reviewed-on: #106
2026-07-21 22:20:21 -04:00
329663ccdf chore: Update @types/node to 24.13.3 (#101)
Some checks failed
CICD / Build CICD Image Failure Postmortem (push) Has been cancelled
CICD / Source Checks (push) Has been cancelled
CICD / Dependency Audits (Informational) (push) Has been cancelled
CICD / Build and Push CICD Images (push) Has started running
CICD / CICD Tests Complete (push) Has been cancelled
CICD / Build Release Images (push) Has been cancelled
CICD / Build Tester Images (push) Has been cancelled
CICD / Production Images Complete (push) Has been cancelled
CICD / Production Image Failures Postmortem (push) Has been cancelled
CICD / Source Lanes Failure Postmortem (push) Has been cancelled
CICD / Runtime Black-Box Integration Tests (push) Has been cancelled
CICD / Integration Tests Failure Postmortem (push) Has been cancelled
CICD / End-to-End Tests (push) Has been cancelled
CICD / E2E Tests Failure Postmortem (push) Has been cancelled
CICD / Promote Staging Images To Release (push) Has been cancelled
This PR contains the following updates:

| Package | Change | Age | Adoption | Passing | Confidence |
|---|---|---|---|---|---|

---

### Release Notes

### Configuration

📅 **Schedule**:

🚦 **Automerge**: Disabled

♻ **Rebasing**: Not rebasing

👥 **Reviewers**: None

---

*This PR has been generated by [Renovate Bot](https://github.com/renovatebot/renovate).*
<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0MS4xNzMuMSIsInVwZGF0ZWRJblZlciI6IjQxLjE3My4xIiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6WyJtYWpvci11cGRhdGUiXX0=-->

Co-authored-by: Renovate Bot <renovate@darkhelm.org>
Reviewed-on: #101
2026-07-21 22:20:04 -04:00
1ba01171a1 chore: Update Yarn to 4.17.1 (#100)
Some checks failed
CICD / Build CICD Image Failure Postmortem (push) Has been cancelled
CICD / Source Checks (push) Has been cancelled
CICD / Dependency Audits (Informational) (push) Has been cancelled
CICD / CICD Tests Complete (push) Has been cancelled
CICD / Build Release Images (push) Has been cancelled
CICD / Build Tester Images (push) Has been cancelled
CICD / Production Images Complete (push) Has been cancelled
CICD / Production Image Failures Postmortem (push) Has been cancelled
CICD / Source Lanes Failure Postmortem (push) Has been cancelled
CICD / Runtime Black-Box Integration Tests (push) Has been cancelled
CICD / Integration Tests Failure Postmortem (push) Has been cancelled
CICD / End-to-End Tests (push) Has been cancelled
CICD / E2E Tests Failure Postmortem (push) Has been cancelled
CICD / Promote Staging Images To Release (push) Has been cancelled
CICD / Build and Push CICD Images (push) Has started running
This PR contains the following updates:

| Package | Change | Age | Adoption | Passing | Confidence |
|---|---|---|---|---|---|

---

### Release Notes

### Configuration

📅 **Schedule**:

🚦 **Automerge**: Disabled

♻ **Rebasing**: Not rebasing

👥 **Reviewers**: None

---

*This PR has been generated by [Renovate Bot](https://github.com/renovatebot/renovate).*
<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0MS4xNzMuMSIsInVwZGF0ZWRJblZlciI6IjQxLjE3My4xIiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6WyJzZWN1cml0eSJdfQ==-->

Co-authored-by: Renovate Bot <renovate@darkhelm.org>
Reviewed-on: #100
2026-07-21 22:19:47 -04:00
9d97f4bec8 Merge pull request 'chore: Update typescript to 5.9.3' (#99) from renovate/typescript-5.x into main
Some checks failed
CICD / Build CICD Image Failure Postmortem (push) Has been cancelled
CICD / Source Checks (push) Has been cancelled
CICD / Dependency Audits (Informational) (push) Has been cancelled
CICD / Build and Push CICD Images (push) Has started running
CICD / CICD Tests Complete (push) Has been cancelled
CICD / Build Release Images (push) Has been cancelled
CICD / Build Tester Images (push) Has been cancelled
CICD / Production Images Complete (push) Has been cancelled
CICD / Production Image Failures Postmortem (push) Has been cancelled
CICD / Source Lanes Failure Postmortem (push) Has been cancelled
CICD / Runtime Black-Box Integration Tests (push) Has been cancelled
CICD / Integration Tests Failure Postmortem (push) Has been cancelled
CICD / End-to-End Tests (push) Has been cancelled
CICD / E2E Tests Failure Postmortem (push) Has been cancelled
CICD / Promote Staging Images To Release (push) Has been cancelled
Reviewed-on: #99
2026-07-21 22:19:06 -04:00
81ff99fe59 chore: Update typescript to 5.9.3 2026-07-21 22:19:06 -04:00
a51bb70ba0 chore: Update @vue/tsconfig to 0.9.1 (#95)
Some checks failed
CICD / Build CICD Image Failure Postmortem (push) Has been cancelled
CICD / Source Checks (push) Has been cancelled
CICD / Dependency Audits (Informational) (push) Has been cancelled
CICD / Build and Push CICD Images (push) Has started running
CICD / CICD Tests Complete (push) Has been cancelled
CICD / Build Release Images (push) Has been cancelled
CICD / Build Tester Images (push) Has been cancelled
CICD / Production Images Complete (push) Has been cancelled
CICD / Production Image Failures Postmortem (push) Has been cancelled
CICD / Source Lanes Failure Postmortem (push) Has been cancelled
CICD / Runtime Black-Box Integration Tests (push) Has been cancelled
CICD / Integration Tests Failure Postmortem (push) Has been cancelled
CICD / End-to-End Tests (push) Has been cancelled
CICD / E2E Tests Failure Postmortem (push) Has been cancelled
CICD / Promote Staging Images To Release (push) Has been cancelled
This PR contains the following updates:

| Package | Change | Age | Adoption | Passing | Confidence |
|---|---|---|---|---|---|

---

### Release Notes

### Configuration

📅 **Schedule**:

🚦 **Automerge**: Disabled

♻ **Rebasing**: Not rebasing

👥 **Reviewers**: None

---

*This PR has been generated by [Renovate Bot](https://github.com/renovatebot/renovate).*
<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0MS4xNzMuMSIsInVwZGF0ZWRJblZlciI6IjQxLjE3My4xIiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6WyJzZWN1cml0eSJdfQ==-->

Co-authored-by: Renovate Bot <renovate@darkhelm.org>
Reviewed-on: #95
2026-07-21 22:18:42 -04:00
5fa44e2bec chore: Update @playwright/test to 1.61.1 (#94)
Some checks failed
CICD / Build CICD Image Failure Postmortem (push) Has been cancelled
CICD / Source Checks (push) Has been cancelled
CICD / Dependency Audits (Informational) (push) Has been cancelled
CICD / CICD Tests Complete (push) Has been cancelled
CICD / Build Release Images (push) Has been cancelled
CICD / Build Tester Images (push) Has been cancelled
CICD / Build and Push CICD Images (push) Has started running
CICD / Production Images Complete (push) Has been cancelled
CICD / Production Image Failures Postmortem (push) Has been cancelled
CICD / Source Lanes Failure Postmortem (push) Has been cancelled
CICD / Runtime Black-Box Integration Tests (push) Has been cancelled
CICD / Integration Tests Failure Postmortem (push) Has been cancelled
CICD / End-to-End Tests (push) Has been cancelled
CICD / E2E Tests Failure Postmortem (push) Has been cancelled
CICD / Promote Staging Images To Release (push) Has been cancelled
This PR contains the following updates:

| Package | Change | Age | Adoption | Passing | Confidence |
|---|---|---|---|---|---|

---

### Release Notes

### Configuration

📅 **Schedule**:

🚦 **Automerge**: Disabled

♻ **Rebasing**: Not rebasing

👥 **Reviewers**: None

---

*This PR has been generated by [Renovate Bot](https://github.com/renovatebot/renovate).*
<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0MS4xNzMuMSIsInVwZGF0ZWRJblZlciI6IjQxLjE3My4xIiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6WyJzZWN1cml0eSJdfQ==-->

Co-authored-by: Renovate Bot <renovate@darkhelm.org>
Reviewed-on: #94
2026-07-21 22:17:44 -04:00
640d3bb767 chore: Update vue to 3.5.40 (#93)
Some checks failed
CICD / Build CICD Image Failure Postmortem (push) Has been cancelled
CICD / Source Checks (push) Has been cancelled
CICD / Build and Push CICD Images (push) Has been cancelled
CICD / Dependency Audits (Informational) (push) Has been cancelled
CICD / CICD Tests Complete (push) Has been cancelled
CICD / Build Release Images (push) Has been cancelled
CICD / Build Tester Images (push) Has been cancelled
CICD / Production Images Complete (push) Has been cancelled
CICD / Production Image Failures Postmortem (push) Has been cancelled
CICD / Source Lanes Failure Postmortem (push) Has been cancelled
CICD / Runtime Black-Box Integration Tests (push) Has been cancelled
CICD / Integration Tests Failure Postmortem (push) Has been cancelled
CICD / End-to-End Tests (push) Has been cancelled
CICD / E2E Tests Failure Postmortem (push) Has been cancelled
CICD / Promote Staging Images To Release (push) Has been cancelled
This PR contains the following updates:

| Package | Change | Age | Adoption | Passing | Confidence |
|---|---|---|---|---|---|

---

### Release Notes

### Configuration

📅 **Schedule**:

🚦 **Automerge**: Disabled

♻ **Rebasing**: Not rebasing

👥 **Reviewers**: None

---

*This PR has been generated by [Renovate Bot](https://github.com/renovatebot/renovate).*
<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0MS4xNzMuMSIsInVwZGF0ZWRJblZlciI6IjQxLjE3My4xIiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6WyJzZWN1cml0eSJdfQ==-->

Co-authored-by: Renovate Bot <renovate@darkhelm.org>
Reviewed-on: #93
2026-07-21 22:16:56 -04:00
75fdff75cf chore: Update Frontend dev tools (patch) (#91)
Some checks failed
CICD / Build CICD Image Failure Postmortem (push) Has been cancelled
CICD / Source Checks (push) Has been cancelled
CICD / Dependency Audits (Informational) (push) Has been cancelled
CICD / Build and Push CICD Images (push) Has started running
CICD / CICD Tests Complete (push) Has been cancelled
CICD / Build Release Images (push) Has been cancelled
CICD / Build Tester Images (push) Has been cancelled
CICD / Production Images Complete (push) Has been cancelled
CICD / Production Image Failures Postmortem (push) Has been cancelled
CICD / Source Lanes Failure Postmortem (push) Has been cancelled
CICD / Runtime Black-Box Integration Tests (push) Has been cancelled
CICD / Integration Tests Failure Postmortem (push) Has been cancelled
CICD / End-to-End Tests (push) Has been cancelled
CICD / E2E Tests Failure Postmortem (push) Has been cancelled
CICD / Promote Staging Images To Release (push) Has been cancelled
This PR contains the following updates:

| Package | Change | Age | Adoption | Passing | Confidence |
|---|---|---|---|---|---|

---

### Release Notes

### Configuration

📅 **Schedule**:

🚦 **Automerge**: Disabled

♻ **Rebasing**: Not rebasing

👥 **Reviewers**: None

---

*This PR has been generated by [Renovate Bot](https://github.com/renovatebot/renovate).*
<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0MS4xNzMuMSIsInVwZGF0ZWRJblZlciI6IjQxLjE3My4xIiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6WyJzZWN1cml0eSJdfQ==-->

Co-authored-by: Renovate Bot <renovate@darkhelm.org>
Reviewed-on: #91
2026-07-21 22:15:29 -04:00
4d1069767b chore: Update fastapi to 0.139.2 (#90)
Some checks failed
CICD / Build CICD Image Failure Postmortem (push) Has been cancelled
CICD / Source Checks (push) Has been cancelled
CICD / Dependency Audits (Informational) (push) Has been cancelled
CICD / CICD Tests Complete (push) Has been cancelled
CICD / Build Release Images (push) Has been cancelled
CICD / Build Tester Images (push) Has been cancelled
CICD / Production Images Complete (push) Has been cancelled
CICD / Production Image Failures Postmortem (push) Has been cancelled
CICD / Source Lanes Failure Postmortem (push) Has been cancelled
CICD / Runtime Black-Box Integration Tests (push) Has been cancelled
CICD / Integration Tests Failure Postmortem (push) Has been cancelled
CICD / End-to-End Tests (push) Has been cancelled
CICD / E2E Tests Failure Postmortem (push) Has been cancelled
CICD / Promote Staging Images To Release (push) Has been cancelled
CICD / Build and Push CICD Images (push) Has started running
This PR contains the following updates:

| Package | Change | Age | Adoption | Passing | Confidence |
|---|---|---|---|---|---|

---

### Release Notes

### Configuration

📅 **Schedule**:

🚦 **Automerge**: Disabled

♻ **Rebasing**: Not rebasing

👥 **Reviewers**: None

---

*This PR has been generated by [Renovate Bot](https://github.com/renovatebot/renovate).*
<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0MS4xNzMuMSIsInVwZGF0ZWRJblZlciI6IjQxLjE3My4xIiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6WyJzZWN1cml0eSJdfQ==-->

Co-authored-by: Renovate Bot <renovate@darkhelm.org>
Reviewed-on: #90
2026-07-21 22:15:06 -04:00
9d4db9eaa4 chore: Update @vue/test-utils to 2.4.11 (#89)
Some checks failed
CICD / Build CICD Image Failure Postmortem (push) Has been cancelled
CICD / Source Checks (push) Has been cancelled
CICD / Build and Push CICD Images (push) Has been cancelled
CICD / Dependency Audits (Informational) (push) Has been cancelled
CICD / CICD Tests Complete (push) Has been cancelled
CICD / Build Release Images (push) Has been cancelled
CICD / Build Tester Images (push) Has been cancelled
CICD / Production Images Complete (push) Has been cancelled
CICD / Production Image Failures Postmortem (push) Has been cancelled
CICD / Source Lanes Failure Postmortem (push) Has been cancelled
CICD / Runtime Black-Box Integration Tests (push) Has been cancelled
CICD / Integration Tests Failure Postmortem (push) Has been cancelled
CICD / End-to-End Tests (push) Has been cancelled
CICD / E2E Tests Failure Postmortem (push) Has been cancelled
CICD / Promote Staging Images To Release (push) Has been cancelled
This PR contains the following updates:

| Package | Change | Age | Adoption | Passing | Confidence |
|---|---|---|---|---|---|

---

### Release Notes

### Configuration

📅 **Schedule**:

🚦 **Automerge**: Disabled

♻ **Rebasing**: Not rebasing

👥 **Reviewers**: None

---

*This PR has been generated by [Renovate Bot](https://github.com/renovatebot/renovate).*
<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0MS4xNzMuMSIsInVwZGF0ZWRJblZlciI6IjQxLjE3My4xIiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6WyJzZWN1cml0eSJdfQ==-->

Co-authored-by: Renovate Bot <renovate@darkhelm.org>
Reviewed-on: #89
2026-07-21 22:14:25 -04:00
0e76925c90 chore: Update @vitest/coverage-v8 to 3.2.7 (#88)
Some checks failed
CICD / Build and Push CICD Images (push) Has been cancelled
CICD / Build CICD Image Failure Postmortem (push) Has been cancelled
CICD / Source Checks (push) Has been cancelled
CICD / Dependency Audits (Informational) (push) Has been cancelled
CICD / CICD Tests Complete (push) Has been cancelled
CICD / Build Release Images (push) Has been cancelled
CICD / Build Tester Images (push) Has been cancelled
CICD / Production Images Complete (push) Has been cancelled
CICD / Production Image Failures Postmortem (push) Has been cancelled
CICD / Source Lanes Failure Postmortem (push) Has been cancelled
CICD / Runtime Black-Box Integration Tests (push) Has been cancelled
CICD / Integration Tests Failure Postmortem (push) Has been cancelled
CICD / End-to-End Tests (push) Has been cancelled
CICD / E2E Tests Failure Postmortem (push) Has been cancelled
CICD / Promote Staging Images To Release (push) Has been cancelled
This PR contains the following updates:

| Package | Change | Age | Adoption | Passing | Confidence |
|---|---|---|---|---|---|

---

### Release Notes

### Configuration

📅 **Schedule**:

🚦 **Automerge**: Disabled

♻ **Rebasing**: Not rebasing

👥 **Reviewers**: None

---

*This PR has been generated by [Renovate Bot](https://github.com/renovatebot/renovate).*
<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0MS4xNzMuMSIsInVwZGF0ZWRJblZlciI6IjQxLjE3My4xIiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6WyJzZWN1cml0eSJdfQ==-->

Co-authored-by: Renovate Bot <renovate@darkhelm.org>
Reviewed-on: #88
2026-07-21 22:12:41 -04:00
c4f59e4d05 chore: Update @vitejs/plugin-vue to 6.0.8 (#87)
Some checks failed
CICD / Build and Push CICD Images (push) Has been cancelled
CICD / Build CICD Image Failure Postmortem (push) Has been cancelled
CICD / Source Checks (push) Has been cancelled
CICD / Dependency Audits (Informational) (push) Has been cancelled
CICD / CICD Tests Complete (push) Has been cancelled
CICD / Build Release Images (push) Has been cancelled
CICD / Build Tester Images (push) Has been cancelled
CICD / Production Images Complete (push) Has been cancelled
CICD / Production Image Failures Postmortem (push) Has been cancelled
CICD / Source Lanes Failure Postmortem (push) Has been cancelled
CICD / Runtime Black-Box Integration Tests (push) Has been cancelled
CICD / Integration Tests Failure Postmortem (push) Has been cancelled
CICD / End-to-End Tests (push) Has been cancelled
CICD / E2E Tests Failure Postmortem (push) Has been cancelled
CICD / Promote Staging Images To Release (push) Has been cancelled
This PR contains the following updates:

| Package | Change | Age | Adoption | Passing | Confidence |
|---|---|---|---|---|---|

---

### Release Notes

### Configuration

📅 **Schedule**:

🚦 **Automerge**: Disabled

♻ **Rebasing**: Not rebasing

👥 **Reviewers**: None

---

*This PR has been generated by [Renovate Bot](https://github.com/renovatebot/renovate).*
<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0MS4xNzMuMSIsInVwZGF0ZWRJblZlciI6IjQxLjE3My4xIiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6WyJzZWN1cml0eSJdfQ==-->

Co-authored-by: Renovate Bot <renovate@darkhelm.org>
Reviewed-on: #87
2026-07-21 22:12:22 -04:00
copilotcoder
e4925e2023 ci(renovate): force manual runs outside schedule
Some checks failed
CICD / Build CICD Image Failure Postmortem (push) Has been cancelled
CICD / Source Checks (push) Has been cancelled
CICD / Dependency Audits (Informational) (push) Has been cancelled
CICD / CICD Tests Complete (push) Has been cancelled
CICD / Build Release Images (push) Has been cancelled
CICD / Build Tester Images (push) Has been cancelled
CICD / Production Images Complete (push) Has been cancelled
CICD / Production Image Failures Postmortem (push) Has been cancelled
CICD / Source Lanes Failure Postmortem (push) Has been cancelled
CICD / Runtime Black-Box Integration Tests (push) Has been cancelled
CICD / Integration Tests Failure Postmortem (push) Has been cancelled
CICD / End-to-End Tests (push) Has been cancelled
CICD / E2E Tests Failure Postmortem (push) Has been cancelled
CICD / Promote Staging Images To Release (push) Has been cancelled
CICD / Build and Push CICD Images (push) Has been cancelled
2026-07-21 15:52:58 -04:00
copilotcoder
f037e7138d docs(dev): document Renovate manual dispatch behavior
All checks were successful
CICD / Build and Push CICD Images (push) Successful in 9m42s
CICD / Build CICD Image Failure Postmortem (push) Has been skipped
CICD / Source Checks (push) Successful in 2m19s
CICD / Source Lanes Failure Postmortem (push) Has been skipped
CICD / Build Release Images (push) Successful in 9m52s
CICD / Build Tester Images (push) Successful in 12m17s
CICD / Production Image Failures Postmortem (push) Has been skipped
CICD / Production Images Complete (push) Successful in 3s
CICD / Runtime Black-Box Integration Tests (push) Successful in 1m19s
CICD / Integration Tests Failure Postmortem (push) Has been skipped
CICD / End-to-End Tests (push) Successful in 2m12s
CICD / E2E Tests Failure Postmortem (push) Has been skipped
CICD / Promote Staging Images To Release (push) Successful in 42s
CICD / Dependency Audits (Informational) (push) Successful in 18m45s
CICD / CICD Tests Complete (push) Successful in 4s
2026-07-21 15:04:09 -04:00
copilotcoder
93b4000b20 ci(renovate): run manual dispatch outside schedule in single pass
Some checks failed
CICD / Build CICD Image Failure Postmortem (push) Has been cancelled
CICD / Source Checks (push) Has been cancelled
CICD / Dependency Audits (Informational) (push) Has been cancelled
CICD / CICD Tests Complete (push) Has been cancelled
CICD / Build Release Images (push) Has been cancelled
CICD / Build Tester Images (push) Has been cancelled
CICD / Production Images Complete (push) Has been cancelled
CICD / Production Image Failures Postmortem (push) Has been cancelled
CICD / Source Lanes Failure Postmortem (push) Has been cancelled
CICD / Runtime Black-Box Integration Tests (push) Has been cancelled
CICD / Integration Tests Failure Postmortem (push) Has been cancelled
CICD / End-to-End Tests (push) Has been cancelled
CICD / Build and Push CICD Images (push) Has been cancelled
CICD / E2E Tests Failure Postmortem (push) Has been cancelled
CICD / Promote Staging Images To Release (push) Has been cancelled
2026-07-21 14:24:45 -04:00
copilotcoder
996a018dad Working on debugging renovate, set log level back to debug.
Some checks failed
CICD / Build CICD Image Failure Postmortem (push) Has been cancelled
CICD / Source Checks (push) Has been cancelled
CICD / Dependency Audits (Informational) (push) Has been cancelled
CICD / Build and Push CICD Images (push) Has been cancelled
CICD / CICD Tests Complete (push) Has been cancelled
CICD / Build Release Images (push) Has been cancelled
CICD / Build Tester Images (push) Has been cancelled
CICD / Production Images Complete (push) Has been cancelled
CICD / Production Image Failures Postmortem (push) Has been cancelled
CICD / Source Lanes Failure Postmortem (push) Has been cancelled
CICD / Runtime Black-Box Integration Tests (push) Has been cancelled
CICD / Integration Tests Failure Postmortem (push) Has been cancelled
CICD / End-to-End Tests (push) Has been cancelled
CICD / E2E Tests Failure Postmortem (push) Has been cancelled
CICD / Promote Staging Images To Release (push) Has been cancelled
Signed-off-by: copilotcoder <copilotcoder@darkhelm.org>
2026-07-21 13:46:45 -04:00
copilotcoder
b1055ba605 Updating psycopg to 3.3.4
Some checks failed
CICD / Build and Push CICD Images (push) Successful in 12m11s
CICD / Build CICD Image Failure Postmortem (push) Has been skipped
CICD / Source Checks (push) Successful in 2m36s
CICD / Source Lanes Failure Postmortem (push) Has been skipped
CICD / Dependency Audits (Informational) (push) Successful in 1m28s
CICD / CICD Tests Complete (push) Successful in 8s
CICD / Build Tester Images (push) Successful in 6m31s
CICD / Build Release Images (push) Successful in 27m10s
CICD / Production Image Failures Postmortem (push) Has been skipped
CICD / Production Images Complete (push) Successful in 4s
CICD / End-to-End Tests (push) Successful in 6m38s
CICD / E2E Tests Failure Postmortem (push) Has been skipped
CICD / Runtime Black-Box Integration Tests (push) Successful in 21m37s
CICD / Integration Tests Failure Postmortem (push) Has been skipped
CICD / Promote Staging Images To Release (push) Successful in 44s
Renovate Dependency Updates / Renovate Dependencies (push) Failing after 12m58s
Signed-off-by: copilotcoder <copilotcoder@darkhelm.org>
2026-07-20 20:50:10 -04:00
copilotcoder
5efe0446d5 Rename runtime images to explicit plex-playlist names
Some checks failed
CICD / Build CICD Image Failure Postmortem (push) Has been cancelled
CICD / Source Checks (push) Has been cancelled
CICD / Dependency Audits (Informational) (push) Has been cancelled
CICD / CICD Tests Complete (push) Has been cancelled
CICD / Build Release Images (push) Has been cancelled
CICD / Build Tester Images (push) Has been cancelled
CICD / Production Images Complete (push) Has been cancelled
CICD / Production Image Failures Postmortem (push) Has been cancelled
CICD / Build and Push CICD Images (push) Has been cancelled
CICD / Source Lanes Failure Postmortem (push) Has been cancelled
CICD / Runtime Black-Box Integration Tests (push) Has been cancelled
CICD / Integration Tests Failure Postmortem (push) Has been cancelled
CICD / End-to-End Tests (push) Has been cancelled
CICD / E2E Tests Failure Postmortem (push) Has been cancelled
CICD / Promote Staging Images To Release (push) Has been cancelled
2026-07-20 20:44:58 -04:00
22 changed files with 1742 additions and 2081 deletions

View File

@@ -135,9 +135,9 @@ jobs:
if retry_cmd 5 3 env GIT_SSH_COMMAND="ssh -i ~/.ssh/id_rsa -o IdentitiesOnly=yes -o StrictHostKeyChecking=no" \
git fetch --depth 1 origin "${HEAD_SHA}" >/dev/null 2>&1; then
git checkout FETCH_HEAD -- Dockerfile.cicd-base .dockerignore scripts/compute-cicd-base-hash.sh scripts/resolve-mirrored-image.sh
git checkout FETCH_HEAD -- Dockerfile.cicd-base .dockerignore versions/ci.env backend/pyproject.toml frontend/package.json scripts/compute-cicd-base-hash.sh scripts/resolve-mirrored-image.sh
else
git checkout HEAD -- Dockerfile.cicd-base .dockerignore scripts/compute-cicd-base-hash.sh scripts/resolve-mirrored-image.sh
git checkout HEAD -- Dockerfile.cicd-base .dockerignore versions/ci.env backend/pyproject.toml frontend/package.json scripts/compute-cicd-base-hash.sh scripts/resolve-mirrored-image.sh
fi
chmod +x scripts/compute-cicd-base-hash.sh
@@ -324,8 +324,17 @@ jobs:
docker_login_with_retry 5 3
PLAYWRIGHT_BROWSERS_MIRROR_TAG="${GITEA_REGISTRY}/darkhelm.org/playwright-browsers:v1.56.1-jammy"
PLAYWRIGHT_BROWSERS_UPSTREAM_TAG="mcr.microsoft.com/playwright:v1.56.1-jammy"
set -a
# shellcheck source=versions/ci.env
source versions/ci.env
set +a
PYTHON_VERSION="$(python3 -c "from pathlib import Path; import re, tomllib, sys; pyproject = tomllib.loads(Path('backend/pyproject.toml').read_text()); requires_python = pyproject['project']['requires-python']; match = re.search(r'([0-9]+[.][0-9]+)', requires_python); sys.exit('could not derive backend Python version') if not match else None; print(match.group(1))")"
NODE_MAJOR="$(node -p "const pkg = require('./frontend/package.json'); const match = String(pkg.engines?.node ?? '').match(/(\\d+)/); if (!match) throw new Error('could not derive frontend Node major'); match[1]")"
PLAYWRIGHT_BROWSERS_MIRROR_TAG="${GITEA_REGISTRY}/${PLAYWRIGHT_MIRROR_IMAGE}"
PLAYWRIGHT_BROWSERS_UPSTREAM_TAG="${PLAYWRIGHT_IMAGE}"
PLAYWRIGHT_BROWSERS_LOCAL_TAG="$(./scripts/resolve-mirrored-image.sh \
--image "${PLAYWRIGHT_BROWSERS_MIRROR_TAG}" \
--mirror-image "${PLAYWRIGHT_BROWSERS_MIRROR_TAG}" \
@@ -342,6 +351,10 @@ jobs:
docker build --progress=plain -f Dockerfile.cicd-base \
--build-arg BASE_IMAGE_VERSION="v1.0.0-${BASE_HASH}" \
--build-arg BASE_IMAGE_HASH="${BASE_HASH}" \
--build-arg PYTHON_VERSION="${PYTHON_VERSION}" \
--build-arg NODE_MAJOR="${NODE_MAJOR}" \
--build-arg PLAYWRIGHT_VERSION="${PLAYWRIGHT_VERSION}" \
--build-arg PLAYWRIGHT_DISTRO="${PLAYWRIGHT_DISTRO}" \
--build-arg PLAYWRIGHT_BROWSERS_IMAGE="${PLAYWRIGHT_BROWSERS_IMAGE}" \
-t cicd-base:latest .
@@ -399,9 +412,9 @@ jobs:
if retry_cmd 5 3 env GIT_SSH_COMMAND="ssh -i ~/.ssh/id_rsa -o IdentitiesOnly=yes -o StrictHostKeyChecking=no" \
git fetch --depth 1 origin "${HEAD_SHA}" >/dev/null 2>&1; then
git checkout FETCH_HEAD -- .dockerignore Dockerfile.cicd Dockerfile.cicd-base scripts/compute-cicd-base-hash.sh scripts/resolve-mirrored-image.sh
git checkout FETCH_HEAD -- .dockerignore Dockerfile.cicd Dockerfile.cicd-base versions/ci.env scripts/compute-cicd-base-hash.sh scripts/resolve-mirrored-image.sh
else
git checkout HEAD -- .dockerignore Dockerfile.cicd Dockerfile.cicd-base scripts/compute-cicd-base-hash.sh scripts/resolve-mirrored-image.sh
git checkout HEAD -- .dockerignore Dockerfile.cicd Dockerfile.cicd-base versions/ci.env scripts/compute-cicd-base-hash.sh scripts/resolve-mirrored-image.sh
fi
chmod +x scripts/compute-cicd-base-hash.sh
chmod +x scripts/resolve-mirrored-image.sh
@@ -1094,11 +1107,16 @@ jobs:
FRONTEND_BASE_TAG_REF="${FRONTEND_BASE_REPO}:${HEAD_SHA}"
FRONTEND_BASE_CACHE_REF="${FRONTEND_BASE_REPO}:cache"
NODE_ALPINE_TAG="$(node -p "const pkg = require('./frontend/package.json'); const match = String(pkg.engines?.node ?? '').match(/(\\d+)/); if (!match) throw new Error('could not derive frontend Node major'); match[1] + '-alpine'")"
YARN_VERSION="$(node -p "const pkg = require('./frontend/package.json'); const match = String(pkg.packageManager ?? '').match(/^yarn@(.*)$/); if (!match) throw new Error('could not derive frontend Yarn version'); match[1]")"
retry_registry_op pull "${FRONTEND_BASE_CACHE_REF}" 5 3 || true
BUILDKIT_NO_CLIENT_TOKEN=1 DOCKER_BUILDKIT=1 docker build -f Dockerfile.frontend \
--target deps \
--cache-from "${FRONTEND_BASE_CACHE_REF}" \
--build-arg BUILDKIT_INLINE_CACHE=1 \
--build-arg NODE_ALPINE_TAG="${FRONTEND_NODE_ALPINE_TAG}" \
--build-arg YARN_VERSION="${FRONTEND_YARN_VERSION}" \
-t plex-playlist-frontend-base:"${HEAD_SHA}" .
docker tag plex-playlist-frontend-base:"${HEAD_SHA}" "${FRONTEND_BASE_TAG_REF}"
docker tag plex-playlist-frontend-base:"${HEAD_SHA}" "${FRONTEND_BASE_CACHE_REF}"
@@ -1173,7 +1191,7 @@ jobs:
return 1
}
DEPLOYABLE_BACKEND_REPO="${GITEA_REGISTRY}/darkhelm.org/deployable-backend-staging"
DEPLOYABLE_BACKEND_REPO="${GITEA_REGISTRY}/darkhelm.org/plex-playlist-backend-staging"
DEPLOYABLE_BACKEND_TAG_REF="${DEPLOYABLE_BACKEND_REPO}:${HEAD_SHA}"
DEPLOYABLE_BACKEND_CACHE_REF="${DEPLOYABLE_BACKEND_REPO}:cache"
@@ -1182,11 +1200,11 @@ jobs:
DOCKER_BUILDKIT=1 docker build -f Dockerfile.backend \
--cache-from "${DEPLOYABLE_BACKEND_CACHE_REF}" \
--build-arg BUILDKIT_INLINE_CACHE=1 \
-t deployable-backend:"${HEAD_SHA}" .
bash ./scripts/verify-deployable-image-purity.sh --image deployable-backend:"${HEAD_SHA}" --profile backend
-t plex-playlist-backend:"${HEAD_SHA}" .
bash ./scripts/verify-deployable-image-purity.sh --image plex-playlist-backend:"${HEAD_SHA}" --profile backend
docker tag "deployable-backend:${HEAD_SHA}" "${DEPLOYABLE_BACKEND_TAG_REF}"
docker tag "deployable-backend:${HEAD_SHA}" "${DEPLOYABLE_BACKEND_CACHE_REF}"
docker tag "plex-playlist-backend:${HEAD_SHA}" "${DEPLOYABLE_BACKEND_TAG_REF}"
docker tag "plex-playlist-backend:${HEAD_SHA}" "${DEPLOYABLE_BACKEND_CACHE_REF}"
retry_registry_op push "${DEPLOYABLE_BACKEND_TAG_REF}" 5 4
retry_registry_op push "${DEPLOYABLE_BACKEND_CACHE_REF}" 5 4
@@ -1281,21 +1299,26 @@ jobs:
return 1
}
DEPLOYABLE_FRONTEND_REPO="${GITEA_REGISTRY}/darkhelm.org/deployable-frontend-staging"
DEPLOYABLE_FRONTEND_REPO="${GITEA_REGISTRY}/darkhelm.org/plex-playlist-frontend-staging"
DEPLOYABLE_FRONTEND_TAG_REF="${DEPLOYABLE_FRONTEND_REPO}:${HEAD_SHA}"
DEPLOYABLE_FRONTEND_CACHE_REF="${DEPLOYABLE_FRONTEND_REPO}:cache"
NODE_ALPINE_TAG="$(node -p "const pkg = require('./frontend/package.json'); const match = String(pkg.engines?.node ?? '').match(/(\\d+)/); if (!match) throw new Error('could not derive frontend Node major'); match[1] + '-alpine'")"
YARN_VERSION="$(node -p "const pkg = require('./frontend/package.json'); const match = String(pkg.packageManager ?? '').match(/^yarn@(.*)$/); if (!match) throw new Error('could not derive frontend Yarn version'); match[1]")"
docker_login_with_retry 5 3
retry_registry_op pull "${DEPLOYABLE_FRONTEND_CACHE_REF}" 5 3 || true
BUILDKIT_NO_CLIENT_TOKEN=1 DOCKER_BUILDKIT=1 docker build -f Dockerfile.frontend \
--target production \
--cache-from "${DEPLOYABLE_FRONTEND_CACHE_REF}" \
--build-arg BUILDKIT_INLINE_CACHE=1 \
-t deployable-frontend:"${HEAD_SHA}" .
bash ./scripts/verify-deployable-image-purity.sh --image deployable-frontend:"${HEAD_SHA}" --profile frontend
--build-arg NODE_ALPINE_TAG="${FRONTEND_NODE_ALPINE_TAG}" \
--build-arg YARN_VERSION="${FRONTEND_YARN_VERSION}" \
-t plex-playlist-frontend:"${HEAD_SHA}" .
bash ./scripts/verify-deployable-image-purity.sh --image plex-playlist-frontend:"${HEAD_SHA}" --profile frontend
docker tag "deployable-frontend:${HEAD_SHA}" "${DEPLOYABLE_FRONTEND_TAG_REF}"
docker tag "deployable-frontend:${HEAD_SHA}" "${DEPLOYABLE_FRONTEND_CACHE_REF}"
docker tag "plex-playlist-frontend:${HEAD_SHA}" "${DEPLOYABLE_FRONTEND_TAG_REF}"
docker tag "plex-playlist-frontend:${HEAD_SHA}" "${DEPLOYABLE_FRONTEND_CACHE_REF}"
retry_registry_op push "${DEPLOYABLE_FRONTEND_TAG_REF}" 5 4
retry_registry_op push "${DEPLOYABLE_FRONTEND_CACHE_REF}" 5 4
@@ -1442,8 +1465,13 @@ jobs:
run: |
set -euo pipefail
PLAYWRIGHT_BASE_IMAGE_MIRROR="${GITEA_REGISTRY}/darkhelm.org/playwright-browsers:v1.56.1-jammy"
PLAYWRIGHT_BASE_IMAGE_UPSTREAM="mcr.microsoft.com/playwright:v1.56.1-jammy"
set -a
# shellcheck source=versions/ci.env
source versions/ci.env
set +a
PLAYWRIGHT_BASE_IMAGE_MIRROR="${GITEA_REGISTRY}/${PLAYWRIGHT_MIRROR_IMAGE}"
PLAYWRIGHT_BASE_IMAGE_UPSTREAM="${PLAYWRIGHT_IMAGE}"
docker_login_with_retry() {
attempts="${1:-5}"
@@ -1543,6 +1571,8 @@ jobs:
DOCKER_BUILDKIT=1 docker build --pull=false -f Dockerfile.e2e-tester \
--cache-from "${E2E_TESTER_CACHE_REF}" \
--build-arg BUILDKIT_INLINE_CACHE=1 \
--build-arg PLAYWRIGHT_VERSION="${PLAYWRIGHT_VERSION}" \
--build-arg PLAYWRIGHT_DISTRO="${PLAYWRIGHT_DISTRO}" \
--build-arg PLAYWRIGHT_BASE_IMAGE="${PLAYWRIGHT_BASE_IMAGE}" \
-t plex-playlist-e2e:"${HEAD_SHA}" .
docker tag plex-playlist-e2e:"${HEAD_SHA}" "${E2E_TESTER_TAG_REF}"
@@ -1806,8 +1836,7 @@ jobs:
COMPOSE_PROJECT_NAME="plex-int-${RUN_ID}-${RUN_ATTEMPT}"
DB_PASSWORD="plex_password"
DB_URL="postgresql://plex_user:${DB_PASSWORD}@database:5432/plex_playlist"
POSTGRES_IMAGE_MIRROR="${GITEA_REGISTRY}/darkhelm.org/postgres:16-alpine"
POSTGRES_IMAGE_UPSTREAM="docker.io/library/postgres:16-alpine"
VERSION_ENV_PATH="/tmp/ci.env"
RESOLVER_PATH="/tmp/resolve-mirrored-image.sh"
if ! command -v docker >/dev/null 2>&1; then
@@ -1839,9 +1868,18 @@ jobs:
RESOLVER_SOURCE_IMAGE="${GITEA_REGISTRY}/darkhelm.org/plex-playlist-cicd:${HEAD_SHA}"
RESOLVER_CONTAINER="$(docker create "${RESOLVER_SOURCE_IMAGE}")"
docker cp "${RESOLVER_CONTAINER}:/workspace/scripts/resolve-mirrored-image.sh" "${RESOLVER_PATH}"
docker cp "${RESOLVER_CONTAINER}:/workspace/versions/ci.env" "${VERSION_ENV_PATH}"
docker rm -f "${RESOLVER_CONTAINER}" >/dev/null 2>&1 || true
chmod +x "${RESOLVER_PATH}"
set -a
# shellcheck source=/tmp/ci.env
source "${VERSION_ENV_PATH}"
set +a
POSTGRES_IMAGE_MIRROR="${GITEA_REGISTRY}/${POSTGRES_MIRROR_IMAGE}"
POSTGRES_IMAGE_UPSTREAM="${POSTGRES_UPSTREAM_IMAGE}"
POSTGRES_IMAGE="$(${RESOLVER_PATH} \
--image "${POSTGRES_IMAGE_MIRROR}" \
--mirror-image "${POSTGRES_IMAGE_MIRROR}" \
@@ -2113,8 +2151,7 @@ jobs:
DB_PASSWORD="plex_password"
DB_URL="postgresql://plex_user:${DB_PASSWORD}@database:5432/plex_playlist"
E2E_REPO_DIR="$(mktemp -d)"
POSTGRES_IMAGE_MIRROR="${GITEA_REGISTRY}/darkhelm.org/postgres:16-alpine"
POSTGRES_IMAGE_UPSTREAM="docker.io/library/postgres:16-alpine"
VERSION_ENV_PATH="/tmp/ci.env"
RESOLVER_PATH="/tmp/resolve-mirrored-image.sh"
if ! command -v docker >/dev/null 2>&1; then
@@ -2146,9 +2183,18 @@ jobs:
RESOLVER_SOURCE_IMAGE="${GITEA_REGISTRY}/darkhelm.org/plex-playlist-cicd:${HEAD_SHA}"
RESOLVER_CONTAINER="$(docker create "${RESOLVER_SOURCE_IMAGE}")"
docker cp "${RESOLVER_CONTAINER}:/workspace/scripts/resolve-mirrored-image.sh" "${RESOLVER_PATH}"
docker cp "${RESOLVER_CONTAINER}:/workspace/versions/ci.env" "${VERSION_ENV_PATH}"
docker rm -f "${RESOLVER_CONTAINER}" >/dev/null 2>&1 || true
chmod +x "${RESOLVER_PATH}"
set -a
# shellcheck source=/tmp/ci.env
source "${VERSION_ENV_PATH}"
set +a
POSTGRES_IMAGE_MIRROR="${GITEA_REGISTRY}/${POSTGRES_MIRROR_IMAGE}"
POSTGRES_IMAGE_UPSTREAM="${POSTGRES_UPSTREAM_IMAGE}"
POSTGRES_IMAGE="$(${RESOLVER_PATH} \
--image "${POSTGRES_IMAGE_MIRROR}" \
--mirror-image "${POSTGRES_IMAGE_MIRROR}" \
@@ -2617,12 +2663,12 @@ jobs:
if [ -z "${STAGING_BACKEND_DIGEST_REF}" ]; then
echo "Staging backend digest output missing; deriving from staging tag ${HEAD_SHA}"
STAGING_BACKEND_DIGEST_REF="$(resolve_staging_digest_from_tag "${GITEA_REGISTRY}/darkhelm.org/deployable-backend-staging" "${HEAD_SHA}")"
STAGING_BACKEND_DIGEST_REF="$(resolve_staging_digest_from_tag "${GITEA_REGISTRY}/darkhelm.org/plex-playlist-backend-staging" "${HEAD_SHA}")"
fi
if [ -z "${STAGING_FRONTEND_DIGEST_REF}" ]; then
echo "Staging frontend digest output missing; deriving from staging tag ${HEAD_SHA}"
STAGING_FRONTEND_DIGEST_REF="$(resolve_staging_digest_from_tag "${GITEA_REGISTRY}/darkhelm.org/deployable-frontend-staging" "${HEAD_SHA}")"
STAGING_FRONTEND_DIGEST_REF="$(resolve_staging_digest_from_tag "${GITEA_REGISTRY}/darkhelm.org/plex-playlist-frontend-staging" "${HEAD_SHA}")"
fi
if [ -z "${STAGING_BACKEND_DIGEST_REF}" ] || [ -z "${STAGING_FRONTEND_DIGEST_REF}" ]; then
@@ -2683,8 +2729,8 @@ jobs:
PREVIOUS_RELEASE_VERSION="$(printf '%s\n' "${RELEASE_TAG_LIST}" | awk -v current="${RELEASE_VERSION}" 'NF {if ($0 == current) {print prev; found=1; exit} prev=$0} END {if (!found) print prev}')"
RELEASE_BACKEND_REPO="${GITEA_REGISTRY}/darkhelm.org/deployable-backend"
RELEASE_FRONTEND_REPO="${GITEA_REGISTRY}/darkhelm.org/deployable-frontend"
RELEASE_BACKEND_REPO="${GITEA_REGISTRY}/darkhelm.org/plex-playlist-backend"
RELEASE_FRONTEND_REPO="${GITEA_REGISTRY}/darkhelm.org/plex-playlist-frontend"
BACKEND_RELEASE_VERSION_REF="${RELEASE_BACKEND_REPO}:${RELEASE_VERSION}"
BACKEND_RELEASE_TAGGED_REF="${RELEASE_BACKEND_REPO}:${RELEASE_TAGGED_VERSION}"

View File

@@ -180,7 +180,7 @@ jobs:
RENOVATE_NODE_ARGS: --max-old-space-size=768
RENOVATE_OSV_VULNERABILITY_ALERTS: "false"
RENOVATE_FETCH_CHANGELOGS: "off"
LOG_LEVEL: info
LOG_LEVEL: debug
run: |
set -euo pipefail
@@ -400,10 +400,10 @@ jobs:
# Manual workflow dispatch should execute immediately, regardless of repository schedule windows.
if [ "${GITHUB_EVENT_NAME:-}" = "workflow_dispatch" ]; then
export RENOVATE_IGNORE_SCHEDULE="true"
echo "✓ Manual run detected: ignoring Renovate schedule constraints"
export RENOVATE_FORCE='{"schedule":["at any time"]}'
echo "✓ Manual run detected: forcing Renovate outside schedule windows"
else
unset RENOVATE_IGNORE_SCHEDULE
unset RENOVATE_FORCE
fi
# Multi-batch runs must not prune branches created by earlier batches.
@@ -412,22 +412,16 @@ jobs:
run_renovate_with_endpoint() {
endpoint="$1"
enabled_managers="$2"
batch_label="$3"
batch_node_args="${RENOVATE_NODE_ARGS}"
batch_pr_limit="${RENOVATE_PR_CONCURRENT_LIMIT}"
batch_branch_limit="${RENOVATE_BRANCH_CONCURRENT_LIMIT}"
if [ "${batch_label}" = "npm" ]; then
batch_node_args="--max-old-space-size=1536"
batch_pr_limit="1"
batch_branch_limit="1"
fi
single_pass_node_args="${RENOVATE_NODE_ARGS}"
single_pass_pr_limit="${RENOVATE_PR_CONCURRENT_LIMIT}"
single_pass_branch_limit="${RENOVATE_BRANCH_CONCURRENT_LIMIT}"
export RENOVATE_ENDPOINT="${endpoint}"
echo "Running Renovate batch '${batch_label}' with endpoint: ${RENOVATE_ENDPOINT}"
echo "Enabled managers for '${batch_label}': ${enabled_managers}"
echo "Node args for '${batch_label}': ${batch_node_args}"
echo "PR/branch limits for '${batch_label}': ${batch_pr_limit}/${batch_branch_limit}"
echo "Running Renovate single pass with endpoint: ${RENOVATE_ENDPOINT}"
echo "Enabled managers: ${enabled_managers}"
echo "Node args: ${single_pass_node_args}"
echo "PR/branch limits: ${single_pass_pr_limit}/${single_pass_branch_limit}"
# shellcheck disable=SC2086
docker run --rm ${DOCKER_ADD_HOST_ARG} \
@@ -448,12 +442,12 @@ jobs:
-e RENOVATE_GIT_AUTHOR \
-e RENOVATE_ONBOARDING \
-e RENOVATE_REQUIRE_CONFIG \
-e RENOVATE_PR_CONCURRENT_LIMIT="${batch_pr_limit}" \
-e RENOVATE_BRANCH_CONCURRENT_LIMIT="${batch_branch_limit}" \
-e RENOVATE_NODE_ARGS="${batch_node_args}" \
-e RENOVATE_PR_CONCURRENT_LIMIT="${single_pass_pr_limit}" \
-e RENOVATE_BRANCH_CONCURRENT_LIMIT="${single_pass_branch_limit}" \
-e RENOVATE_NODE_ARGS="${single_pass_node_args}" \
-e RENOVATE_OSV_VULNERABILITY_ALERTS \
-e RENOVATE_FETCH_CHANGELOGS \
-e RENOVATE_IGNORE_SCHEDULE \
-e RENOVATE_FORCE \
-e RENOVATE_PRUNE_STALE_BRANCHES \
-e RENOVATE_ENABLED_MANAGERS="${enabled_managers}" \
--entrypoint /bin/sh \
@@ -469,30 +463,27 @@ jobs:
renovate --platform "${RENOVATE_PLATFORM}" --endpoint "${RENOVATE_ENDPOINT}" --git-url "${RENOVATE_GIT_URL}" --git-author "${RENOVATE_GIT_AUTHOR}" --onboarding="${RENOVATE_ONBOARDING}" --pr-concurrent-limit "${RENOVATE_PR_CONCURRENT_LIMIT}" --branch-concurrent-limit "${RENOVATE_BRANCH_CONCURRENT_LIMIT}" --osv-vulnerability-alerts="${RENOVATE_OSV_VULNERABILITY_ALERTS}" --enabled-managers "${RENOVATE_ENABLED_MANAGERS}" DarkHelm.org/plex-playlist'
}
run_batch_with_fallback() {
run_single_pass_with_fallback() {
enabled_managers="$1"
batch_label="$2"
if run_renovate_with_endpoint "${BASE_ENDPOINT}" "${enabled_managers}" "${batch_label}" 2>&1 | tee -a /tmp/renovate.log; then
if run_renovate_with_endpoint "${BASE_ENDPOINT}" "${enabled_managers}" 2>&1 | tee -a /tmp/renovate.log; then
return 0
fi
primary_status=$?
if [ "${primary_status}" -eq 137 ] || tail -n 400 /tmp/renovate.log | grep -qE '(^|[[:space:]])Killed($|[[:space:]])|exitcode '\''137'\''' ; then
echo "❌ Renovate batch '${batch_label}' terminated by OOM/kill signal on primary endpoint; skipping endpoint retry"
echo "❌ Renovate single pass terminated by OOM/kill signal on primary endpoint; skipping endpoint retry"
return "${primary_status}"
fi
echo "⚠ Renovate batch '${batch_label}' failed with primary endpoint. Retrying with API endpoint form..."
run_renovate_with_endpoint "${API_ENDPOINT}" "${enabled_managers}" "${batch_label}" 2>&1 | tee -a /tmp/renovate.log
echo "⚠ Renovate single pass failed with primary endpoint. Retrying with API endpoint form..."
run_renovate_with_endpoint "${API_ENDPOINT}" "${enabled_managers}" 2>&1 | tee -a /tmp/renovate.log
}
: > /tmp/renovate.log
# Run low-memory batches sequentially to keep peak usage below constrained runner limits.
run_batch_with_fallback "docker-compose,dockerfile" "containers"
run_batch_with_fallback "github-actions,pep621" "python-and-actions"
run_batch_with_fallback "npm" "npm"
# Run Renovate once across all enabled managers.
run_single_pass_with_fallback "docker-compose,dockerfile,github-actions,npm,pep621"
echo "✓ Renovate execution completed"

View File

@@ -1,8 +1,20 @@
# CICD Base Setup - System dependencies and language runtimes only
ARG PLAYWRIGHT_BROWSERS_IMAGE=mcr.microsoft.com/playwright:v1.61.1-jammy
ARG PLAYWRIGHT_VERSION=1.61.1
ARG PLAYWRIGHT_DISTRO=jammy
ARG PLAYWRIGHT_BROWSERS_IMAGE=mcr.microsoft.com/playwright:v${PLAYWRIGHT_VERSION}-${PLAYWRIGHT_DISTRO}
ARG UBUNTU_VERSION=26.04
FROM ${PLAYWRIGHT_BROWSERS_IMAGE} AS playwright-browsers
FROM ubuntu:22.04
FROM ubuntu:${UBUNTU_VERSION}
ARG PLAYWRIGHT_VERSION
ARG PYTHON_VERSION=3.14
ARG NODE_MAJOR=24
ARG TYPESCRIPT_VERSION=5.3.3
ARG ESLINT_VERSION=9.33.0
ARG PRETTIER_VERSION=3.6.2
ARG VITE_VERSION=7.1.10
ARG NODE_TYPES_VERSION=20.16.0
# Build args for cache busting (base dependencies change rarely)
ARG BASE_IMAGE_VERSION=v1.0.0
@@ -59,6 +71,11 @@ RUN set -eux; \
exit 1; \
fi; \
done; \
if apt-cache show libasound2t64 >/dev/null 2>&1; then \
asound_package=libasound2t64; \
else \
asound_package=libasound2; \
fi; \
apt-get install -y --no-install-recommends \
git \
curl \
@@ -77,15 +94,15 @@ RUN set -eux; \
libxrandr2 \
libgbm1 \
libxkbcommon0 \
libasound2 \
"$asound_package" \
tzdata \
gnupg \
wget \
&& rm -rf /var/lib/apt/lists/*
# Install Python 3.14 with retry and fallback mechanisms
# Install Python with retry and fallback mechanisms
RUN for i in 1 2 3; do \
echo "Attempt $i: Adding deadsnakes PPA..." && \
echo "Attempt $i: Adding deadsnakes PPA..." && \
add-apt-repository -y ppa:deadsnakes/ppa && \
find /etc/apt -type f \( -name 'sources.list' -o -name '*.sources' -o -name '*.list' \) -print0 | xargs -0 sed -i 's|http://|https://|g' && \
apt-get update && \
@@ -94,28 +111,38 @@ RUN for i in 1 2 3; do \
done
RUN for i in 1 2 3; do \
echo "Attempt $i: Installing Python 3.14..." && \
echo "Attempt $i: Installing Python ${PYTHON_VERSION}..." && \
timeout 300 apt-get install -y --no-install-recommends \
python3.14 \
python3.14-venv \
python3.14-dev && \
python${PYTHON_VERSION} \
python${PYTHON_VERSION}-venv \
python${PYTHON_VERSION}-dev && \
break || \
(echo "Attempt $i failed, retrying in 15s..." && sleep 15); \
done && \
rm -rf /var/lib/apt/lists/*
# Install Node.js 24 with retry mechanism
RUN for i in 1 2 3; do \
echo "Attempt $i: Installing Node.js 24..." && \
curl -fsSL --connect-timeout 30 --max-time 300 \
https://deb.nodesource.com/setup_24.x | bash - && \
find /etc/apt -type f \( -name 'sources.list' -o -name '*.sources' -o -name '*.list' \) -print0 | xargs -0 sed -i 's|http://|https://|g' && \
apt-get update && \
timeout 300 apt-get install -y --no-install-recommends nodejs && \
break || \
(echo "Attempt $i failed, retrying in 15s..." && sleep 15); \
done && \
rm -rf /var/lib/apt/lists/*
# Install Node.js with retry mechanism
RUN node_arch="$(dpkg --print-architecture)"; \
case "$node_arch" in \
amd64) node_tarball_arch=linux-x64 ;; \
arm64) node_tarball_arch=linux-arm64 ;; \
*) echo "unsupported architecture for Node.js tarball: $node_arch" >&2; exit 1 ;; \
esac; \
for i in 1 2 3; do \
echo "Attempt $i: Installing Node.js ${NODE_MAJOR}..."; \
node_version="$(python3 -c "import json, urllib.request; versions = json.load(urllib.request.urlopen('https://nodejs.org/dist/index.json')); print(next(item['version'].lstrip('v') for item in versions if item['version'].startswith('v${NODE_MAJOR}.')))" )"; \
if curl -fsSLO "https://nodejs.org/dist/v${node_version}/node-v${node_version}-${node_tarball_arch}.tar.xz" && \
tar -xJf "node-v${node_version}-${node_tarball_arch}.tar.xz" -C /usr/local --strip-components=1 && \
rm -f "node-v${node_version}-${node_tarball_arch}.tar.xz"; then \
break; \
fi; \
if [ "$i" -lt 3 ]; then \
echo "Attempt $i failed, retrying in 15s..."; \
sleep 15; \
else \
exit 1; \
fi; \
done
# Enable corepack for yarn and set up Yarn Berry
RUN corepack enable \
@@ -141,12 +168,12 @@ RUN set -eu && \
RUN echo "=== Installing Global Development Tools ===" && \
# Use npm for global installations (works better than yarn global in Berry)
npm install -g \
@playwright/test@1.56.1 \
typescript@5.3.3 \
eslint@9.33.0 \
prettier@3.6.2 \
vite@7.1.10 \
@types/node@20.16.0 && \
@playwright/test@${PLAYWRIGHT_VERSION} \
typescript@${TYPESCRIPT_VERSION} \
eslint@${ESLINT_VERSION} \
prettier@${PRETTIER_VERSION} \
vite@${VITE_VERSION} \
@types/node@${NODE_TYPES_VERSION} && \
# Verify global tools are available
which playwright && \
which tsc && \
@@ -207,7 +234,7 @@ RUN echo '#!/bin/bash' > /usr/local/bin/setup-ssh && \
# Verify that all base tools are working
RUN echo "=== Base System Verification ===" && \
python3.14 --version && \
python${PYTHON_VERSION} --version && \
node --version && \
yarn --version && \
uv --version && \

View File

@@ -1,4 +1,6 @@
ARG PLAYWRIGHT_BASE_IMAGE=mcr.microsoft.com/playwright:v1.61.1-jammy
ARG PLAYWRIGHT_VERSION=1.61.1
ARG PLAYWRIGHT_DISTRO=jammy
ARG PLAYWRIGHT_BASE_IMAGE=mcr.microsoft.com/playwright:v${PLAYWRIGHT_VERSION}-${PLAYWRIGHT_DISTRO}
FROM ${PLAYWRIGHT_BASE_IMAGE}
WORKDIR /workspace/frontend

View File

@@ -1,5 +1,9 @@
# Frontend Dockerfile for Vue/Vite TypeScript project
FROM node:24-alpine AS deps
ARG NODE_ALPINE_TAG=24-alpine
ARG YARN_VERSION=4.17.1
FROM node:${NODE_ALPINE_TAG} AS deps
ARG YARN_VERSION
WORKDIR /app
@@ -19,7 +23,8 @@ RUN set -eux; \
done; \
return 1; \
}; \
retry 5 npm install -g --force @yarnpkg/cli-dist@4.10.3; \
corepack enable; \
retry 5 corepack prepare yarn@${YARN_VERSION} --activate; \
retry 5 yarn install --immutable
FROM deps AS build

View File

@@ -4,23 +4,23 @@ requires = ["hatchling"]
[dependency-groups]
dev = [
"ruff==0.14.1",
"pyright==1.1.410",
"ruff==0.15.22",
"pyright==1.1.411",
"pydoclint==0.9.1",
"pytest==9.1.1",
"pytest-asyncio==1.4.0",
"pytest-cov==7.0.0",
"typeguard==4.4.4",
"pytest-cov==7.1.0",
"typeguard==4.5.2",
"httpx==0.28.1", # For testing async HTTP calls
"pytest-mock==3.15.1",
# File format and linting tools
"pre-commit==4.6.0", # For running pre-commit hooks in CI
"pre-commit==4.6.1", # For running pre-commit hooks in CI
"pyyaml==6.0.3",
"yamllint==1.37.1",
"toml-sort==0.24.3",
"yamllint==1.38.0",
"toml-sort==0.24.4",
"language-formatters-pre-commit-hooks==2.16.0", # For pretty-format-toml
"xdoctest==1.3.0", # For doctest support # Task runner for unified development workflows
"poethepoet==0.41.0",
"xdoctest==1.3.2", # For doctest support # Task runner for unified development workflows
"poethepoet==0.48.0",
"bandit>=1.9.4",
"pip-audit>=2.9.0"
]
@@ -35,9 +35,9 @@ classifiers = [
"Programming Language :: Python :: 3.14"
]
dependencies = [
"fastapi==0.139.0",
"fastapi==0.141.1",
"sqlalchemy==2.0.51",
"psycopg[binary]==3.2.12",
"psycopg[binary]==3.3.4",
"uvicorn==0.51.0"
]
description = "Backend service for Plex playlist management"

149
backend/uv.lock generated
View File

@@ -239,7 +239,7 @@ wheels = [
[[package]]
name = "fastapi"
version = "0.139.0"
version = "0.141.1"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "annotated-doc" },
@@ -248,9 +248,9 @@ dependencies = [
{ name = "typing-extensions" },
{ name = "typing-inspection" },
]
sdist = { url = "https://files.pythonhosted.org/packages/d3/af/a5f50ccfa659ec1802cb4ca842c23f06d906a8cc9aef6016a2caeea3d4ed/fastapi-0.139.0.tar.gz", hash = "sha256:99ab7b2d92223c76d6cf10757ab3f89d45b38267fc20b2a136cf02f6beac3145", size = 423016, upload-time = "2026-07-01T16:35:33.436Z" }
sdist = { url = "https://files.pythonhosted.org/packages/8a/02/91e3416a8fdd715abb903a952a6bec7cdd8d14eed55d415fc8595524c319/fastapi-0.141.1.tar.gz", hash = "sha256:e8822fc40db1e1858054d7a949a888695bc9bdce70139178e33bd2871a453ca1", size = 425799, upload-time = "2026-07-29T17:18:05.568Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/9e/7c/8e3c6ad324ea5cb36604fc3f968554887891c316d9dfde57761611d907ad/fastapi-0.139.0-py3-none-any.whl", hash = "sha256:cf15e1e9e667ddb0ad63811e60bd11390d1aac838ca4a7a23f421807b2308189", size = 130339, upload-time = "2026-07-01T16:35:32.19Z" },
{ url = "https://files.pythonhosted.org/packages/cb/03/10388a42375ee7e4ac9b94eb2c5c569c8b5795e377e701c9ac3ad63de890/fastapi-0.141.1-py3-none-any.whl", hash = "sha256:bfb91aa2d334c61cb35ba9a116fc123b3d3df31640b801cf57a7a78ec3f603b3", size = 131954, upload-time = "2026-07-29T17:18:04.364Z" },
]
[[package]]
@@ -482,11 +482,11 @@ wheels = [
[[package]]
name = "pathspec"
version = "0.12.1"
version = "1.1.1"
source = { registry = "https://pypi.org/simple" }
sdist = { url = "https://files.pythonhosted.org/packages/ca/bc/f35b8446f4531a7cb215605d100cd88b7ac6f44ab3fc94870c120ab3adbf/pathspec-0.12.1.tar.gz", hash = "sha256:a482d51503a1ab33b1c67a6c3813a26953dbdc71c31dacaef9a838c4e29f5712", size = 51043, upload-time = "2023-12-10T22:30:45Z" }
sdist = { url = "https://files.pythonhosted.org/packages/5a/82/42f767fc1c1143d6fd36efb827202a2d997a375e160a71eb2888a925aac1/pathspec-1.1.1.tar.gz", hash = "sha256:17db5ecd524104a120e173814c90367a96a98d07c45b2e10c2f3919fff91bf5a", size = 135180, upload-time = "2026-04-27T01:46:08.907Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/cc/20/ff623b09d963f88bfde16306a54e12ee5ea43e9b597108672ff3a408aad6/pathspec-0.12.1-py3-none-any.whl", hash = "sha256:a0d503e138a4c123b27490a4f7beda6a01c6f288df0e4a8b79c7eb0dc7b4cc08", size = 31191, upload-time = "2023-12-10T22:30:43.14Z" },
{ url = "https://files.pythonhosted.org/packages/f1/d9/7fb5aa316bc299258e68c73ba3bddbc499654a07f151cba08f6153988714/pathspec-1.1.1-py3-none-any.whl", hash = "sha256:a00ce642f577bf7f473932318056212bc4f8bfdf53128c78bbd5af0b9b20b189", size = 57328, upload-time = "2026-04-27T01:46:07.06Z" },
]
[[package]]
@@ -588,8 +588,8 @@ dev = [
[package.metadata]
requires-dist = [
{ name = "fastapi", specifier = "==0.139.0" },
{ name = "psycopg", extras = ["binary"], specifier = "==3.2.12" },
{ name = "fastapi", specifier = "==0.141.1" },
{ name = "psycopg", extras = ["binary"], specifier = "==3.3.4" },
{ name = "sqlalchemy", specifier = "==2.0.51" },
{ name = "uvicorn", specifier = "==0.51.0" },
]
@@ -600,20 +600,20 @@ dev = [
{ name = "httpx", specifier = "==0.28.1" },
{ name = "language-formatters-pre-commit-hooks", specifier = "==2.16.0" },
{ name = "pip-audit", specifier = ">=2.9.0" },
{ name = "poethepoet", specifier = "==0.41.0" },
{ name = "pre-commit", specifier = "==4.6.0" },
{ name = "poethepoet", specifier = "==0.48.0" },
{ name = "pre-commit", specifier = "==4.6.1" },
{ name = "pydoclint", specifier = "==0.9.1" },
{ name = "pyright", specifier = "==1.1.410" },
{ name = "pyright", specifier = "==1.1.411" },
{ name = "pytest", specifier = "==9.1.1" },
{ name = "pytest-asyncio", specifier = "==1.4.0" },
{ name = "pytest-cov", specifier = "==7.0.0" },
{ name = "pytest-cov", specifier = "==7.1.0" },
{ name = "pytest-mock", specifier = "==3.15.1" },
{ name = "pyyaml", specifier = "==6.0.3" },
{ name = "ruff", specifier = "==0.14.1" },
{ name = "toml-sort", specifier = "==0.24.3" },
{ name = "typeguard", specifier = "==4.4.4" },
{ name = "xdoctest", specifier = "==1.3.0" },
{ name = "yamllint", specifier = "==1.37.1" },
{ name = "ruff", specifier = "==0.15.22" },
{ name = "toml-sort", specifier = "==0.24.4" },
{ name = "typeguard", specifier = "==4.5.2" },
{ name = "xdoctest", specifier = "==1.3.2" },
{ name = "yamllint", specifier = "==1.38.0" },
]
[[package]]
@@ -627,20 +627,20 @@ wheels = [
[[package]]
name = "poethepoet"
version = "0.41.0"
version = "0.48.0"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "pastel" },
{ name = "pyyaml" },
]
sdist = { url = "https://files.pythonhosted.org/packages/a8/b9/fa92286560f70eaa40d473ea48376d20c6c21f63627d33c6bb1c5e385175/poethepoet-0.41.0.tar.gz", hash = "sha256:dcaad621dc061f6a90b17d091bebb9ca043d67bfe9bd6aa4185aea3ebf7ff3e6", size = 87780, upload-time = "2026-02-08T20:45:36.061Z" }
sdist = { url = "https://files.pythonhosted.org/packages/5c/92/93a4af9511b8c7c647874521d9e6c904266be98067c2ee1eb2e74520d208/poethepoet-0.48.0.tar.gz", hash = "sha256:a06f49d244fadfc2e2e7faa78b54e64a9694727e4ce1d50e08f23cea3ded74f1", size = 148679, upload-time = "2026-07-05T21:48:30.106Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/5d/5e/0b83e0222ce5921b3f9081eeca8c6fb3e1cfd5ca0d06338adf93b28ce061/poethepoet-0.41.0-py3-none-any.whl", hash = "sha256:4bab9fd8271664c5d21407e8f12827daeb6aa484dc6cc7620f0c3b4e62b42ee4", size = 113590, upload-time = "2026-02-08T20:45:34.697Z" },
{ url = "https://files.pythonhosted.org/packages/59/8d/d7c9455b15f8d2d7ce57e7b71a8ef8d02d9992ae4283c9777120620c9022/poethepoet-0.48.0-py3-none-any.whl", hash = "sha256:98da6096d060f49b8d84034770265863fb7dc92a40233b7694b9d216ac68737d", size = 185808, upload-time = "2026-07-05T21:48:28.601Z" },
]
[[package]]
name = "pre-commit"
version = "4.6.0"
version = "4.6.1"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "cfgv" },
@@ -649,21 +649,21 @@ dependencies = [
{ name = "pyyaml" },
{ name = "virtualenv" },
]
sdist = { url = "https://files.pythonhosted.org/packages/8e/22/2de9408ac81acbb8a7d05d4cc064a152ccf33b3d480ebe0cd292153db239/pre_commit-4.6.0.tar.gz", hash = "sha256:718d2208cef53fdc38206e40524a6d4d9576d103eb16f0fec11c875e7716e9d9", size = 198525, upload-time = "2026-04-21T20:31:41.613Z" }
sdist = { url = "https://files.pythonhosted.org/packages/25/3a/ddb78f32a0814e66b18a099377a106a2dcdce92d86a034d69d65df9b256e/pre_commit-4.6.1.tar.gz", hash = "sha256:03e809865c7d178b9979d06c761fcbfe6808fdaded8581a745bb110e52050421", size = 198646, upload-time = "2026-07-21T20:56:58.225Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/80/6e/4b28b62ecb6aae56769c34a8ff1d661473ec1e9519e2d5f8b2c150086b26/pre_commit-4.6.0-py2.py3-none-any.whl", hash = "sha256:e2cf246f7299edcabcf15f9b0571fdce06058527f0a06535068a86d38089f29b", size = 226472, upload-time = "2026-04-21T20:31:40.092Z" },
{ url = "https://files.pythonhosted.org/packages/fb/49/bc925106abcdac498074f2cbe6137e94e09f418dd2b7775df5b577dc0313/pre_commit-4.6.1-py2.py3-none-any.whl", hash = "sha256:0e3b2942510d1fb34eec167a3ec57331bf8442122f1153a9fb8b58f5c49b2717", size = 226186, upload-time = "2026-07-21T20:56:57.064Z" },
]
[[package]]
name = "psycopg"
version = "3.2.12"
version = "3.3.4"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "tzdata", marker = "sys_platform == 'win32'" },
]
sdist = { url = "https://files.pythonhosted.org/packages/a8/77/c72d10262b872617e509a0c60445afcc4ce2cd5cd6bc1c97700246d69c85/psycopg-3.2.12.tar.gz", hash = "sha256:85c08d6f6e2a897b16280e0ff6406bef29b1327c045db06d21f364d7cd5da90b", size = 160642, upload-time = "2025-10-26T00:46:03.045Z" }
sdist = { url = "https://files.pythonhosted.org/packages/db/2f/cb91e5502ec9de1de6f1b76cfbf69531932725361168bb06963620c77e2e/psycopg-3.3.4.tar.gz", hash = "sha256:e21207764952cff81b6b8bdacad9a3939f2793367fdac2987b3aac36a651b5bc", size = 165799, upload-time = "2026-05-01T23:31:55.179Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/c8/28/8c4f90e415411dc9c78d6ba10b549baa324659907c13f64bfe3779d4066c/psycopg-3.2.12-py3-none-any.whl", hash = "sha256:8a1611a2d4c16ae37eada46438be9029a35bb959bb50b3d0e1e93c0f3d54c9ee", size = 206765, upload-time = "2025-10-26T00:10:42.173Z" },
{ url = "https://files.pythonhosted.org/packages/5c/e0/7b3dee031daae7743609ce3c746565d4a3ed7c2c186479eb48e34e838c64/psycopg-3.3.4-py3-none-any.whl", hash = "sha256:b6bbc25ccf05c8fad3b061d9db2ef0909a555171b84b07f29458a447253d679a", size = 213001, upload-time = "2026-05-01T23:20:50.816Z" },
]
[package.optional-dependencies]
@@ -673,18 +673,20 @@ binary = [
[[package]]
name = "psycopg-binary"
version = "3.2.12"
version = "3.3.4"
source = { registry = "https://pypi.org/simple" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/5c/5b/76fbb40b981b73b285a00dccafc38cf67b7a9b3f7d4f2025dda7b896e7ef/psycopg_binary-3.2.12-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:dc68094e00a5a7e8c20de1d3a0d5e404a27f522e18f8eb62bbbc9f865c3c81ef", size = 4016868, upload-time = "2025-10-26T00:31:29.974Z" },
{ url = "https://files.pythonhosted.org/packages/0e/08/8841ae3e2d1a3228e79eaaf5b7f991d15f0a231bb5031a114305b19724b1/psycopg_binary-3.2.12-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:2d55009eeddbef54c711093c986daaf361d2c4210aaa1ee905075a3b97a62441", size = 4090508, upload-time = "2025-10-26T00:32:04.192Z" },
{ url = "https://files.pythonhosted.org/packages/05/de/a41f62230cf4095ae4547eceada218cf28c17e7f94376913c1c8dde9546f/psycopg_binary-3.2.12-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:66a031f22e4418016990446d3e38143826f03ad811b9f78f58e2afbc1d343f7a", size = 4629788, upload-time = "2025-10-26T00:32:43.28Z" },
{ url = "https://files.pythonhosted.org/packages/45/19/529d92134eae44475f781a86d58cdf3edd0953e17c69762abf387a9f2636/psycopg_binary-3.2.12-cp314-cp314-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:58ed30d33c25d7dc8d2f06285e88493147c2a660cc94713e4b563a99efb80a1f", size = 4724124, upload-time = "2025-10-26T00:33:22.594Z" },
{ url = "https://files.pythonhosted.org/packages/5c/f5/97344e87065f7c9713ce213a2cff7732936ec3af6622e4b2a88715a953f2/psycopg_binary-3.2.12-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:e0b5ccd03ca4749b8f66f38608ccbcb415cbd130d02de5eda80d042b83bee90e", size = 4411340, upload-time = "2025-10-26T00:34:00.759Z" },
{ url = "https://files.pythonhosted.org/packages/b1/c2/34bce068f6bfb4c2e7bb1187bb64a3f3be254702b158c4ad05eacc0055cf/psycopg_binary-3.2.12-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:909de94de7dd4d6086098a5755562207114c9638ec42c52d84c8a440c45fe084", size = 3867815, upload-time = "2025-10-26T00:34:33.181Z" },
{ url = "https://files.pythonhosted.org/packages/d1/a1/c647e01ab162e6bfa52380e23e486215e9d28ffd31e9cf3cb1e9ca59008b/psycopg_binary-3.2.12-cp314-cp314-musllinux_1_2_ppc64le.whl", hash = "sha256:7130effd0517881f3a852eff98729d51034128f0737f64f0d1c7ea8343d77bd7", size = 3541756, upload-time = "2025-10-26T00:35:08.622Z" },
{ url = "https://files.pythonhosted.org/packages/6b/d0/795bdaa8c946a7b7126bf7ca8d4371eaaa613093e3ec341a0e50f52cbee2/psycopg_binary-3.2.12-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:89b3c5201ca616d69ca0c3c0003ca18f7170a679c445c7e386ebfb4f29aa738e", size = 3587950, upload-time = "2025-10-26T00:35:41.183Z" },
{ url = "https://files.pythonhosted.org/packages/53/cf/10c3e95827a3ca8af332dfc471befec86e15a14dc83cee893c49a4910dad/psycopg_binary-3.2.12-cp314-cp314-win_amd64.whl", hash = "sha256:48a8e29f3e38fcf8d393b8fe460d83e39c107ad7e5e61cd3858a7569e0554a39", size = 3005787, upload-time = "2025-10-26T00:36:06.783Z" },
{ url = "https://files.pythonhosted.org/packages/48/a6/828c9185701dab71b234c2a76c38a08b098ebfec5020716b4e93807492b5/psycopg_binary-3.3.4-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:28b7398fdd19db3232c884fb24550bdfe951221f510e195e233299e4c9b78f97", size = 4607292, upload-time = "2026-05-01T23:30:38.962Z" },
{ url = "https://files.pythonhosted.org/packages/92/58/5b40dbc9d839045c9dae956960e4fb6d20bcabe6c59a2aa34fc3a371913f/psycopg_binary-3.3.4-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:1fbaa292a3c8bb61b45df1ad3da1908ccee7cb889db9425e3557d9e34e2a4829", size = 4687023, upload-time = "2026-05-01T23:30:47.227Z" },
{ url = "https://files.pythonhosted.org/packages/85/a9/793f0ac107a9003b48441d0d1f9f616d96e0f37458dd8dc12528ceff55fb/psycopg_binary-3.3.4-cp314-cp314-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:94596f9e7633ee3f6440711d43bb70aa31cc0a46a900ab8b4201a366ace5c9e7", size = 5486985, upload-time = "2026-05-01T23:30:55.517Z" },
{ url = "https://files.pythonhosted.org/packages/8f/26/42e8533497e2592334f68ec529cf5f840f7fa4e99575a4bb61aa184dbfbf/psycopg_binary-3.3.4-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:8c0056529e68dbe9184cd4019a1f3d8f3a4ead2f6fc7a5afcf27d3314edd1277", size = 5168745, upload-time = "2026-05-01T23:31:01.904Z" },
{ url = "https://files.pythonhosted.org/packages/15/af/b7151776cc08d5935d45c833ec818a9beb417cf7c08239af1aafbdae78ee/psycopg_binary-3.3.4-cp314-cp314-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:2c09aad7051326e7603c14e50636db9c01f78272dc54b3accff03d46370461e6", size = 6761486, upload-time = "2026-05-01T23:31:14.511Z" },
{ url = "https://files.pythonhosted.org/packages/d0/ed/c92533b9124712d592cbf1cd6c76da933a2e0acea81dfe1fbe7e735f0cff/psycopg_binary-3.3.4-cp314-cp314-manylinux_2_38_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:514404ed543efd620c85602b747df2a23cf1241b4067199e1a66f2d2757aaa41", size = 4997427, upload-time = "2026-05-01T23:31:20.901Z" },
{ url = "https://files.pythonhosted.org/packages/a2/23/ccadfd0de416aa188356daa199453af24087b042e296088706d190ae0295/psycopg_binary-3.3.4-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:46893c26858be12cc49ca4226ed6a60b4bfccadd946b3bebb783a60b38788228", size = 4533549, upload-time = "2026-05-01T23:31:26.204Z" },
{ url = "https://files.pythonhosted.org/packages/fd/a0/c8f43cee36386f7bc891ab41a9d31ea07cf9826038e732da79f26b1e5f34/psycopg_binary-3.3.4-cp314-cp314-musllinux_1_2_ppc64le.whl", hash = "sha256:df1d567fc430f6df15c9fcf67d87685fc49bdb325adc0db5af1adfb2f44eb5c9", size = 4210256, upload-time = "2026-05-01T23:31:33.884Z" },
{ url = "https://files.pythonhosted.org/packages/4e/2c/c1547871be3790676e8868b38655496422f94f0978dfb66b74bdba2f1676/psycopg_binary-3.3.4-cp314-cp314-musllinux_1_2_riscv64.whl", hash = "sha256:6b9016b1714da4dd5ecaaa75b82098aa5a0b87854ce9b092e21c27c4ae23e014", size = 3946204, upload-time = "2026-05-01T23:31:39.626Z" },
{ url = "https://files.pythonhosted.org/packages/c4/b1/f6670f00fa7ea601584623f6c11602ab92117d83eaff885e0210f6de7418/psycopg_binary-3.3.4-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:47c656a8a7ba6eb0cff1801a4caaa9c8bdc12d03080e273aff1c8ac39971a77e", size = 4255811, upload-time = "2026-05-01T23:31:44.986Z" },
{ url = "https://files.pythonhosted.org/packages/eb/e6/5fff07a70d1f945ed90ae131c3bd76cab32beff7c58c6db15ad5820b6d1f/psycopg_binary-3.3.4-cp314-cp314-win_amd64.whl", hash = "sha256:c37e024c07308cd06cf3ec51bfd0e7f6157585a4d84d1bce4a7f5f7913719bf8", size = 3666849, upload-time = "2026-05-01T23:31:51.165Z" },
]
[[package]]
@@ -777,15 +779,15 @@ wheels = [
[[package]]
name = "pyright"
version = "1.1.410"
version = "1.1.411"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "nodeenv" },
{ name = "typing-extensions" },
]
sdist = { url = "https://files.pythonhosted.org/packages/10/53/e4d8ea1391bd4355231be6f91bf239479aa0014260ed3fb5526eeb12a1f2/pyright-1.1.410.tar.gz", hash = "sha256:07a073b8ba6749826773c1269773efa11b93440d9a6aa60419d9a3172d6dc488", size = 4062013, upload-time = "2026-06-01T17:35:48.894Z" }
sdist = { url = "https://files.pythonhosted.org/packages/7e/ab/265f7dc69d28113ebba19092e57b075f41543b2ed048429c5f56e2b88eac/pyright-1.1.411.tar.gz", hash = "sha256:d885a0551f2e763b089a02702174e7f4ba77548cddabc972ab86d1f7f1b0f998", size = 4112861, upload-time = "2026-06-25T02:14:06.37Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/d7/33/288b5868fa00846dacf249633719d747893e54aebd196b9968ac1878a5d3/pyright-1.1.410-py3-none-any.whl", hash = "sha256:5e961bed37cacf96b3f7cd7b1da39b350a9239aa2e69138d0e88f728cfaf296c", size = 6082448, upload-time = "2026-06-01T17:35:46.387Z" },
{ url = "https://files.pythonhosted.org/packages/0a/49/385be530a6a5b78d1cbcd5c2e38debc8959a2fc6bdb716f4e581002979fc/pyright-1.1.411-py3-none-any.whl", hash = "sha256:dc7c72a8e2700c55baa127554040e067041ea53ccfd50bf96308cc4291c7d5d9", size = 6181526, upload-time = "2026-06-25T02:14:04.691Z" },
]
[[package]]
@@ -818,16 +820,16 @@ wheels = [
[[package]]
name = "pytest-cov"
version = "7.0.0"
version = "7.1.0"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "coverage" },
{ name = "pluggy" },
{ name = "pytest" },
]
sdist = { url = "https://files.pythonhosted.org/packages/5e/f7/c933acc76f5208b3b00089573cf6a2bc26dc80a8aece8f52bb7d6b1855ca/pytest_cov-7.0.0.tar.gz", hash = "sha256:33c97eda2e049a0c5298e91f519302a1334c26ac65c1a483d6206fd458361af1", size = 54328, upload-time = "2025-09-09T10:57:02.113Z" }
sdist = { url = "https://files.pythonhosted.org/packages/b1/51/a849f96e117386044471c8ec2bd6cfebacda285da9525c9106aeb28da671/pytest_cov-7.1.0.tar.gz", hash = "sha256:30674f2b5f6351aa09702a9c8c364f6a01c27aae0c1366ae8016160d1efc56b2", size = 55592, upload-time = "2026-03-21T20:11:16.284Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/ee/49/1377b49de7d0c1ce41292161ea0f721913fa8722c19fb9c1e3aa0367eecb/pytest_cov-7.0.0-py3-none-any.whl", hash = "sha256:3b8e9558b16cc1479da72058bdecf8073661c7f57f7d3c5f22a1c23507f2d861", size = 22424, upload-time = "2025-09-09T10:57:00.695Z" },
{ url = "https://files.pythonhosted.org/packages/9d/7a/d968e294073affff457b041c2be9868a40c1c71f4a35fcc1e45e5493067b/pytest_cov-7.1.0-py3-none-any.whl", hash = "sha256:a0461110b7865f9a271aa1b51e516c9a95de9d696734a2f71e3e78f46e1d4678", size = 22876, upload-time = "2026-03-21T20:11:14.438Z" },
]
[[package]]
@@ -907,28 +909,27 @@ wheels = [
[[package]]
name = "ruff"
version = "0.14.1"
version = "0.15.22"
source = { registry = "https://pypi.org/simple" }
sdist = { url = "https://files.pythonhosted.org/packages/9e/58/6ca66896635352812de66f71cdf9ff86b3a4f79071ca5730088c0cd0fc8d/ruff-0.14.1.tar.gz", hash = "sha256:1dd86253060c4772867c61791588627320abcb6ed1577a90ef432ee319729b69", size = 5513429, upload-time = "2025-10-16T18:05:41.766Z" }
sdist = { url = "https://files.pythonhosted.org/packages/3a/06/ae069393fc66e8ff33036d4b368003833bf6e88ccf182e17e7a2f1c754fd/ruff-0.15.22.tar.gz", hash = "sha256:3f15175b1fb580126f58285a5dae6b2ea89000136d980c64499211f116b54809", size = 4785063, upload-time = "2026-07-16T15:14:13.244Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/8d/39/9cc5ab181478d7a18adc1c1e051a84ee02bec94eb9bdfd35643d7c74ca31/ruff-0.14.1-py3-none-linux_armv6l.whl", hash = "sha256:083bfc1f30f4a391ae09c6f4f99d83074416b471775b59288956f5bc18e82f8b", size = 12445415, upload-time = "2025-10-16T18:04:48.227Z" },
{ url = "https://files.pythonhosted.org/packages/ef/2e/1226961855ccd697255988f5a2474890ac7c5863b080b15bd038df820818/ruff-0.14.1-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:f6fa757cd717f791009f7669fefb09121cc5f7d9bd0ef211371fad68c2b8b224", size = 12784267, upload-time = "2025-10-16T18:04:52.515Z" },
{ url = "https://files.pythonhosted.org/packages/c1/ea/fd9e95863124ed159cd0667ec98449ae461de94acda7101f1acb6066da00/ruff-0.14.1-py3-none-macosx_11_0_arm64.whl", hash = "sha256:d6191903d39ac156921398e9c86b7354d15e3c93772e7dbf26c9fcae59ceccd5", size = 11781872, upload-time = "2025-10-16T18:04:55.396Z" },
{ url = "https://files.pythonhosted.org/packages/1e/5a/e890f7338ff537dba4589a5e02c51baa63020acfb7c8cbbaea4831562c96/ruff-0.14.1-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ed04f0e04f7a4587244e5c9d7df50e6b5bf2705d75059f409a6421c593a35896", size = 12226558, upload-time = "2025-10-16T18:04:58.166Z" },
{ url = "https://files.pythonhosted.org/packages/a6/7a/8ab5c3377f5bf31e167b73651841217542bcc7aa1c19e83030835cc25204/ruff-0.14.1-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:5c9e6cf6cd4acae0febbce29497accd3632fe2025c0c583c8b87e8dbdeae5f61", size = 12187898, upload-time = "2025-10-16T18:05:01.455Z" },
{ url = "https://files.pythonhosted.org/packages/48/8d/ba7c33aa55406955fc124e62c8259791c3d42e3075a71710fdff9375134f/ruff-0.14.1-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a6fa2458527794ecdfbe45f654e42c61f2503a230545a91af839653a0a93dbc6", size = 12939168, upload-time = "2025-10-16T18:05:04.397Z" },
{ url = "https://files.pythonhosted.org/packages/b4/c2/70783f612b50f66d083380e68cbd1696739d88e9b4f6164230375532c637/ruff-0.14.1-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:39f1c392244e338b21d42ab29b8a6392a722c5090032eb49bb4d6defcdb34345", size = 14386942, upload-time = "2025-10-16T18:05:07.102Z" },
{ url = "https://files.pythonhosted.org/packages/48/44/cd7abb9c776b66d332119d67f96acf15830d120f5b884598a36d9d3f4d83/ruff-0.14.1-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:7382fa12a26cce1f95070ce450946bec357727aaa428983036362579eadcc5cf", size = 13990622, upload-time = "2025-10-16T18:05:09.882Z" },
{ url = "https://files.pythonhosted.org/packages/eb/56/4259b696db12ac152fe472764b4f78bbdd9b477afd9bc3a6d53c01300b37/ruff-0.14.1-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:dd0bf2be3ae8521e1093a487c4aa3b455882f139787770698530d28ed3fbb37c", size = 13431143, upload-time = "2025-10-16T18:05:13.46Z" },
{ url = "https://files.pythonhosted.org/packages/e0/35/266a80d0eb97bd224b3265b9437bd89dde0dcf4faf299db1212e81824e7e/ruff-0.14.1-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:cabcaa9ccf8089fb4fdb78d17cc0e28241520f50f4c2e88cb6261ed083d85151", size = 13132844, upload-time = "2025-10-16T18:05:16.1Z" },
{ url = "https://files.pythonhosted.org/packages/65/6e/d31ce218acc11a8d91ef208e002a31acf315061a85132f94f3df7a252b18/ruff-0.14.1-py3-none-manylinux_2_31_riscv64.whl", hash = "sha256:747d583400f6125ec11a4c14d1c8474bf75d8b419ad22a111a537ec1a952d192", size = 13401241, upload-time = "2025-10-16T18:05:19.395Z" },
{ url = "https://files.pythonhosted.org/packages/9f/b5/dbc4221bf0b03774b3b2f0d47f39e848d30664157c15b965a14d890637d2/ruff-0.14.1-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:5a6e74c0efd78515a1d13acbfe6c90f0f5bd822aa56b4a6d43a9ffb2ae6e56cd", size = 12132476, upload-time = "2025-10-16T18:05:22.163Z" },
{ url = "https://files.pythonhosted.org/packages/98/4b/ac99194e790ccd092d6a8b5f341f34b6e597d698e3077c032c502d75ea84/ruff-0.14.1-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:0ea6a864d2fb41a4b6d5b456ed164302a0d96f4daac630aeba829abfb059d020", size = 12139749, upload-time = "2025-10-16T18:05:25.162Z" },
{ url = "https://files.pythonhosted.org/packages/47/26/7df917462c3bb5004e6fdfcc505a49e90bcd8a34c54a051953118c00b53a/ruff-0.14.1-py3-none-musllinux_1_2_i686.whl", hash = "sha256:0826b8764f94229604fa255918d1cc45e583e38c21c203248b0bfc9a0e930be5", size = 12544758, upload-time = "2025-10-16T18:05:28.018Z" },
{ url = "https://files.pythonhosted.org/packages/64/d0/81e7f0648e9764ad9b51dd4be5e5dac3fcfff9602428ccbae288a39c2c22/ruff-0.14.1-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:cbc52160465913a1a3f424c81c62ac8096b6a491468e7d872cb9444a860bc33d", size = 13221811, upload-time = "2025-10-16T18:05:30.707Z" },
{ url = "https://files.pythonhosted.org/packages/c3/07/3c45562c67933cc35f6d5df4ca77dabbcd88fddaca0d6b8371693d29fd56/ruff-0.14.1-py3-none-win32.whl", hash = "sha256:e037ea374aaaff4103240ae79168c0945ae3d5ae8db190603de3b4012bd1def6", size = 12319467, upload-time = "2025-10-16T18:05:33.261Z" },
{ url = "https://files.pythonhosted.org/packages/02/88/0ee4ca507d4aa05f67e292d2e5eb0b3e358fbcfe527554a2eda9ac422d6b/ruff-0.14.1-py3-none-win_amd64.whl", hash = "sha256:59d599cdff9c7f925a017f6f2c256c908b094e55967f93f2821b1439928746a1", size = 13401123, upload-time = "2025-10-16T18:05:35.984Z" },
{ url = "https://files.pythonhosted.org/packages/b8/81/4b6387be7014858d924b843530e1b2a8e531846807516e9bea2ee0936bf7/ruff-0.14.1-py3-none-win_arm64.whl", hash = "sha256:e3b443c4c9f16ae850906b8d0a707b2a4c16f8d2f0a7fe65c475c5886665ce44", size = 12436636, upload-time = "2025-10-16T18:05:38.995Z" },
{ url = "https://files.pythonhosted.org/packages/23/18/ee54b7ae1e121be7a28ea6da4b67564ebb0530e183a54415ab7e3bcd2c4e/ruff-0.15.22-py3-none-linux_armv6l.whl", hash = "sha256:44423e73493737f5e7c5b41d475483898ff37afcdae38bc3da5085e29af1c2d8", size = 10781258, upload-time = "2026-07-16T15:13:19.452Z" },
{ url = "https://files.pythonhosted.org/packages/2f/d2/2520cb14761ddbeaf57642a76942fc36adcbdbe53b4532241995f6fc485c/ruff-0.15.22-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:b82c6482946e9eda7ff2e091d25b8bad3f718684e1916d41bd56873cee05b697", size = 10999477, upload-time = "2026-07-16T15:13:23.318Z" },
{ url = "https://files.pythonhosted.org/packages/c9/10/74e53572aa758dfaa678c2a2646b5c5515d884b7ca56be4d2ce03ca4b560/ruff-0.15.22-py3-none-macosx_11_0_arm64.whl", hash = "sha256:11c1c715af53a09f714e011106bffc419751ec8232fcb5da42173284ea3fec6f", size = 10466716, upload-time = "2026-07-16T15:13:26.162Z" },
{ url = "https://files.pythonhosted.org/packages/1e/cc/44eaaf0844e028182f2d0a8f2190d0f359159aed0a9e5ab861d892f1ae2a/ruff-0.15.22-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:742a29cf29bddb7c8327895d6a10e0e6c5b38a96dd407af9b5d0857f809c0576", size = 10892644, upload-time = "2026-07-16T15:13:29.229Z" },
{ url = "https://files.pythonhosted.org/packages/9f/21/8edf559014d2b0f82beea19cfb713993ad802ccda16868769979c6090a84/ruff-0.15.22-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:72af58b951b0ae395935ae79763dc349bc0eb706319d28f7a33ad2cfb3cfc178", size = 10576719, upload-time = "2026-07-16T15:13:32.35Z" },
{ url = "https://files.pythonhosted.org/packages/bf/1e/3a13abd392a3b50b62e5938a831f9ab6e588358cacad5c18545b716d2182/ruff-0.15.22-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:62d425005c1835eb24e2ee4161cb90e8db263415f4a71c8c72c33abaa6c0c224", size = 11376494, upload-time = "2026-07-16T15:13:35.958Z" },
{ url = "https://files.pythonhosted.org/packages/bf/3e/422d3d95bcf04dd78e1aeac22184d4f9a8fb2c01865d39d44618484a0317/ruff-0.15.22-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e8b9b3f8779a4f08c969defc3c8c35abffaa757e601ed5ae66d6d1db6519969a", size = 12208370, upload-time = "2026-07-16T15:13:39.185Z" },
{ url = "https://files.pythonhosted.org/packages/1e/91/5d065a0e0a02bf4813f5119ad278462eed081d2b832eb7c021ade0ec9e65/ruff-0.15.22-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:1e0dd1b2e4d3d585f897a0d137cbf4eaf6223bef4e8ce34d6bb12556c5f9249e", size = 11581098, upload-time = "2026-07-16T15:13:42.132Z" },
{ url = "https://files.pythonhosted.org/packages/f6/f9/a0d4871d12fae702eb1f41b686caf05f1f8b124dc6db6f784f53d74918fa/ruff-0.15.22-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:365523eb91d9224e1bcb03b022fbf0facb8f9e23792a2c53d9d4b3924bdbdebb", size = 11399422, upload-time = "2026-07-16T15:13:45.2Z" },
{ url = "https://files.pythonhosted.org/packages/18/80/c843a5176cddbceb0b7e8dd41cf9993490796c1c469348d384f5a5c13c56/ruff-0.15.22-py3-none-manylinux_2_31_riscv64.whl", hash = "sha256:fabfd168afdf29fee5be98b831efa9683c94d7c5a3b58b9ce5a2e38444589a74", size = 11381683, upload-time = "2026-07-16T15:13:48.46Z" },
{ url = "https://files.pythonhosted.org/packages/d4/00/8485de0ae92239438a36cfc51350db9b9e85c9ebdfaea91b18e422706662/ruff-0.15.22-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:225dbf095a87f1d9f90f5fd7924d2613ee452a75a4308c63a8f50f761787aa7c", size = 10850295, upload-time = "2026-07-16T15:13:51.655Z" },
{ url = "https://files.pythonhosted.org/packages/fa/91/24977ec2ec72eaf15e4394ace2959fdff2dd1e14f03e005e838023407169/ruff-0.15.22-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:1877d63b9d24ed278744f1523fd11b85540566d54641f97c566d7d9dc5ca5296", size = 10579640, upload-time = "2026-07-16T15:13:54.79Z" },
{ url = "https://files.pythonhosted.org/packages/9c/47/9b51216951974df1f263ac19da550d34252e0ed7218c25f10c5ef9ed7517/ruff-0.15.22-py3-none-musllinux_1_2_i686.whl", hash = "sha256:a1606c510bd7215680d32efab38965f7cdec3ef69f5170a3f4791404ffdd5262", size = 11105077, upload-time = "2026-07-16T15:13:57.915Z" },
{ url = "https://files.pythonhosted.org/packages/c2/47/20e9d4a3b8016778acea5fc32bb50d35d207500a17ddb529ffa6996feef8/ruff-0.15.22-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:630479b18625f5ffc373f77603a22a9f8ac0acd7ff0501178b5db28ec71e9c64", size = 11490980, upload-time = "2026-07-16T15:14:01.032Z" },
{ url = "https://files.pythonhosted.org/packages/4d/76/3f72d8fc38c1cb77b38c56a70da9d0c17700cc1cc50f9649c9d3c8f5ba71/ruff-0.15.22-py3-none-win32.whl", hash = "sha256:e5ba0e4a13fd14abbed2a77b517a3911290c6c6c59ef67784328d1668fab76cf", size = 10789165, upload-time = "2026-07-16T15:14:04.16Z" },
{ url = "https://files.pythonhosted.org/packages/cb/46/4965251734c2b6fcdca1b1b187d20bcac3af0ee5b083b89c910bb961ce3a/ruff-0.15.22-py3-none-win_amd64.whl", hash = "sha256:9be63ba1eb936acd2d1342fb8337c356353706fce233b2a15a09a97037e6acde", size = 11938297, upload-time = "2026-07-16T15:14:07.316Z" },
{ url = "https://files.pythonhosted.org/packages/57/c9/e69b1ff4c8b69093ef08b8919ab767af0569666865b39c30a8795d88d3c6/ruff-0.15.22-py3-none-win_arm64.whl", hash = "sha256:e1168075b72158510839f250027659cdd78476f40507dd517892304c41318661", size = 11298172, upload-time = "2026-07-16T15:14:10.51Z" },
]
[[package]]
@@ -999,14 +1000,14 @@ wheels = [
[[package]]
name = "toml-sort"
version = "0.24.3"
version = "0.24.4"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "tomlkit" },
]
sdist = { url = "https://files.pythonhosted.org/packages/15/65/d62fb175769355a65c2c5e53a155cf28f2162af4e4067f11d8af89c0a4a3/toml_sort-0.24.3.tar.gz", hash = "sha256:74c3cab5c1ecaf76c8239addc15342de548fb39598694f1298550d0fe2673a81", size = 17773, upload-time = "2025-09-10T02:43:54.955Z" }
sdist = { url = "https://files.pythonhosted.org/packages/47/c5/d6f650fdcf8e1f83096815fa67fb13a9a345b99da6015c60c4b7e4a8ea2b/toml_sort-0.24.4.tar.gz", hash = "sha256:429b69f5b98b7047a11380c80ecf0838556bdea1a8902d0be564961c48841423", size = 17793, upload-time = "2026-03-24T14:05:53.637Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/0e/1c/f5a9a4f918ff0e1578fdc3f607a7ec704c5da1b13ddc290fd0aefa97ff2e/toml_sort-0.24.3-py3-none-any.whl", hash = "sha256:d70642f54827b4c17a6cde788dcb45d598c1eb9833544a2fcec5eb7b0b744ed4", size = 16538, upload-time = "2025-09-10T02:43:53.67Z" },
{ url = "https://files.pythonhosted.org/packages/0f/5a/1f0e54df4eacf0f4d8f94ba50cf72be33d2a3f04babdfb1931bead48a0ab/toml_sort-0.24.4-py3-none-any.whl", hash = "sha256:125aa5fb94f33c542c6901040456145dd38f79bbb310b56b436a93057d30a739", size = 16577, upload-time = "2026-03-24T14:05:54.757Z" },
]
[[package]]
@@ -1056,14 +1057,14 @@ wheels = [
[[package]]
name = "typeguard"
version = "4.4.4"
version = "4.5.2"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "typing-extensions" },
]
sdist = { url = "https://files.pythonhosted.org/packages/c7/68/71c1a15b5f65f40e91b65da23b8224dad41349894535a97f63a52e462196/typeguard-4.4.4.tar.gz", hash = "sha256:3a7fd2dffb705d4d0efaed4306a704c89b9dee850b688f060a8b1615a79e5f74", size = 75203, upload-time = "2025-06-18T09:56:07.624Z" }
sdist = { url = "https://files.pythonhosted.org/packages/67/1c/dfba5c4633cafc4c701f237d2ba63b416805047fd6d96aab4cfc40969f98/typeguard-4.5.2.tar.gz", hash = "sha256:5a16dcac23502039299c97c8941651bc33d7ea8cc4b2f7d6bbb1b528f6eea423", size = 80240, upload-time = "2026-05-14T12:59:40.857Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/1b/a9/e3aee762739c1d7528da1c3e06d518503f8b6c439c35549b53735ba52ead/typeguard-4.4.4-py3-none-any.whl", hash = "sha256:b5f562281b6bfa1f5492470464730ef001646128b180769880468bd84b68b09e", size = 34874, upload-time = "2025-06-18T09:56:05.999Z" },
{ url = "https://files.pythonhosted.org/packages/5b/29/74eeb4d3f3ae61ca096b018ad486b3b3c74b17bec09ab4edab721cbefec3/typeguard-4.5.2-py3-none-any.whl", hash = "sha256:fcf9de18bd945cdb4c7b996e12b4c51ce83f92f191314a6d7cf1739586ec98cf", size = 36748, upload-time = "2026-05-14T12:59:39.473Z" },
]
[[package]]
@@ -1134,22 +1135,22 @@ wheels = [
[[package]]
name = "xdoctest"
version = "1.3.0"
version = "1.3.2"
source = { registry = "https://pypi.org/simple" }
sdist = { url = "https://files.pythonhosted.org/packages/92/3a/425e9555e23409559fa01d3431b7e1ffbc4ad6fa3b808e9f7bac9e3afbb6/xdoctest-1.3.0.tar.gz", hash = "sha256:f92cb99a3be6011c57bb94613a26b09a268e0095e926b4559132d135d8f6c9d4", size = 207394, upload-time = "2025-09-08T15:02:46.256Z" }
sdist = { url = "https://files.pythonhosted.org/packages/3f/df/1b5751e3546967a4884cff6ea743b1e457d3f7c94fc35913f149a85734fc/xdoctest-1.3.2.tar.gz", hash = "sha256:bf6078c4fc0d60aafd8753fccdc435c95f26a640508e606d188d96f48359f0aa", size = 209923, upload-time = "2026-03-27T01:13:25.275Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/a7/75/35c17f21153190386af9fb36aab5f76d9f865c69d2f13afdfeb0b3109481/xdoctest-1.3.0-py3-none-any.whl", hash = "sha256:b546accaecae2fd0a14e8d8e125550832f3f11981629324519d057e218dd348f", size = 152543, upload-time = "2025-09-08T15:02:43.245Z" },
{ url = "https://files.pythonhosted.org/packages/29/1d/6b9cf46122f2f07eab95c4af29ab5e29bd6674147a0b1e9a6d3929870af1/xdoctest-1.3.2-py3-none-any.whl", hash = "sha256:052118c8efb2b4cfb54485d328915b9e7b44da37c64b0998ca6aa21193dcb601", size = 146469, upload-time = "2026-03-27T01:13:23.417Z" },
]
[[package]]
name = "yamllint"
version = "1.37.1"
version = "1.38.0"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "pathspec" },
{ name = "pyyaml" },
]
sdist = { url = "https://files.pythonhosted.org/packages/46/f2/cd8b7584a48ee83f0bc94f8a32fea38734cefcdc6f7324c4d3bfc699457b/yamllint-1.37.1.tar.gz", hash = "sha256:81f7c0c5559becc8049470d86046b36e96113637bcbe4753ecef06977c00245d", size = 141613, upload-time = "2025-05-04T08:25:54.355Z" }
sdist = { url = "https://files.pythonhosted.org/packages/28/a0/8fc2d68e132cf918f18273fdc8a1b8432b60d75ac12fdae4b0ef5c9d2e8d/yamllint-1.38.0.tar.gz", hash = "sha256:09e5f29531daab93366bb061e76019d5e91691ef0a40328f04c927387d1d364d", size = 142446, upload-time = "2026-01-13T07:47:53.276Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/dd/b9/be7a4cfdf47e03785f657f94daea8123e838d817be76c684298305bd789f/yamllint-1.37.1-py3-none-any.whl", hash = "sha256:364f0d79e81409f591e323725e6a9f4504c8699ddf2d7263d8d2b539cd66a583", size = 68813, upload-time = "2025-05-04T08:25:52.552Z" },
{ url = "https://files.pythonhosted.org/packages/05/92/aed08e68de6e6a3d7c2328ce7388072cd6affc26e2917197430b646aed02/yamllint-1.38.0-py3-none-any.whl", hash = "sha256:fc394a5b3be980a4062607b8fdddc0843f4fa394152b6da21722f5d59013c220", size = 68940, upload-time = "2026-01-13T07:47:51.343Z" },
]

View File

@@ -13,7 +13,7 @@ services:
retries: 12
backend:
image: ${DEPLOYABLE_BACKEND_IMAGE:-deployable-backend:local}
image: ${DEPLOYABLE_BACKEND_IMAGE:-plex-playlist-backend:local}
environment:
DATABASE_URL: ${DB_URL:-postgresql://plex_user:plex_password@database:5432/plex_playlist}
ENVIRONMENT: production
@@ -22,7 +22,7 @@ services:
condition: service_healthy
frontend:
image: ${DEPLOYABLE_FRONTEND_IMAGE:-deployable-frontend:local}
image: ${DEPLOYABLE_FRONTEND_IMAGE:-plex-playlist-frontend:local}
depends_on:
backend:
condition: service_started

View File

@@ -13,7 +13,7 @@ services:
retries: 12
backend:
image: ${DEPLOYABLE_BACKEND_IMAGE:-deployable-backend:local}
image: ${DEPLOYABLE_BACKEND_IMAGE:-plex-playlist-backend:local}
environment:
DATABASE_URL: ${DB_URL:-postgresql://plex_user:plex_password@database:5432/plex_playlist}
ENVIRONMENT: production

View File

@@ -72,12 +72,12 @@
### **Current Release Lifecycle (2026-07)**
- Runtime deployable images are published first to staging repositories:
- `deployable-backend-staging`
- `deployable-frontend-staging`
- `plex-playlist-backend-staging`
- `plex-playlist-frontend-staging`
- Runtime validation (`Runtime Black-Box Integration Tests` and `End-to-End Tests`) must pass before release tagging.
- `Promote Release Images` retags validated staging artifacts to release repositories, but only on automated `push` runs to `main`:
- `deployable-backend`
- `deployable-frontend`
- `plex-playlist-backend`
- `plex-playlist-frontend`
- Published release tags:
- `latest`
- `v<major>.<minor>.0`

View File

@@ -14,10 +14,10 @@ automation work under epic #66.
Lifecycle note:
- CI first builds deployable runtime artifacts in staging repositories
(`deployable-backend-staging`, `deployable-frontend-staging`).
(`plex-playlist-backend-staging`, `plex-playlist-frontend-staging`).
- After integration and E2E validation pass, CI promotes those immutable
artifacts to release repositories (`deployable-backend`,
`deployable-frontend`) via tag promotion.
artifacts to release repositories (`plex-playlist-backend`,
`plex-playlist-frontend`) via tag promotion.
Included:

View File

@@ -411,11 +411,11 @@ The pipeline is intentionally staged so expensive image jobs run only after sour
2. Source + audit lanes:
`Source Checks` and `Dependency Audits (Informational)` run after producer completion. Audit failures are intentionally non-blocking so both frontend and backend audits always report.
3. Runtime image lanes:
`Build Release Images` publishes `deployable-backend-staging` and `deployable-frontend-staging`; `Build Tester Images` publishes integration/e2e tester images; then `Production Images Complete` gates downstream runtime tests.
`Build Release Images` publishes `plex-playlist-backend-staging` and `plex-playlist-frontend-staging`; `Build Tester Images` publishes integration/e2e tester images; then `Production Images Complete` gates downstream runtime tests.
4. Runtime validation lanes:
`Runtime Black-Box Integration Tests` and `End-to-End Tests` validate staged runtime artifacts.
5. Promotion lane:
`Promote Release Images` runs only for automated `push` events on `main`. It retags validated staging artifacts to release repos (`deployable-backend`, `deployable-frontend`) with `latest`, `v<major>.<minor>.0`, `v<major>.<minor>.<patch>`, and `v<major>.<minor>.<patch>-<7-char-short-sha>` tags. If the `main` commit is untagged, CI creates the next patch tag automatically; if no prior semver tag exists, the bootstrap baseline is `v0.0.0`.
`Promote Release Images` runs only for automated `push` events on `main`. It retags validated staging artifacts to release repos (`plex-playlist-backend`, `plex-playlist-frontend`) with `latest`, `v<major>.<minor>.0`, `v<major>.<minor>.<patch>`, and `v<major>.<minor>.<patch>-<7-char-short-sha>` tags. If the `main` commit is untagged, CI creates the next patch tag automatically; if no prior semver tag exists, the bootstrap baseline is `v0.0.0`.
6. Postmortem lanes:
targeted postmortem jobs run when key lanes fail to capture diagnostics even when primary jobs fail early.
@@ -433,6 +433,16 @@ Current workflow behavior includes:
For details of base/complete image build strategy, see [CI/CD Multi-Stage Build Architecture](CICD_MULTI_STAGE_BUILD.md).
For incident handling, see [CI/CD Troubleshooting](CICD_TROUBLESHOOTING_GUIDE.md).
### Renovate Manual Run Behavior
The Renovate workflow at `.gitea/workflows/renovate.yml` now treats manual dispatch as an explicit operator override:
- when triggered via `workflow_dispatch`, it forces out-of-window execution by setting `RENOVATE_IGNORE_SCHEDULE=true`
- it also sets `RENOVATE_SCHEDULE="at any time"` for the run
- it executes one single pass across enabled managers instead of splitting work into multiple manager batches
This keeps scheduled behavior unchanged while making manual runs deterministic and immediate.
### Operator Quick Reference
Use workflow dispatch when you need deterministic reruns on a specific commit:

View File

@@ -94,7 +94,7 @@ export default [
security,
},
rules: {
...vue.configs['vue3-essential'].rules,
...vue.configs['essential'].rules,
'no-console': process.env.NODE_ENV === 'production' ? 'warn' : 'off',
'no-debugger': process.env.NODE_ENV === 'production' ? 'warn' : 'off',
...securityRules,

View File

@@ -22,29 +22,29 @@
},
"dependencies": {
"vue": "^3.4.0",
"zod": "^3.22.0"
"zod": "^4.0.0"
},
"devDependencies": {
"@playwright/test": "^1.40.0",
"@types/node": "^20.0.0",
"@types/node": "^24.0.0",
"@typescript-eslint/eslint-plugin": "^8.0.0",
"@typescript-eslint/parser": "^8.0.0",
"@vitejs/plugin-vue": "^6.0.0",
"@vitest/coverage-v8": "^3.2.4",
"@vitest/coverage-v8": "^4.0.0",
"@vue/test-utils": "^2.4.0",
"@vue/tsconfig": "^0.5.0",
"eslint": "^9.33.0",
"eslint-plugin-jsdoc": "^50.0.0",
"@vue/tsconfig": "^0.9.0",
"eslint": "^10.0.0",
"eslint-plugin-jsdoc": "^63.0.0",
"eslint-plugin-security": "^4.0.1",
"eslint-plugin-tsdoc": "^0.3.0",
"eslint-plugin-vue": "^9.28.0",
"jsdom": "^23.0.0",
"prettier": "3.6.2",
"typescript": "~5.3.0",
"vite": "^7.1.10",
"vitest": "^3.2.4",
"vue-eslint-parser": "^9.4.0",
"vue-tsc": "^2.0.0"
"eslint-plugin-tsdoc": "^0.5.0",
"eslint-plugin-vue": "^10.0.0",
"jsdom": "^29.0.0",
"prettier": "3.9.6",
"typescript": "~6.0.0",
"vite": "^8.0.0",
"vitest": "^4.0.0",
"vue-eslint-parser": "^10.0.0",
"vue-tsc": "^3.0.0"
},
"packageManager": "yarn@4.10.3"
"packageManager": "yarn@4.17.1"
}

View File

@@ -46,10 +46,7 @@ function enhancedParse<T>(this: z.ZodType<T>, data: unknown): T {
* @param data - The data to validate against the schema
* @returns Safe parse result with success flag and data or error
*/
function enhancedSafeParse<T>(
this: z.ZodType<T>,
data: unknown
): z.SafeParseReturnType<unknown, T> {
function enhancedSafeParse<T>(this: z.ZodType<T>, data: unknown) {
const result = originalSafeParse.call(this, data);
validationCount++;

View File

@@ -22,7 +22,7 @@ export const UserSchema = z.object({
theme: z.enum(['light', 'dark']).default('light'),
notifications: z.boolean().default(true),
})
.default({}),
.default({ theme: 'light', notifications: true }),
});
// Inferred types (no manual type definitions needed)

View File

@@ -4,6 +4,7 @@
"exclude": ["src/**/__tests__/*"],
"compilerOptions": {
"composite": true,
"ignoreDeprecations": "6.0",
"baseUrl": ".",
"paths": {
"@/*": ["./src/*"]
@@ -12,6 +13,7 @@
"target": "ES2020",
"module": "ESNext",
"moduleResolution": "bundler",
"types": ["node", "vite/client", "vitest/globals"],
"strict": true,
"noUnusedLocals": true,
"noUnusedParameters": true,

File diff suppressed because it is too large Load Diff

View File

@@ -1,5 +1,23 @@
#!/usr/bin/env xonsh
from pathlib import Path
def load_ci_versions():
env_path = Path(__file__).resolve().parents[2] / "versions" / "ci.env"
values = {}
for raw_line in env_path.read_text().splitlines():
line = raw_line.strip()
if not line or line.startswith("#") or "=" not in line:
continue
key, value = line.split("=", 1)
values[key.strip()] = value.strip()
return values
ci_versions = load_ci_versions()
playwright_tag = ci_versions["PLAYWRIGHT_IMAGE_TAG"]
hosts = [
"kankali.darkhelm.lan",
"zhokq.darkhelm.lan",
@@ -14,7 +32,7 @@ remote_code_template = """
mirror_pairs = [
("ACT_UBUNTU", "ghcr.io/catthehacker/ubuntu:act-latest", "kankali.darkhelm.lan:3001/darkhelm.org/act-ubuntu:act-latest"),
("RENOVATE", "ghcr.io/renovatebot/renovate:41", "kankali.darkhelm.lan:3001/darkhelm.org/renovate:41"),
("PLAYWRIGHT", "mcr.microsoft.com/playwright:v1.56.1-jammy", "kankali.darkhelm.lan:3001/darkhelm.org/playwright-browsers:v1.56.1-jammy"),
("PLAYWRIGHT", "mcr.microsoft.com/playwright:" + __PLAYWRIGHT_TAG__, "kankali.darkhelm.lan:3001/darkhelm.org/playwright-browsers:" + __PLAYWRIGHT_TAG__),
]
is_publisher = __IS_PUBLISHER__
@@ -94,5 +112,10 @@ for label, source_image, mirror_image in mirror_pairs:
for host in hosts:
print(f"\n=== {host} ===")
remote_code = remote_code_template.replace("__IS_PUBLISHER__", "True" if host == publisher_host else "False")
quoted_playwright_tag = repr(playwright_tag)
remote_code = (
remote_code_template
.replace("__IS_PUBLISHER__", "True" if host == publisher_host else "False")
.replace("__PLAYWRIGHT_TAG__", quoted_playwright_tag)
)
ssh @(host) @(remote_code)

View File

@@ -4,14 +4,26 @@ set -euo pipefail
ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
COMPOSE_FILE="${ROOT_DIR}/compose.ci.e2e.yml"
PROJECT_NAME="${COMPOSE_PROJECT_NAME:-plex-e2e-local}"
VERSION_ENV_FILE="${ROOT_DIR}/versions/ci.env"
if [ ! -f "${VERSION_ENV_FILE}" ]; then
echo "❌ Missing version source file: ${VERSION_ENV_FILE}"
exit 1
fi
set -a
# shellcheck source=../versions/ci.env
source "${VERSION_ENV_FILE}"
set +a
mkdir -p "${ROOT_DIR}/frontend/.playwright-artifacts"
export DEPLOYABLE_BACKEND_IMAGE="${DEPLOYABLE_BACKEND_IMAGE:-deployable-backend:local}"
export DEPLOYABLE_FRONTEND_IMAGE="${DEPLOYABLE_FRONTEND_IMAGE:-deployable-frontend:local}"
export DEPLOYABLE_BACKEND_IMAGE="${DEPLOYABLE_BACKEND_IMAGE:-plex-playlist-backend:local}"
export DEPLOYABLE_FRONTEND_IMAGE="${DEPLOYABLE_FRONTEND_IMAGE:-plex-playlist-frontend:local}"
export DB_PASSWORD="${DB_PASSWORD:-plex_password}"
export DB_URL="${DB_URL:-postgresql://plex_user:${DB_PASSWORD}@database:5432/plex_playlist}"
export E2E_ARTIFACT_DIR="${E2E_ARTIFACT_DIR:-${ROOT_DIR}/frontend/.playwright-artifacts}"
export PLAYWRIGHT_E2E_IMAGE="${PLAYWRIGHT_E2E_IMAGE:-${PLAYWRIGHT_IMAGE}}"
cleanup() {
docker compose -p "${PROJECT_NAME}" -f "${COMPOSE_FILE}" down -v --remove-orphans >/dev/null 2>&1 || true
@@ -23,6 +35,7 @@ echo "Running E2E tests against runtime backend/frontend images via compose"
echo "DEPLOYABLE_BACKEND_IMAGE=${DEPLOYABLE_BACKEND_IMAGE}"
echo "DEPLOYABLE_FRONTEND_IMAGE=${DEPLOYABLE_FRONTEND_IMAGE}"
echo "E2E_ARTIFACT_DIR=${E2E_ARTIFACT_DIR}"
echo "PLAYWRIGHT_E2E_IMAGE=${PLAYWRIGHT_E2E_IMAGE}"
docker compose -p "${PROJECT_NAME}" -f "${COMPOSE_FILE}" up -d database backend frontend
@@ -34,5 +47,5 @@ docker run --rm \
-e PLAYWRIGHT_JUNIT_OUTPUT_FILE=/tmp/playwright-artifacts/playwright-results.xml \
-v "${ROOT_DIR}/frontend:/workspace/frontend" \
-v "${E2E_ARTIFACT_DIR}:/tmp/playwright-artifacts" \
mcr.microsoft.com/playwright:v1.56.1-jammy \
"${PLAYWRIGHT_E2E_IMAGE}" \
bash -lc "cd /workspace/frontend && corepack enable && yarn install --immutable && yarn test:e2e --reporter=list --timeout=90000"

View File

@@ -5,7 +5,7 @@ ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
COMPOSE_FILE="${ROOT_DIR}/compose.ci.integration.yml"
PROJECT_NAME="${COMPOSE_PROJECT_NAME:-plex-int-local}"
export DEPLOYABLE_BACKEND_IMAGE="${DEPLOYABLE_BACKEND_IMAGE:-deployable-backend:local}"
export DEPLOYABLE_BACKEND_IMAGE="${DEPLOYABLE_BACKEND_IMAGE:-plex-playlist-backend:local}"
export DB_PASSWORD="${DB_PASSWORD:-plex_password}"
export DB_URL="${DB_URL:-postgresql://plex_user:${DB_PASSWORD}@database:5432/plex_playlist}"
@@ -15,7 +15,7 @@ cleanup() {
trap cleanup EXIT
echo "Running runtime integration checks against deployable backend image via compose"
echo "Running runtime integration checks against plex-playlist backend image via compose"
echo "DEPLOYABLE_BACKEND_IMAGE=${DEPLOYABLE_BACKEND_IMAGE}"
docker compose -p "${PROJECT_NAME}" -f "${COMPOSE_FILE}" up -d database backend

12
versions/ci.env Normal file
View File

@@ -0,0 +1,12 @@
# CI/runtime version source of truth for scripts and docker build args.
# shellcheck disable=SC2034
PLAYWRIGHT_VERSION=1.61.1
PLAYWRIGHT_DISTRO=jammy
PLAYWRIGHT_IMAGE_TAG=v1.61.1-jammy
PLAYWRIGHT_IMAGE=mcr.microsoft.com/playwright:${PLAYWRIGHT_IMAGE_TAG}
PLAYWRIGHT_MIRROR_IMAGE=darkhelm.org/playwright-browsers:${PLAYWRIGHT_IMAGE_TAG}
POSTGRES_IMAGE_TAG=16-alpine
POSTGRES_MIRROR_IMAGE=darkhelm.org/postgres:${POSTGRES_IMAGE_TAG}
POSTGRES_UPSTREAM_IMAGE=docker.io/library/postgres:${POSTGRES_IMAGE_TAG}
UBUNTU_CICD_BASE_VERSION=26.04