Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .github/workflows/publish-release.yml
Original file line numberDiff line numberDiff line change
Expand Up@@ -164,11 +164,11 @@ jobs:
actions: write
steps:
- name: Delete workflow artifacts step
# continue-on-error: best-effort housekeeping must never red the run, even on an unexpected failure.
continue-on-error: true
env:
GH_TOKEN: ${{ github.token }}
run: |
# Best-effort housekeeping: a failed list or delete logs a warning and continues so it never reds the run,
# while `set -e` still catches unexpected failures.
set -euo pipefail
if ! ids=$(gh api repos/${{ github.repository }}/actions/runs/${{ github.run_id }}/artifacts --paginate \
--jq '.artifacts[].id'); then
Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/test-pull-request.yml
Original file line numberDiff line numberDiff line change
Expand Up@@ -152,11 +152,11 @@ jobs:
actions: write
steps:
- name: Delete workflow artifacts step
# continue-on-error: best-effort housekeeping must never red the run, even on an unexpected failure.
continue-on-error: true
env:
GH_TOKEN: ${{ github.token }}
run: |
# Best-effort housekeeping: a failed list or delete logs a warning and continues so it never reds the run,
# while `set -e` still catches unexpected failures.
set -euo pipefail
if ! ids=$(gh api repos/${{ github.repository }}/actions/runs/${{ github.run_id }}/artifacts --paginate \
--jq '.artifacts[].id'); then
Expand Down
2 changes: 1 addition & 1 deletion AGENTS.md
Original file line numberDiff line numberDiff line change
Expand Up@@ -192,7 +192,7 @@ These conventions describe the target state. New and modified workflows must res
- **Boolean inputs**: workflows triggered both via `workflow_call` and `workflow_dispatch` must declare each boolean input in *both* trigger blocks - one definition does not propagate to the other. `workflow_call` delivers booleans as actual booleans; `workflow_dispatch` delivers them as the *strings* `"true"`/`"false"`. Any `if:` consuming a boolean input must compare against both forms - `if: ${{ inputs.foo == true || inputs.foo == 'true' }}`.
- **Reusable workflows**: job-level `permissions:` are validated *before* the `if:` evaluates, so even a skipped job needs valid permissions declared. A `release` job with `permissions: contents: write` and `if: ${{ inputs.publish }}` will still cause `startup_failure` on a caller that doesn't grant `contents: write`. Either declare permissions at the call site, or omit the inner block and inherit.
- **Allowlist `success` and `skipped` explicitly** when chaining jobs across optional dependencies - `!= 'failure'` lets `cancelled` through (timeout, runner failure, manual cancel). Use `(needs.X.result == 'success' || needs.X.result == 'skipped')`.
- **Artifact retention**: workflow artifacts are an intra-run handoff only - durable copies live on the GitHub release, not in workflow artifacts - so they must not survive the run and accumulate against the small account-wide artifact-storage quota. **Every workflow that can produce artifacts ends with a terminal `cleanup-artifacts` job** that deletes the run's artifacts via the REST API: `permissions: actions: write`, `needs` the artifact producers, an `if:` that **includes** `always()` (so a failed run still cleans up) plus any workflow-specific gate (e.g. `publish-release.yml` adds `&& needs.setup.outputs.publish == 'true'` to run only on real publishes), independent of any required status check so housekeeping never gates a merge, and tolerant of individual list/delete failures (warn and continue, never red the run). This covers not just `actions/upload-artifact` but build-records that actions emit automatically (e.g. `docker/build-push-action`'s `.dockerbuild`). Both `publish-release.yml` and `test-pull-request.yml` carry one; add one to any new artifact-producing entry workflow. Set `retention-days: 1` on explicit uploads as a backstop.
- **Artifact retention**: workflow artifacts are an intra-run handoff only - durable copies live on the GitHub release, not in workflow artifacts - so they must not survive the run and accumulate against the small account-wide artifact-storage quota. **Every workflow that can produce artifacts ends with a terminal `cleanup-artifacts` job** that deletes the run's artifacts via the REST API: `permissions: actions: write`, `needs` the artifact producers, an `if:` that **includes** `always()` (so a failed run still cleans up) plus any workflow-specific gate (e.g. `publish-release.yml` adds `&& needs.setup.outputs.publish == 'true'` to run only on real publishes), independent of any required status check so housekeeping never gates a merge, `continue-on-error: true` on the delete step so even an unexpected failure never reds the run, and tolerant of individual list/delete failures (warn and continue). This covers not just `actions/upload-artifact` but build-records that actions emit automatically (e.g. `docker/build-push-action`'s `.dockerbuild`). Both `publish-release.yml` and `test-pull-request.yml` carry one; add one to any new artifact-producing entry workflow. Set `retention-days: 1` on explicit uploads as a backstop.
- **Docker layer cache**: cache to/from a registry tag (`type=registry`, e.g. `buildcache-<branch>` on Docker Hub), not the GitHub Actions cache (`type=gha`), to keep large image layers off the 10 GB Actions cache.
- **Tag pinning on releases**: when using `softprops/action-gh-release` (or any tag-creating action), pass `target_commitish` explicitly - without it, GitHub's REST API defaults the new tag to the repository's default branch instead of the commit that built the artifact. Pin it to the **exact built commit's SHA** (the publisher uses NBGV's `GitCommitId` output), not `github.sha` (wrong branch in the publisher's branch matrix - a `develop` leg runs with `github.sha` = main's tip) and not a branch name (a moving ref that a mid-run commit could advance past the built tree).

