From 923d2ee811f29115b56cffc3291e0f1b42487203 Mon Sep 17 00:00:00 2001
From: SandObserver <260779319+SandObserver@users.noreply.github.com>
Date: Sun, 16 Aug 2026 21:17:43 -0400
Subject: [PATCH] Fix Community Applications template update against a
protected branch
The workflow committed the release notes straight onto the default branch,
which a ruleset rejects, so the v1.7.0 run failed after the release published
and the template stayed on 1.6.1.
Push a per-release branch and open a pull request instead, and carry the 1.7.0
notes the failed run produced.
---
.github/workflows/ca-template-changes.yml | 34 ++++++-
api/test/ca-template.test.js | 13 +++
api/test/workflow-hardening.test.js | 8 +-
templates/stackyard.xml | 115 +++++++++++++++++-----
4 files changed, 138 insertions(+), 32 deletions(-)
diff --git a/.github/workflows/ca-template-changes.yml b/.github/workflows/ca-template-changes.yml
index fbf60240..bf3bd0c2 100644
--- a/.github/workflows/ca-template-changes.yml
+++ b/.github/workflows/ca-template-changes.yml
@@ -4,16 +4,17 @@ on:
release:
types: [published]
-# Commits the updated template back to the default branch. The repository
-# default is read, so the write is granted here and nowhere else.
+# Opens a pull request against the default branch. The repository default is
+# read, so the writes are granted here and nowhere else.
permissions:
contents: write
+ pull-requests: write
jobs:
update:
runs-on: ubuntu-latest
steps:
- # Commit onto the default branch, not the tag the release points at: a
+ # Branch from the default branch, not the tag the release points at: a
# tag checkout is detached and the push would go nowhere.
- name: Checkout default branch
uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4.4.0
@@ -38,17 +39,40 @@ jobs:
# The checkout keeps no credentials, so the token authenticates this one
# push and is never left in the runner's git config.
- - name: Commit
+ #
+ # A pull request, never a direct push: the default branch requires one.
+ # Checks do not start on a pull request opened with GITHUB_TOKEN. Merging
+ # this one needs the ruleset bypass, or a re-run of the checks.
+ - name: Open a pull request
if: steps.changes.outputs.changed == 'true'
env:
VERSION: ${{ github.event.release.tag_name }}
- BRANCH: ${{ github.event.repository.default_branch }}
+ BASE: ${{ github.event.repository.default_branch }}
REPO: ${{ github.repository }}
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
set -euo pipefail
+ BRANCH="docs/ca-template-${VERSION}"
git config user.name 'github-actions[bot]'
git config user.email '41898282+github-actions[bot]@users.noreply.github.com'
+ git checkout -b "${BRANCH}"
git add templates/stackyard.xml
git commit -m "Docs: describe ${VERSION} in the Community Applications template"
git push "https://x-access-token:${GH_TOKEN}@github.com/${REPO}.git" "HEAD:${BRANCH}"
+ gh pr create \
+ --base "${BASE}" \
+ --head "${BRANCH}" \
+ --title "Docs: describe ${VERSION} in the Community Applications template" \
+ --label documentation \
+ --body "$(printf '%s\n' \
+ '**Summary**' \
+ "- Copy the ${VERSION} changelog section into the Community Applications template." \
+ '' \
+ '**Testing**' \
+ 'The template was validated as well-formed before this branch was pushed.' \
+ '' \
+ '**Checklist**' \
+ '- [x] Stays within the project constraints: one container, no runtime dependencies, no build step (see CONTRIBUTING.md).' \
+ '- [ ] Tests added or updated for new logic, and the full suite, lint, and typechecks pass.' \
+ '- [x] Docs updated if behavior or configuration changed.' \
+ '- [ ] CHANGELOG.md updated under Unreleased if the change is user-visible.')"
diff --git a/api/test/ca-template.test.js b/api/test/ca-template.test.js
index ecdae30d..1ffe9734 100644
--- a/api/test/ca-template.test.js
+++ b/api/test/ca-template.test.js
@@ -82,6 +82,19 @@ test('both documents use the repository path with its real capitalisation', () =
}
});
+/* The default branch requires a pull request. A workflow that pushes the
+ template straight at it is rejected by the ruleset and the release notes
+ never reach the listing. */
+test('the template update opens a pull request instead of pushing to the default branch', () => {
+ const src = fs.readFileSync(path.join(ROOT, '.github', 'workflows', 'ca-template-changes.yml'), 'utf8');
+ const commands = src
+ .split('\n')
+ .filter(line => !/^\s*#/.test(line))
+ .join('\n');
+ assert.match(commands, /gh pr create/, 'the update no longer opens a pull request');
+ assert.doesNotMatch(commands, /git push[^\n]*HEAD:\$\{BASE\}/, 'a direct push to the default branch is rejected');
+});
+
/* The runner image has no xmllint, so a workflow that reaches for it fails at
step one. Both validate through the committed script instead. */
test('the workflows validate with the committed script, not xmllint', () => {
diff --git a/api/test/workflow-hardening.test.js b/api/test/workflow-hardening.test.js
index bf9068d2..ae29238b 100644
--- a/api/test/workflow-hardening.test.js
+++ b/api/test/workflow-hardening.test.js
@@ -52,13 +52,13 @@ test('no workflow grants a write scope it does not need', () => {
lets the job mint a short-lived OIDC token, which is what cosign exchanges
for a Sigstore certificate when it signs the released image. Keyless
signing needs it, and it is the reason there is no private key to hold. */
- /* The CA template's release notes are committed back to the default branch,
- which is the only thing that write scope covers. The checkout still keeps
- no credentials: the push authenticates on its own. */
+ /* The CA template's release notes go to a branch and a pull request, which is
+ all those two scopes cover. The checkout still keeps no credentials: the
+ push authenticates on its own. */
const allowed = {
'workflows/release.yml': ['packages: write', 'id-token: write'],
'workflows/codeql.yml': ['security-events: write'],
- 'workflows/ca-template-changes.yml': ['contents: write'],
+ 'workflows/ca-template-changes.yml': ['contents: write', 'pull-requests: write'],
};
const bad = [];
for (const [f, src] of workflows) {
diff --git a/templates/stackyard.xml b/templates/stackyard.xml
index aabff05a..bd93bc96 100644
--- a/templates/stackyard.xml
+++ b/templates/stackyard.xml
@@ -19,42 +19,111 @@
If Stackyard is useful to you, you can buy me a coffee.
https://buymeacoffee.com/sandobserver
-### 1.6.1 - 2026-08-14
+### 1.7.0 - 2026-08-16
+
+### Added
+
+- Light theme for the Settings pages, with Settings Display Mode in Settings >
+ Appearance: System Default, Light or Dark. Stored per device.
+
+- Keep Screen Awake in Settings > Appearance, off by default. Needs HTTPS.
+
+- Show From on a live activity badge, to badge only counts at or above a number.
+
+- Install from Unraid Community Applications, with a template in `templates/`.
+
+### Changed
+
+- Text on both pages now follows one type scale, so some sizes and line spacing
+ shift slightly.
+
+- Widget colours now match the rest of the app. Reds, blues, greens and greys
+ that had been left on older values are corrected.
+
+- Settings controls are redrawn: switches are wider with a capsule knob, slider
+ tracks are thicker, and groups are more rounded.
+
+- The wallpaper brightness slider now has the same handle as the colour sliders.
+
+- Each colour slider handle shows the value it is set to.
+
+- Group headings and their help text now line up with the settings above and
+ below them.
+
+- The settings sidebar is wider, with taller items and a rounded selection.
+
+- The selected tab on a phone is marked with a pill instead of a coloured
+ label.
+
+- Widget tiles and dock icons are rounded correctly, and stay so at every icon
+ and dashboard size.
+
+- Either-or settings are now a segmented control instead of radio dots.
+
+- Buttons in a dialog are taller and rounded.
+
+- A long settings label now keeps its line and the value beside it shortens,
+ instead of the label breaking in two.
+
+- Unsplash API Key is now just API Key, under a Source row that already names
+ Unsplash.
+
+- Row separators now start level with the row's label instead of spanning the
+ full width.
+
+- Settings on a phone use the larger phone text size. On a desktop the panel
+ keeps its denser size.
+
+- Widgets on a page you are not looking at now poll four times less often, and
+ refresh when you swipe back to them.
+
+- Badge and health targets that keep failing are contacted less often, so an
+ offline service no longer slows every other tile on every refresh.
+
+- Scripts and stylesheets are now cached for a year instead of revalidated on
+ every load. Their URLs change whenever the file does.
+
+- The logo is redrawn, and its arc now follows the accent colour.
### Fixed
-- Phone home screen no longer starts under the status bar in a home-screen
- install. The first row clears the clock and the island.
+- Home screen no longer leaves a dead strip below the dock in a home-screen
+ install on iOS.
+
+- App icons now use the current logo, and the browser tab icon follows the
+ light or dark theme.
+
+- Colour and brightness slider tracks draw round ends on a touch device instead
+ of tapering to a point.
-- Settings reserves the status bar area on a phone.
+- Hue, saturation and brightness sliders no longer stretch across the row on a
+ phone.
-- Notification badges inside a folder no longer get trimmed at the page edge or
- bleed into the next page.
+- Slider fills and colour ramps now run the same way as the handle in
+ right-to-left languages.
-- Opening a folder no longer puts a focus ring on the first app, on a phone or
- on the desktop.
+- Saturation, brightness and wallpaper brightness sliders now draw a thin track
+ on a phone, matching hue.
-- A long error in Admin now stays on screen long enough to read, up to fifteen
- seconds.
+- Settings no longer flashes the desktop sidebar before the phone layout
+ appears.
-- Backup placeholder no longer moves or reshuffles when a card is hovered or
- tapped.
+- Dock and the Settings tab bar now sit as close to the bottom of the screen as
+ to the sides.
-- The App, Widget and Folder tiles under Add New show their names instead of
- their internal keys.
+- Remove the stray Support link from Settings > General.
-- The Backup widget shows the job picker for the provider you picked. Kopia
- showed the Duplicati picker as well, and Duplicati showed no picker at all.
+- App title toggles in Settings > Appearance now persist across a reload.
-- A badge or widget field blocked for pointing at a private address now names
- `ALLOW_PRIVATE_IPS=true` as the setting that allows it. The advice was added
- in 1.6.0 but never appeared.
+- Connections map tooltips now use the system font on Android, Windows and
+ Linux instead of falling back to a serif.
-- A widget settings Fetch marks a blocked private address as a warning, the
- same as a badge test, instead of a hard error.
+- Saving on Settings > Appearance no longer reports "Wallpaper saved" when
+ something else on the page was saved.
-- A badge extract path ending in `count` now reads a JSON field of that
- name. It only counts an array when the value is an array.
+- The login and set-password screens, the phone tab bar, the logging level and
+ wallpaper source menus, the version line and the app, widget and widget
+ configuration forms are now translated instead of always showing English.
8700
/mnt/user/appdata/stackyard/data