Expand Down
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Add copy buttons to all
 blocks\n(function() {\n function addCopyButtons() {\n document.querySelectorAll('pre code').forEach(function(codeBlock) {\n if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;\n codeBlock.parentElement.setAttribute('data-copy-added', 'true');\n \n var btn = document.createElement('button');\n btn.textContent = 'Copy';\n btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';\n btn.onmouseover = function() { this.style.opacity = '1'; };\n btn.onmouseout = function() { this.style.opacity = '0.7'; };\n btn.onclick = function() {\n navigator.clipboard.writeText(codeBlock.textContent).then(function() {\n btn.textContent = 'Copied!';\n setTimeout(function() { btn.textContent = 'Copy'; }, 1500);\n });\n };\n codeBlock.parentElement.style.position = 'relative';\n codeBlock.parentElement.appendChild(btn);\n });\n }\n \n addCopyButtons();\n \n // Re-run on dynamic content\n var observer = new MutationObserver(addCopyButtons);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Add Copy Buttons to Code Blocks");
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .github/workflows/publish-release.yml
Original file line numberDiff line numberDiff line change
Expand Up@@ -164,11 +164,11 @@ jobs:
actions: write
steps:
- name: Delete workflow artifacts step
# continue-on-error: best-effort housekeeping must never red the run, even on an unexpected failure.
continue-on-error: true
env:
GH_TOKEN: ${{ github.token }}
run: |
# Best-effort housekeeping: a failed list or delete logs a warning and continues so it never reds the run,
# while `set -e` still catches unexpected failures.
set -euo pipefail
if ! ids=$(gh api repos/${{ github.repository }}/actions/runs/${{ github.run_id }}/artifacts --paginate \
--jq '.artifacts[].id'); then
Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/test-pull-request.yml
Original file line numberDiff line numberDiff line change
Expand Up@@ -152,11 +152,11 @@ jobs:
actions: write
steps:
- name: Delete workflow artifacts step
# continue-on-error: best-effort housekeeping must never red the run, even on an unexpected failure.
continue-on-error: true
env:
GH_TOKEN: ${{ github.token }}
run: |
# Best-effort housekeeping: a failed list or delete logs a warning and continues so it never reds the run,
# while `set -e` still catches unexpected failures.
set -euo pipefail
if ! ids=$(gh api repos/${{ github.repository }}/actions/runs/${{ github.run_id }}/artifacts --paginate \
--jq '.artifacts[].id'); then
Expand Down
2 changes: 1 addition & 1 deletion AGENTS.md
Original file line numberDiff line numberDiff line change
Expand Up@@ -192,7 +192,7 @@ These conventions describe the target state. New and modified workflows must res
- **Boolean inputs**: workflows triggered both via `workflow_call` and `workflow_dispatch` must declare each boolean input in *both* trigger blocks - one definition does not propagate to the other. `workflow_call` delivers booleans as actual booleans; `workflow_dispatch` delivers them as the *strings* `"true"`/`"false"`. Any `if:` consuming a boolean input must compare against both forms - `if: ${{ inputs.foo == true || inputs.foo == 'true' }}`.
- **Reusable workflows**: job-level `permissions:` are validated *before* the `if:` evaluates, so even a skipped job needs valid permissions declared. A `release` job with `permissions: contents: write` and `if: ${{ inputs.publish }}` will still cause `startup_failure` on a caller that doesn't grant `contents: write`. Either declare permissions at the call site, or omit the inner block and inherit.
- **Allowlist `success` and `skipped` explicitly** when chaining jobs across optional dependencies - `!= 'failure'` lets `cancelled` through (timeout, runner failure, manual cancel). Use `(needs.X.result == 'success' || needs.X.result == 'skipped')`.
- **Artifact retention**: workflow artifacts are an intra-run handoff only - durable copies live on the GitHub release, not in workflow artifacts - so they must not survive the run and accumulate against the small account-wide artifact-storage quota. **Every workflow that can produce artifacts ends with a terminal `cleanup-artifacts` job** that deletes the run's artifacts via the REST API: `permissions: actions: write`, `needs` the artifact producers, an `if:` that **includes** `always()` (so a failed run still cleans up) plus any workflow-specific gate (e.g. `publish-release.yml` adds `&& needs.setup.outputs.publish == 'true'` to run only on real publishes), independent of any required status check so housekeeping never gates a merge, and tolerant of individual list/delete failures (warn and continue, never red the run). This covers not just `actions/upload-artifact` but build-records that actions emit automatically (e.g. `docker/build-push-action`'s `.dockerbuild`). Both `publish-release.yml` and `test-pull-request.yml` carry one; add one to any new artifact-producing entry workflow. Set `retention-days: 1` on explicit uploads as a backstop.
- **Artifact retention**: workflow artifacts are an intra-run handoff only - durable copies live on the GitHub release, not in workflow artifacts - so they must not survive the run and accumulate against the small account-wide artifact-storage quota. **Every workflow that can produce artifacts ends with a terminal `cleanup-artifacts` job** that deletes the run's artifacts via the REST API: `permissions: actions: write`, `needs` the artifact producers, an `if:` that **includes** `always()` (so a failed run still cleans up) plus any workflow-specific gate (e.g. `publish-release.yml` adds `&& needs.setup.outputs.publish == 'true'` to run only on real publishes), independent of any required status check so housekeeping never gates a merge, `continue-on-error: true` on the delete step so even an unexpected failure never reds the run, and tolerant of individual list/delete failures (warn and continue). This covers not just `actions/upload-artifact` but build-records that actions emit automatically (e.g. `docker/build-push-action`'s `.dockerbuild`). Both `publish-release.yml` and `test-pull-request.yml` carry one; add one to any new artifact-producing entry workflow. Set `retention-days: 1` on explicit uploads as a backstop.
- **Docker layer cache**: cache to/from a registry tag (`type=registry`, e.g. `buildcache-<branch>` on Docker Hub), not the GitHub Actions cache (`type=gha`), to keep large image layers off the 10 GB Actions cache.
- **Tag pinning on releases**: when using `softprops/action-gh-release` (or any tag-creating action), pass `target_commitish` explicitly - without it, GitHub's REST API defaults the new tag to the repository's default branch instead of the commit that built the artifact. Pin it to the **exact built commit's SHA** (the publisher uses NBGV's `GitCommitId` output), not `github.sha` (wrong branch in the publisher's branch matrix - a `develop` leg runs with `github.sha` = main's tip) and not a branch name (a moving ref that a mid-run commit could advance past the built tree).

Expand Down
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Force GitHub README to respect dark mode\n(function() {\n var style = document.createElement('style');\n style.textContent = '\n .markdown-body {\n color-scheme: dark light;\n }\n .markdown-body pre { background: #161b22 !important; }\n .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; }\n .markdown-body table th, .markdown-body table td { border-color: #30363d !important; }\n .markdown-body img { background: #0d1117; }\n .markdown-body blockquote { border-left-color: #8b949e; }\n .markdown-body hr { border-color: #30363d; }\n ';\n document.head.appendChild(style);\n})();", "GitHub Dark Mode README Fix"); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .github/workflows/publish-release.yml
Original file line numberDiff line numberDiff line change
Expand Up@@ -164,11 +164,11 @@ jobs:
actions: write
steps:
- name: Delete workflow artifacts step
# continue-on-error: best-effort housekeeping must never red the run, even on an unexpected failure.
continue-on-error: true
env:
GH_TOKEN: ${{ github.token }}
run: |
# Best-effort housekeeping: a failed list or delete logs a warning and continues so it never reds the run,
# while `set -e` still catches unexpected failures.
set -euo pipefail
if ! ids=$(gh api repos/${{ github.repository }}/actions/runs/${{ github.run_id }}/artifacts --paginate \
--jq '.artifacts[].id'); then
Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/test-pull-request.yml
Original file line numberDiff line numberDiff line change
Expand Up@@ -152,11 +152,11 @@ jobs:
actions: write
steps:
- name: Delete workflow artifacts step
# continue-on-error: best-effort housekeeping must never red the run, even on an unexpected failure.
continue-on-error: true
env:
GH_TOKEN: ${{ github.token }}
run: |
# Best-effort housekeeping: a failed list or delete logs a warning and continues so it never reds the run,
# while `set -e` still catches unexpected failures.
set -euo pipefail
if ! ids=$(gh api repos/${{ github.repository }}/actions/runs/${{ github.run_id }}/artifacts --paginate \
--jq '.artifacts[].id'); then
Expand Down
2 changes: 1 addition & 1 deletion AGENTS.md
Original file line numberDiff line numberDiff line change
Expand Up@@ -192,7 +192,7 @@ These conventions describe the target state. New and modified workflows must res
- **Boolean inputs**: workflows triggered both via `workflow_call` and `workflow_dispatch` must declare each boolean input in *both* trigger blocks - one definition does not propagate to the other. `workflow_call` delivers booleans as actual booleans; `workflow_dispatch` delivers them as the *strings* `"true"`/`"false"`. Any `if:` consuming a boolean input must compare against both forms - `if: ${{ inputs.foo == true || inputs.foo == 'true' }}`.
- **Reusable workflows**: job-level `permissions:` are validated *before* the `if:` evaluates, so even a skipped job needs valid permissions declared. A `release` job with `permissions: contents: write` and `if: ${{ inputs.publish }}` will still cause `startup_failure` on a caller that doesn't grant `contents: write`. Either declare permissions at the call site, or omit the inner block and inherit.
- **Allowlist `success` and `skipped` explicitly** when chaining jobs across optional dependencies - `!= 'failure'` lets `cancelled` through (timeout, runner failure, manual cancel). Use `(needs.X.result == 'success' || needs.X.result == 'skipped')`.
- **Artifact retention**: workflow artifacts are an intra-run handoff only - durable copies live on the GitHub release, not in workflow artifacts - so they must not survive the run and accumulate against the small account-wide artifact-storage quota. **Every workflow that can produce artifacts ends with a terminal `cleanup-artifacts` job** that deletes the run's artifacts via the REST API: `permissions: actions: write`, `needs` the artifact producers, an `if:` that **includes** `always()` (so a failed run still cleans up) plus any workflow-specific gate (e.g. `publish-release.yml` adds `&& needs.setup.outputs.publish == 'true'` to run only on real publishes), independent of any required status check so housekeeping never gates a merge, and tolerant of individual list/delete failures (warn and continue, never red the run). This covers not just `actions/upload-artifact` but build-records that actions emit automatically (e.g. `docker/build-push-action`'s `.dockerbuild`). Both `publish-release.yml` and `test-pull-request.yml` carry one; add one to any new artifact-producing entry workflow. Set `retention-days: 1` on explicit uploads as a backstop.
- **Artifact retention**: workflow artifacts are an intra-run handoff only - durable copies live on the GitHub release, not in workflow artifacts - so they must not survive the run and accumulate against the small account-wide artifact-storage quota. **Every workflow that can produce artifacts ends with a terminal `cleanup-artifacts` job** that deletes the run's artifacts via the REST API: `permissions: actions: write`, `needs` the artifact producers, an `if:` that **includes** `always()` (so a failed run still cleans up) plus any workflow-specific gate (e.g. `publish-release.yml` adds `&& needs.setup.outputs.publish == 'true'` to run only on real publishes), independent of any required status check so housekeeping never gates a merge, `continue-on-error: true` on the delete step so even an unexpected failure never reds the run, and tolerant of individual list/delete failures (warn and continue). This covers not just `actions/upload-artifact` but build-records that actions emit automatically (e.g. `docker/build-push-action`'s `.dockerbuild`). Both `publish-release.yml` and `test-pull-request.yml` carry one; add one to any new artifact-producing entry workflow. Set `retention-days: 1` on explicit uploads as a backstop.
- **Docker layer cache**: cache to/from a registry tag (`type=registry`, e.g. `buildcache-<branch>` on Docker Hub), not the GitHub Actions cache (`type=gha`), to keep large image layers off the 10 GB Actions cache.
- **Tag pinning on releases**: when using `softprops/action-gh-release` (or any tag-creating action), pass `target_commitish` explicitly - without it, GitHub's REST API defaults the new tag to the repository's default branch instead of the commit that built the artifact. Pin it to the **exact built commit's SHA** (the publisher uses NBGV's `GitCommitId` output), not `github.sha` (wrong branch in the publisher's branch matrix - a `develop` leg runs with `github.sha` = main's tip) and not a branch name (a moving ref that a mid-run commit could advance past the built tree).

Expand Down
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Highlight search terms from Google/DuckDuckGo/Bing referrer\n(function() {\n var ref = document.referrer;\n var terms = [];\n \n if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) {\n var url = new URL(ref);\n var q = url.searchParams.get('q') || url.searchParams.get('p');\n if (q) {\n terms = q.split(/\\s+/).filter(function(t) { return t.length > 2; });\n }\n }\n \n if (terms.length === 0) return;\n \n var style = document.createElement('style');\n style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }';\n document.head.appendChild(style);\n \n function highlight(node) {\n if (node.nodeType === 3) { // text node\n var text = node.textContent;\n var found = false;\n terms.forEach(function(term) {\n var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\') + ')', 'gi');\n if (regex.test(text)) {\n found = true;\n var frag = document.createDocumentFragment();\n var parts = text.split(regex);\n parts.forEach(function(part, i) {\n if (i % 2 === 0) {\n frag.appendChild(document.createTextNode(part));\n } else {\n var span = document.createElement('span');\n span.className = 'userscript-highlight';\n span.textContent = part;\n frag.appendChild(span);\n }\n });\n node.parentNode.replaceChild(frag, node);\n }\n });\n } else if (node.nodeType === 1 && node.childNodes) { // element\n var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT'];\n if (!skipTags.includes(node.tagName)) {\n Array.from(node.childNodes).forEach(highlight);\n }\n }\n }\n \n highlight(document.body);\n \n // Re-highlight on dynamic content\n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1 || node.nodeType === 3) highlight(node);\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Highlight Search Terms"); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .github/workflows/publish-release.yml
Original file line numberDiff line numberDiff line change
Expand Up@@ -164,11 +164,11 @@ jobs:
actions: write
steps:
- name: Delete workflow artifacts step
# continue-on-error: best-effort housekeeping must never red the run, even on an unexpected failure.
continue-on-error: true
env:
GH_TOKEN: ${{ github.token }}
run: |
# Best-effort housekeeping: a failed list or delete logs a warning and continues so it never reds the run,
# while `set -e` still catches unexpected failures.
set -euo pipefail
if ! ids=$(gh api repos/${{ github.repository }}/actions/runs/${{ github.run_id }}/artifacts --paginate \
--jq '.artifacts[].id'); then
Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/test-pull-request.yml
Original file line numberDiff line numberDiff line change
Expand Up@@ -152,11 +152,11 @@ jobs:
actions: write
steps:
- name: Delete workflow artifacts step
# continue-on-error: best-effort housekeeping must never red the run, even on an unexpected failure.
continue-on-error: true
env:
GH_TOKEN: ${{ github.token }}
run: |
# Best-effort housekeeping: a failed list or delete logs a warning and continues so it never reds the run,
# while `set -e` still catches unexpected failures.
set -euo pipefail
if ! ids=$(gh api repos/${{ github.repository }}/actions/runs/${{ github.run_id }}/artifacts --paginate \
--jq '.artifacts[].id'); then
Expand Down
2 changes: 1 addition & 1 deletion AGENTS.md
Original file line numberDiff line numberDiff line change
Expand Up@@ -192,7 +192,7 @@ These conventions describe the target state. New and modified workflows must res
- **Boolean inputs**: workflows triggered both via `workflow_call` and `workflow_dispatch` must declare each boolean input in *both* trigger blocks - one definition does not propagate to the other. `workflow_call` delivers booleans as actual booleans; `workflow_dispatch` delivers them as the *strings* `"true"`/`"false"`. Any `if:` consuming a boolean input must compare against both forms - `if: ${{ inputs.foo == true || inputs.foo == 'true' }}`.
- **Reusable workflows**: job-level `permissions:` are validated *before* the `if:` evaluates, so even a skipped job needs valid permissions declared. A `release` job with `permissions: contents: write` and `if: ${{ inputs.publish }}` will still cause `startup_failure` on a caller that doesn't grant `contents: write`. Either declare permissions at the call site, or omit the inner block and inherit.
- **Allowlist `success` and `skipped` explicitly** when chaining jobs across optional dependencies - `!= 'failure'` lets `cancelled` through (timeout, runner failure, manual cancel). Use `(needs.X.result == 'success' || needs.X.result == 'skipped')`.
- **Artifact retention**: workflow artifacts are an intra-run handoff only - durable copies live on the GitHub release, not in workflow artifacts - so they must not survive the run and accumulate against the small account-wide artifact-storage quota. **Every workflow that can produce artifacts ends with a terminal `cleanup-artifacts` job** that deletes the run's artifacts via the REST API: `permissions: actions: write`, `needs` the artifact producers, an `if:` that **includes** `always()` (so a failed run still cleans up) plus any workflow-specific gate (e.g. `publish-release.yml` adds `&& needs.setup.outputs.publish == 'true'` to run only on real publishes), independent of any required status check so housekeeping never gates a merge, and tolerant of individual list/delete failures (warn and continue, never red the run). This covers not just `actions/upload-artifact` but build-records that actions emit automatically (e.g. `docker/build-push-action`'s `.dockerbuild`). Both `publish-release.yml` and `test-pull-request.yml` carry one; add one to any new artifact-producing entry workflow. Set `retention-days: 1` on explicit uploads as a backstop.
- **Artifact retention**: workflow artifacts are an intra-run handoff only - durable copies live on the GitHub release, not in workflow artifacts - so they must not survive the run and accumulate against the small account-wide artifact-storage quota. **Every workflow that can produce artifacts ends with a terminal `cleanup-artifacts` job** that deletes the run's artifacts via the REST API: `permissions: actions: write`, `needs` the artifact producers, an `if:` that **includes** `always()` (so a failed run still cleans up) plus any workflow-specific gate (e.g. `publish-release.yml` adds `&& needs.setup.outputs.publish == 'true'` to run only on real publishes), independent of any required status check so housekeeping never gates a merge, `continue-on-error: true` on the delete step so even an unexpected failure never reds the run, and tolerant of individual list/delete failures (warn and continue). This covers not just `actions/upload-artifact` but build-records that actions emit automatically (e.g. `docker/build-push-action`'s `.dockerbuild`). Both `publish-release.yml` and `test-pull-request.yml` carry one; add one to any new artifact-producing entry workflow. Set `retention-days: 1` on explicit uploads as a backstop.
- **Docker layer cache**: cache to/from a registry tag (`type=registry`, e.g. `buildcache-<branch>` on Docker Hub), not the GitHub Actions cache (`type=gha`), to keep large image layers off the 10 GB Actions cache.
- **Tag pinning on releases**: when using `softprops/action-gh-release` (or any tag-creating action), pass `target_commitish` explicitly - without it, GitHub's REST API defaults the new tag to the repository's default branch instead of the commit that built the artifact. Pin it to the **exact built commit's SHA** (the publisher uses NBGV's `GitCommitId` output), not `github.sha` (wrong branch in the publisher's branch matrix - a `develop` leg runs with `github.sha` = main's tip) and not a branch name (a moving ref that a mid-run commit could advance past the built tree).

Expand Down
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Strip utm_, fbclid, gclid, etc. from all links on page\n(function() {\n var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content',\n 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid',\n 'ref', 'ref_src', 'source', 'medium', 'campaign'];\n \n function cleanUrl(url) {\n try {\n var u = new URL(url, window.location.origin);\n var changed = false;\n trackingParams.forEach(function(p) {\n if (u.searchParams.has(p)) {\n u.searchParams.delete(p);\n changed = true;\n }\n });\n return changed ? u.toString() : url;\n } catch (e) {\n return url;\n }\n }\n \n function cleanLinks() {\n document.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n \n cleanLinks();\n \n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1) {\n if (node.tagName === 'A') cleanLinks();\n node.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Remove Tracking Parameters from Links"); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + '
Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .github/workflows/publish-release.yml
Original file line numberDiff line numberDiff line change
Expand Up@@ -164,11 +164,11 @@ jobs:
actions: write
steps:
- name: Delete workflow artifacts step
# continue-on-error: best-effort housekeeping must never red the run, even on an unexpected failure.
continue-on-error: true
env:
GH_TOKEN: ${{ github.token }}
run: |
# Best-effort housekeeping: a failed list or delete logs a warning and continues so it never reds the run,
# while `set -e` still catches unexpected failures.
set -euo pipefail
if ! ids=$(gh api repos/${{ github.repository }}/actions/runs/${{ github.run_id }}/artifacts --paginate \
--jq '.artifacts[].id'); then
Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/test-pull-request.yml
Original file line numberDiff line numberDiff line change
Expand Up@@ -152,11 +152,11 @@ jobs:
actions: write
steps:
- name: Delete workflow artifacts step
# continue-on-error: best-effort housekeeping must never red the run, even on an unexpected failure.
continue-on-error: true
env:
GH_TOKEN: ${{ github.token }}
run: |
# Best-effort housekeeping: a failed list or delete logs a warning and continues so it never reds the run,
# while `set -e` still catches unexpected failures.
set -euo pipefail
if ! ids=$(gh api repos/${{ github.repository }}/actions/runs/${{ github.run_id }}/artifacts --paginate \
--jq '.artifacts[].id'); then
Expand Down
2 changes: 1 addition & 1 deletion AGENTS.md
Original file line numberDiff line numberDiff line change
Expand Up@@ -192,7 +192,7 @@ These conventions describe the target state. New and modified workflows must res
- **Boolean inputs**: workflows triggered both via `workflow_call` and `workflow_dispatch` must declare each boolean input in *both* trigger blocks - one definition does not propagate to the other. `workflow_call` delivers booleans as actual booleans; `workflow_dispatch` delivers them as the *strings* `"true"`/`"false"`. Any `if:` consuming a boolean input must compare against both forms - `if: ${{ inputs.foo == true || inputs.foo == 'true' }}`.
- **Reusable workflows**: job-level `permissions:` are validated *before* the `if:` evaluates, so even a skipped job needs valid permissions declared. A `release` job with `permissions: contents: write` and `if: ${{ inputs.publish }}` will still cause `startup_failure` on a caller that doesn't grant `contents: write`. Either declare permissions at the call site, or omit the inner block and inherit.
- **Allowlist `success` and `skipped` explicitly** when chaining jobs across optional dependencies - `!= 'failure'` lets `cancelled` through (timeout, runner failure, manual cancel). Use `(needs.X.result == 'success' || needs.X.result == 'skipped')`.
- **Artifact retention**: workflow artifacts are an intra-run handoff only - durable copies live on the GitHub release, not in workflow artifacts - so they must not survive the run and accumulate against the small account-wide artifact-storage quota. **Every workflow that can produce artifacts ends with a terminal `cleanup-artifacts` job** that deletes the run's artifacts via the REST API: `permissions: actions: write`, `needs` the artifact producers, an `if:` that **includes** `always()` (so a failed run still cleans up) plus any workflow-specific gate (e.g. `publish-release.yml` adds `&& needs.setup.outputs.publish == 'true'` to run only on real publishes), independent of any required status check so housekeeping never gates a merge, and tolerant of individual list/delete failures (warn and continue, never red the run). This covers not just `actions/upload-artifact` but build-records that actions emit automatically (e.g. `docker/build-push-action`'s `.dockerbuild`). Both `publish-release.yml` and `test-pull-request.yml` carry one; add one to any new artifact-producing entry workflow. Set `retention-days: 1` on explicit uploads as a backstop.
- **Artifact retention**: workflow artifacts are an intra-run handoff only - durable copies live on the GitHub release, not in workflow artifacts - so they must not survive the run and accumulate against the small account-wide artifact-storage quota. **Every workflow that can produce artifacts ends with a terminal `cleanup-artifacts` job** that deletes the run's artifacts via the REST API: `permissions: actions: write`, `needs` the artifact producers, an `if:` that **includes** `always()` (so a failed run still cleans up) plus any workflow-specific gate (e.g. `publish-release.yml` adds `&& needs.setup.outputs.publish == 'true'` to run only on real publishes), independent of any required status check so housekeeping never gates a merge, `continue-on-error: true` on the delete step so even an unexpected failure never reds the run, and tolerant of individual list/delete failures (warn and continue). This covers not just `actions/upload-artifact` but build-records that actions emit automatically (e.g. `docker/build-push-action`'s `.dockerbuild`). Both `publish-release.yml` and `test-pull-request.yml` carry one; add one to any new artifact-producing entry workflow. Set `retention-days: 1` on explicit uploads as a backstop.
- **Docker layer cache**: cache to/from a registry tag (`type=registry`, e.g. `buildcache-<branch>` on Docker Hub), not the GitHub Actions cache (`type=gha`), to keep large image layers off the 10 GB Actions cache.
- **Tag pinning on releases**: when using `softprops/action-gh-release` (or any tag-creating action), pass `target_commitish` explicitly - without it, GitHub's REST API defaults the new tag to the repository's default branch instead of the commit that built the artifact. Pin it to the **exact built commit's SHA** (the publisher uses NBGV's `GitCommitId` output), not `github.sha` (wrong branch in the publisher's branch matrix - a `develop` leg runs with `github.sha` = main's tip) and not a branch name (a moving ref that a mid-run commit could advance past the built tree).

Expand Down
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Auto-enable theater mode on YouTube\n(function() {\n function tryTheater() {\n var btn = document.querySelector('button[aria-label=\"Theater mode\"], ytd-player #player button[title=\"Theater mode\"]');\n if (btn && !btn.classList.contains('activated')) {\n btn.click();\n }\n }\n \n // Try immediately\n tryTheater();\n \n // Try after navigation (SPA)\n var lastUrl = location.href;\n setInterval(function() {\n if (location.href !== lastUrl) {\n lastUrl = location.href;\n setTimeout(tryTheater, 500);\n }\n }, 1000);\n \n // Also try on player load\n var observer = new MutationObserver(tryTheater);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "YouTube Theater Mode Default"); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .github/workflows/publish-release.yml
Original file line numberDiff line numberDiff line change
Expand Up@@ -164,11 +164,11 @@ jobs:
actions: write
steps:
- name: Delete workflow artifacts step
# continue-on-error: best-effort housekeeping must never red the run, even on an unexpected failure.
continue-on-error: true
env:
GH_TOKEN: ${{ github.token }}
run: |
# Best-effort housekeeping: a failed list or delete logs a warning and continues so it never reds the run,
# while `set -e` still catches unexpected failures.
set -euo pipefail
if ! ids=$(gh api repos/${{ github.repository }}/actions/runs/${{ github.run_id }}/artifacts --paginate \
--jq '.artifacts[].id'); then
Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/test-pull-request.yml
Original file line numberDiff line numberDiff line change
Expand Up@@ -152,11 +152,11 @@ jobs:
actions: write
steps:
- name: Delete workflow artifacts step
# continue-on-error: best-effort housekeeping must never red the run, even on an unexpected failure.
continue-on-error: true
env:
GH_TOKEN: ${{ github.token }}
run: |
# Best-effort housekeeping: a failed list or delete logs a warning and continues so it never reds the run,
# while `set -e` still catches unexpected failures.
set -euo pipefail
if ! ids=$(gh api repos/${{ github.repository }}/actions/runs/${{ github.run_id }}/artifacts --paginate \
--jq '.artifacts[].id'); then
Expand Down
2 changes: 1 addition & 1 deletion AGENTS.md
Original file line numberDiff line numberDiff line change
Expand Up@@ -192,7 +192,7 @@ These conventions describe the target state. New and modified workflows must res
- **Boolean inputs**: workflows triggered both via `workflow_call` and `workflow_dispatch` must declare each boolean input in *both* trigger blocks - one definition does not propagate to the other. `workflow_call` delivers booleans as actual booleans; `workflow_dispatch` delivers them as the *strings* `"true"`/`"false"`. Any `if:` consuming a boolean input must compare against both forms - `if: ${{ inputs.foo == true || inputs.foo == 'true' }}`.
- **Reusable workflows**: job-level `permissions:` are validated *before* the `if:` evaluates, so even a skipped job needs valid permissions declared. A `release` job with `permissions: contents: write` and `if: ${{ inputs.publish }}` will still cause `startup_failure` on a caller that doesn't grant `contents: write`. Either declare permissions at the call site, or omit the inner block and inherit.
- **Allowlist `success` and `skipped` explicitly** when chaining jobs across optional dependencies - `!= 'failure'` lets `cancelled` through (timeout, runner failure, manual cancel). Use `(needs.X.result == 'success' || needs.X.result == 'skipped')`.
- **Artifact retention**: workflow artifacts are an intra-run handoff only - durable copies live on the GitHub release, not in workflow artifacts - so they must not survive the run and accumulate against the small account-wide artifact-storage quota. **Every workflow that can produce artifacts ends with a terminal `cleanup-artifacts` job** that deletes the run's artifacts via the REST API: `permissions: actions: write`, `needs` the artifact producers, an `if:` that **includes** `always()` (so a failed run still cleans up) plus any workflow-specific gate (e.g. `publish-release.yml` adds `&& needs.setup.outputs.publish == 'true'` to run only on real publishes), independent of any required status check so housekeeping never gates a merge, and tolerant of individual list/delete failures (warn and continue, never red the run). This covers not just `actions/upload-artifact` but build-records that actions emit automatically (e.g. `docker/build-push-action`'s `.dockerbuild`). Both `publish-release.yml` and `test-pull-request.yml` carry one; add one to any new artifact-producing entry workflow. Set `retention-days: 1` on explicit uploads as a backstop.
- **Artifact retention**: workflow artifacts are an intra-run handoff only - durable copies live on the GitHub release, not in workflow artifacts - so they must not survive the run and accumulate against the small account-wide artifact-storage quota. **Every workflow that can produce artifacts ends with a terminal `cleanup-artifacts` job** that deletes the run's artifacts via the REST API: `permissions: actions: write`, `needs` the artifact producers, an `if:` that **includes** `always()` (so a failed run still cleans up) plus any workflow-specific gate (e.g. `publish-release.yml` adds `&& needs.setup.outputs.publish == 'true'` to run only on real publishes), independent of any required status check so housekeeping never gates a merge, `continue-on-error: true` on the delete step so even an unexpected failure never reds the run, and tolerant of individual list/delete failures (warn and continue). This covers not just `actions/upload-artifact` but build-records that actions emit automatically (e.g. `docker/build-push-action`'s `.dockerbuild`). Both `publish-release.yml` and `test-pull-request.yml` carry one; add one to any new artifact-producing entry workflow. Set `retention-days: 1` on explicit uploads as a backstop.
- **Docker layer cache**: cache to/from a registry tag (`type=registry`, e.g. `buildcache-<branch>` on Docker Hub), not the GitHub Actions cache (`type=gha`), to keep large image layers off the 10 GB Actions cache.
- **Tag pinning on releases**: when using `softprops/action-gh-release` (or any tag-creating action), pass `target_commitish` explicitly - without it, GitHub's REST API defaults the new tag to the repository's default branch instead of the commit that built the artifact. Pin it to the **exact built commit's SHA** (the publisher uses NBGV's `GitCommitId` output), not `github.sha` (wrong branch in the publisher's branch matrix - a `develop` leg runs with `github.sha` = main's tip) and not a branch name (a moving ref that a mid-run commit could advance past the built tree).

Expand Down
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Remove or un-stick sticky/fixed headers that block content\n(function() {\n function unstick() {\n document.querySelectorAll('header, nav, [role=\"banner\"], .header, .navbar, .sticky, .fixed-top, [style*=\"position: fixed\"], [style*=\"position:sticky\"]').forEach(function(el) {\n if (el.style.position === 'fixed' || el.style.position === 'sticky' || \n getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') {\n el.style.position = 'static';\n el.style.top = 'auto';\n el.style.zIndex = 'auto';\n }\n });\n }\n \n unstick();\n \n var observer = new MutationObserver(unstick);\n observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] });\n})();", "Kill Sticky Headers"); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .github/workflows/publish-release.yml
Original file line numberDiff line numberDiff line change
Expand Up@@ -164,11 +164,11 @@ jobs:
actions: write
steps:
- name: Delete workflow artifacts step
# continue-on-error: best-effort housekeeping must never red the run, even on an unexpected failure.
continue-on-error: true
env:
GH_TOKEN: ${{ github.token }}
run: |
# Best-effort housekeeping: a failed list or delete logs a warning and continues so it never reds the run,
# while `set -e` still catches unexpected failures.
set -euo pipefail
if ! ids=$(gh api repos/${{ github.repository }}/actions/runs/${{ github.run_id }}/artifacts --paginate \
--jq '.artifacts[].id'); then
Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/test-pull-request.yml
Original file line numberDiff line numberDiff line change
Expand Up@@ -152,11 +152,11 @@ jobs:
actions: write
steps:
- name: Delete workflow artifacts step
# continue-on-error: best-effort housekeeping must never red the run, even on an unexpected failure.
continue-on-error: true
env:
GH_TOKEN: ${{ github.token }}
run: |
# Best-effort housekeeping: a failed list or delete logs a warning and continues so it never reds the run,
# while `set -e` still catches unexpected failures.
set -euo pipefail
if ! ids=$(gh api repos/${{ github.repository }}/actions/runs/${{ github.run_id }}/artifacts --paginate \
--jq '.artifacts[].id'); then
Expand Down
2 changes: 1 addition & 1 deletion AGENTS.md
Original file line numberDiff line numberDiff line change
Expand Up@@ -192,7 +192,7 @@ These conventions describe the target state. New and modified workflows must res
- **Boolean inputs**: workflows triggered both via `workflow_call` and `workflow_dispatch` must declare each boolean input in *both* trigger blocks - one definition does not propagate to the other. `workflow_call` delivers booleans as actual booleans; `workflow_dispatch` delivers them as the *strings* `"true"`/`"false"`. Any `if:` consuming a boolean input must compare against both forms - `if: ${{ inputs.foo == true || inputs.foo == 'true' }}`.
- **Reusable workflows**: job-level `permissions:` are validated *before* the `if:` evaluates, so even a skipped job needs valid permissions declared. A `release` job with `permissions: contents: write` and `if: ${{ inputs.publish }}` will still cause `startup_failure` on a caller that doesn't grant `contents: write`. Either declare permissions at the call site, or omit the inner block and inherit.
- **Allowlist `success` and `skipped` explicitly** when chaining jobs across optional dependencies - `!= 'failure'` lets `cancelled` through (timeout, runner failure, manual cancel). Use `(needs.X.result == 'success' || needs.X.result == 'skipped')`.
- **Artifact retention**: workflow artifacts are an intra-run handoff only - durable copies live on the GitHub release, not in workflow artifacts - so they must not survive the run and accumulate against the small account-wide artifact-storage quota. **Every workflow that can produce artifacts ends with a terminal `cleanup-artifacts` job** that deletes the run's artifacts via the REST API: `permissions: actions: write`, `needs` the artifact producers, an `if:` that **includes** `always()` (so a failed run still cleans up) plus any workflow-specific gate (e.g. `publish-release.yml` adds `&& needs.setup.outputs.publish == 'true'` to run only on real publishes), independent of any required status check so housekeeping never gates a merge, and tolerant of individual list/delete failures (warn and continue, never red the run). This covers not just `actions/upload-artifact` but build-records that actions emit automatically (e.g. `docker/build-push-action`'s `.dockerbuild`). Both `publish-release.yml` and `test-pull-request.yml` carry one; add one to any new artifact-producing entry workflow. Set `retention-days: 1` on explicit uploads as a backstop.
- **Artifact retention**: workflow artifacts are an intra-run handoff only - durable copies live on the GitHub release, not in workflow artifacts - so they must not survive the run and accumulate against the small account-wide artifact-storage quota. **Every workflow that can produce artifacts ends with a terminal `cleanup-artifacts` job** that deletes the run's artifacts via the REST API: `permissions: actions: write`, `needs` the artifact producers, an `if:` that **includes** `always()` (so a failed run still cleans up) plus any workflow-specific gate (e.g. `publish-release.yml` adds `&& needs.setup.outputs.publish == 'true'` to run only on real publishes), independent of any required status check so housekeeping never gates a merge, `continue-on-error: true` on the delete step so even an unexpected failure never reds the run, and tolerant of individual list/delete failures (warn and continue). This covers not just `actions/upload-artifact` but build-records that actions emit automatically (e.g. `docker/build-push-action`'s `.dockerbuild`). Both `publish-release.yml` and `test-pull-request.yml` carry one; add one to any new artifact-producing entry workflow. Set `retention-days: 1` on explicit uploads as a backstop.
- **Docker layer cache**: cache to/from a registry tag (`type=registry`, e.g. `buildcache-<branch>` on Docker Hub), not the GitHub Actions cache (`type=gha`), to keep large image layers off the 10 GB Actions cache.
- **Tag pinning on releases**: when using `softprops/action-gh-release` (or any tag-creating action), pass `target_commitish` explicitly - without it, GitHub's REST API defaults the new tag to the repository's default branch instead of the commit that built the artifact. Pin it to the **exact built commit's SHA** (the publisher uses NBGV's `GitCommitId` output), not `github.sha` (wrong branch in the publisher's branch matrix - a `develop` leg runs with `github.sha` = main's tip) and not a branch name (a moving ref that a mid-run commit could advance past the built tree).

Expand Down
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Universal Dark Mode - works on any site\n(function() {\n var enabled = true;\n \n function applyDarkMode() {\n if (!enabled) return;\n \n // Create style element if it doesn't exist\n var style = document.getElementById('universal-dark-mode-style');\n if (!style) {\n style = document.createElement('style');\n style.id = 'universal-dark-mode-style';\n document.head.appendChild(style);\n }\n \n // Dark mode CSS - inverts colors but preserves images/video\n style.textContent = '\n /* Invert everything except media */\n html {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #1a1a2e !important;\n }\n \n /* Restore images, videos, iframes, canvas */\n img, video, iframe, canvas, svg, picture, [style*=\"background-image\"] {\n filter: invert(1) hue-rotate(180deg) !important;\n }\n \n /* Preserve specific elements that should not be inverted */\n .no-dark-mode, .no-dark-mode *,\n [data-theme=\"light\"], [data-theme=\"light\"],\n .ace_editor, .ace_editor *,\n .CodeMirror, .CodeMirror *,\n .monaco-editor, .monaco-editor *,\n .markdown-body pre, .markdown-body pre *,\n .highlight, .highlight *,\n pre code, pre code * {\n filter: none !important;\n }\n \n /* Fix common UI elements */\n .modal, .popup, .dropdown-menu, .tooltip, .popover {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #2d2d44 !important;\n border-color: #444 !important;\n }\n \n /* Scrollbars */\n ::-webkit-scrollbar { background: #1a1a2e !important; }\n ::-webkit-scrollbar-thumb { background: #444 !important; }\n ::-webkit-scrollbar-thumb:hover { background: #555 !important; }\n \n /* Selection */\n ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ';\n }\n \n function removeDarkMode() {\n var style = document.getElementById('universal-dark-mode-style');\n if (style) style.remove();\n }\n \n // Toggle with Alt+Shift+D\n document.addEventListener('keydown', function(e) {\n if (e.altKey && e.shiftKey && e.key === 'D') {\n e.preventDefault();\n enabled = !enabled;\n if (enabled) {\n applyDarkMode();\n console.log('[Universal Dark Mode] Enabled');\n } else {\n removeDarkMode();\n console.log('[Universal Dark Mode] Disabled');\n }\n }\n });\n \n // Apply on load\n applyDarkMode();\n \n // Re-apply on dynamic content\n var observer = new MutationObserver(function(mutations) {\n if (enabled && !document.getElementById('universal-dark-mode-style')) {\n applyDarkMode();\n }\n });\n observer.observe(document.head, { childList: true });\n \n console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle');\n})();", "Universal Dark Mode"); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })();
Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .github/workflows/publish-release.yml
Original file line numberDiff line numberDiff line change
Expand Up@@ -164,11 +164,11 @@ jobs:
actions: write
steps:
- name: Delete workflow artifacts step
# continue-on-error: best-effort housekeeping must never red the run, even on an unexpected failure.
continue-on-error: true
env:
GH_TOKEN: ${{ github.token }}
run: |
# Best-effort housekeeping: a failed list or delete logs a warning and continues so it never reds the run,
# while `set -e` still catches unexpected failures.
set -euo pipefail
if ! ids=$(gh api repos/${{ github.repository }}/actions/runs/${{ github.run_id }}/artifacts --paginate \
--jq '.artifacts[].id'); then
Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/test-pull-request.yml
Original file line numberDiff line numberDiff line change
Expand Up@@ -152,11 +152,11 @@ jobs:
actions: write
steps:
- name: Delete workflow artifacts step
# continue-on-error: best-effort housekeeping must never red the run, even on an unexpected failure.
continue-on-error: true
env:
GH_TOKEN: ${{ github.token }}
run: |
# Best-effort housekeeping: a failed list or delete logs a warning and continues so it never reds the run,
# while `set -e` still catches unexpected failures.
set -euo pipefail
if ! ids=$(gh api repos/${{ github.repository }}/actions/runs/${{ github.run_id }}/artifacts --paginate \
--jq '.artifacts[].id'); then
Expand Down
2 changes: 1 addition & 1 deletion AGENTS.md
Original file line numberDiff line numberDiff line change
Expand Up@@ -192,7 +192,7 @@ These conventions describe the target state. New and modified workflows must res
- **Boolean inputs**: workflows triggered both via `workflow_call` and `workflow_dispatch` must declare each boolean input in *both* trigger blocks - one definition does not propagate to the other. `workflow_call` delivers booleans as actual booleans; `workflow_dispatch` delivers them as the *strings* `"true"`/`"false"`. Any `if:` consuming a boolean input must compare against both forms - `if: ${{ inputs.foo == true || inputs.foo == 'true' }}`.
- **Reusable workflows**: job-level `permissions:` are validated *before* the `if:` evaluates, so even a skipped job needs valid permissions declared. A `release` job with `permissions: contents: write` and `if: ${{ inputs.publish }}` will still cause `startup_failure` on a caller that doesn't grant `contents: write`. Either declare permissions at the call site, or omit the inner block and inherit.
- **Allowlist `success` and `skipped` explicitly** when chaining jobs across optional dependencies - `!= 'failure'` lets `cancelled` through (timeout, runner failure, manual cancel). Use `(needs.X.result == 'success' || needs.X.result == 'skipped')`.
- **Artifact retention**: workflow artifacts are an intra-run handoff only - durable copies live on the GitHub release, not in workflow artifacts - so they must not survive the run and accumulate against the small account-wide artifact-storage quota. **Every workflow that can produce artifacts ends with a terminal `cleanup-artifacts` job** that deletes the run's artifacts via the REST API: `permissions: actions: write`, `needs` the artifact producers, an `if:` that **includes** `always()` (so a failed run still cleans up) plus any workflow-specific gate (e.g. `publish-release.yml` adds `&& needs.setup.outputs.publish == 'true'` to run only on real publishes), independent of any required status check so housekeeping never gates a merge, and tolerant of individual list/delete failures (warn and continue, never red the run). This covers not just `actions/upload-artifact` but build-records that actions emit automatically (e.g. `docker/build-push-action`'s `.dockerbuild`). Both `publish-release.yml` and `test-pull-request.yml` carry one; add one to any new artifact-producing entry workflow. Set `retention-days: 1` on explicit uploads as a backstop.
- **Artifact retention**: workflow artifacts are an intra-run handoff only - durable copies live on the GitHub release, not in workflow artifacts - so they must not survive the run and accumulate against the small account-wide artifact-storage quota. **Every workflow that can produce artifacts ends with a terminal `cleanup-artifacts` job** that deletes the run's artifacts via the REST API: `permissions: actions: write`, `needs` the artifact producers, an `if:` that **includes** `always()` (so a failed run still cleans up) plus any workflow-specific gate (e.g. `publish-release.yml` adds `&& needs.setup.outputs.publish == 'true'` to run only on real publishes), independent of any required status check so housekeeping never gates a merge, `continue-on-error: true` on the delete step so even an unexpected failure never reds the run, and tolerant of individual list/delete failures (warn and continue). This covers not just `actions/upload-artifact` but build-records that actions emit automatically (e.g. `docker/build-push-action`'s `.dockerbuild`). Both `publish-release.yml` and `test-pull-request.yml` carry one; add one to any new artifact-producing entry workflow. Set `retention-days: 1` on explicit uploads as a backstop.
- **Docker layer cache**: cache to/from a registry tag (`type=registry`, e.g. `buildcache-<branch>` on Docker Hub), not the GitHub Actions cache (`type=gha`), to keep large image layers off the 10 GB Actions cache.
- **Tag pinning on releases**: when using `softprops/action-gh-release` (or any tag-creating action), pass `target_commitish` explicitly - without it, GitHub's REST API defaults the new tag to the repository's default branch instead of the commit that built the artifact. Pin it to the **exact built commit's SHA** (the publisher uses NBGV's `GitCommitId` output), not `github.sha` (wrong branch in the publisher's branch matrix - a `develop` leg runs with `github.sha` = main's tip) and not a branch name (a moving ref that a mid-run commit could advance past the built tree).

Expand Down