Files
d bef8560ee0 Squashed commit of the following:
commit b06002f449
Author: wxiaoguang <wxiaoguang@gmail.com>
Date:   Sun Jul 19 15:32:00 2026 +0800

    refactor: git repo and relative path handling (#38522)

    1. simplify "StorageRepo" code
    2. simplify git.OpenRepository code
    3. by the way, clean up some unused files in git test fixtures.

commit ae176cd649
Author: YumeMichi <do4suki@gmail.com>
Date:   Sun Jul 19 11:20:01 2026 +0800

    refactor: clean up fragile diff render templates, use backend typed structs (#38517)

    Blob.Size requires a context after the repository context removal
    (5b078f72aa).

    Actually the template code should just render, it should not depend on
    the fragile dynamic calls to backend functions.

    ---------

    Co-authored-by: wxiaoguang <wxiaoguang@gmail.com>

commit e8befe0268
Author: bircni <bircni@icloud.com>
Date:   Sat Jul 18 17:08:09 2026 +0200

    fix(actions): coerce workflow_dispatch boolean inputs to native types (#38472)

    A `workflow_dispatch` job that has `needs:` **and** an `if:` comparing a
    boolean
    input against a boolean literal never runs — it stays `Blocked` forever
    even
    though its needs succeed. Minimal repro:

    ```yaml
    on:
      workflow_dispatch:
        inputs:
          deploy:
            type: boolean
            default: true
    jobs:
      build:
        runs-on: ubuntu-latest
        steps: [{ run: echo build }]
      deploy:
        needs: build
        if: ${{ inputs.deploy == true }}   # never true on Gitea
        runs-on: ubuntu-latest
        steps: [{ run: echo deploy }]
    ```

    On GitHub this runs; on Gitea `deploy` is stuck. Jobs **without**
    `needs` are
    unaffected, which makes it look like a matrix/`needs` bug — it isn't.

    `workflow_dispatch` stores boolean inputs as the strings
    `"true"`/`"false"`
    (`ctx.FormBool` → `strconv.FormatBool` in the web path, plain strings in
    the API
    path). Since #37478 (shipped in **v1.27.0**), `evaluateJobIf` runs
    **server-side**
    as part of the job-emitter resolver passes. For a `needs`-gated job the
    server
    therefore evaluates `inputs.deploy == true` with `inputs.deploy` being
    the string
    `"true"`; comparing a string to a boolean coerces to `NaN == 1` →
    `false`, so the
    job is never dispatched.

    Jobs without `needs` skip this server-side gate and are evaluated by the
    runner,
    which coerces the string to a real bool — that's why they keep working,
    and why
    the same input yields opposite results in the two paths.

    Normalize `type: boolean` dispatch inputs to native JSON booleans in the
    shared
    `DispatchActionWorkflow` path, so it covers both the web and API entry
    points in
    one place. The coerced value flows into both the run's `EventPayload`
    (read back
    by the server-side `if` evaluation and by the runner) and the
    creation-time
    parse, so all consumers agree.

    This matches GitHub, whose `inputs` context "preserves Boolean values as
    Booleans
    instead of converting them to strings", and mirrors the native JSON
    types Gitea
    already sends for `workflow_call`. Only booleans are coerced; other
    input types
    are left untouched, and a value that is already a bool (JSON API
    request) passes
    through.

    Note: this makes dispatch payloads carry native booleans, which the
    runner
    consumes correctly as of gitea/runner#1087 (it accepts a native bool and
    keeps
    the string fallback) — the same expectation `workflow_call` already
    relies on.

    Fixes https://github.com/go-gitea/gitea/issues/38466

commit 66e3849a70
Author: wxiaoguang <wxiaoguang@gmail.com>
Date:   Sat Jul 18 21:28:14 2026 +0800

    refactor: correct git repo design and fix some legacy problems (#38512)

commit 7786df34cf
Author: wxiaoguang <wxiaoguang@gmail.com>
Date:   Sat Jul 18 17:44:01 2026 +0800

    fix: make the merge box button red if some checks fail (#38508)

    fix #38506

    * 1.26: the "show form" button and "submit form" button are all red if
    some checks fail
    * 1.27.0: the "show form" button uses primary color, while "submit form"
    button is red if some checks fail
    * this fix: revert to 1.26

commit c6791c3c58
Author: Knight <raypranav718@gmail.com>
Date:   Sat Jul 18 13:08:36 2026 +0530

    fix: clean up orphaned user-keyed tables in deleteUser (#38511)
    This PR addresses orphaned user-keyed tables during user deletion by
    adding the missing models to the `db.DeleteBeans` call in
    `services/user/delete.go`:
    - `auth_model.TwoFactor` (TOTP secrets)
    - `auth_model.WebAuthnCredential` (WebAuthn keys)
    - `activities_model.Notification` (Notifications)
    - `issues_model.IssueWatch` (Issue watches)

    Additionally, it adds corresponding unit test coverage in
    `services/user/user_test.go` to assert that these records are cleaned up
    successfully.
    Fixes #38510

    Signed-off-by: pranav718 <raypranav718@gmail.com>

commit 2cc28ac2a9
Author: GiteaBot <teabot@gitea.io>
Date:   Sat Jul 18 00:46:45 2026 +0000

    [skip ci] Updated translations via Crowdin

commit ba7c84673b
Author: bircni <bircni@icloud.com>
Date:   Fri Jul 17 17:31:40 2026 +0200

    docs: Update Changelog for 1.27 (#38440)

    Signed-off-by: wxiaoguang <wxiaoguang@gmail.com>
    Co-authored-by: wxiaoguang <wxiaoguang@gmail.com>

commit 3027794c44
Author: wxiaoguang <wxiaoguang@gmail.com>
Date:   Fri Jul 17 22:28:59 2026 +0800

    refactor: fix legacy problems in cmd/serv.go (#38505)

    1. use var names "reqOwnerName, reqRepoName", because these values are
    from request and should not be really used for path construction
    2. simplify enable-pprof logic, don't "log.Fatal"
    3. don't make runServe command to guess the repo storage path, instead,
    let server return RepoStoragePath
    4. don't process lfs verbs when the repo is a wiki
    5. construct the request URI path correctly for the lfs transfer backend
    (moved to the caller)
    6. don't call "owner, err := user_model.GetUserByName", the "owner
    rename redirection" has been done before
    7. fix incorrect "repo.OwnerName = ownerName", the real owner might have
    been "redirected"
    8. fix incorrect "inactive owner" check, it should be checked even if
    the repo is redirected

    Use general error functions to handle responses, error handling code is
    hugely simplified.

commit 5b078f72aa
Author: wxiaoguang <wxiaoguang@gmail.com>
Date:   Fri Jul 17 18:44:31 2026 +0800

    refactor: remove Ctx field from git.Repository (#38500)

commit 2c8e99bbf7
Author: wxiaoguang <wxiaoguang@gmail.com>
Date:   Fri Jul 17 15:44:05 2026 +0800

    fix: make commit message merge correctly (#38490)

    fix #38487

    ---------

    Co-authored-by: silverwind <me@silverwind.io>
    Co-authored-by: bircni <bircni@icloud.com>

commit 8a3daef525
Author: TowyTowy <85077986+TowyTowy@users.noreply.github.com>
Date:   Fri Jul 17 07:17:28 2026 +0200

    fix(repo): stop advertising HTTP clone URLs when DISABLE_HTTP_GIT is set (#38378)

    Fixes #38339

    ---------

    Signed-off-by: TowyTowy <towy@airreps.link>
    Co-authored-by: wxiaoguang <wxiaoguang@gmail.com>

commit bca44bd736
Author: GiteaBot <teabot@gitea.io>
Date:   Fri Jul 17 00:51:13 2026 +0000

    [skip ci] Updated translations via Crowdin

commit b4e601339f
Author: silverwind <me@silverwind.io>
Date:   Thu Jul 16 23:56:31 2026 +0200

    ci: retry snap store upload on transient connection drops (#38461)

    Add a retry to snapstore. Claude can't seem to figure out the reason why
    so many nightly uploads fail and the only logical conclusion is it's a
    server-side issue at Canonical, so retries might help.

    Example:
    https://github.com/go-gitea/gitea/actions/runs/29395231850/job/87287126446

commit a49c893842
Author: Eyüp Can Akman <eyupcanakman@gmail.com>
Date:   Fri Jul 17 00:38:39 2026 +0300

    fix(pull): sign the commit when updating a branch by merge (#38441)

    Updating a branch by merge produced an unsigned commit even when merges
    are configured to be signed. Update by rebase was unaffected.

    `Update()` builds a fake reverse PR to switch head and base, and it has
    no `Index`, so `pr.GetGitHeadRefName()` resolves `refs/pull/0/head`.
    Since #36186 `SignMerge` looks that ref up in the base repository
    instead of the temporary merge repo. That lookup fails. The caller
    dropped the error, so `sign` stayed false.

    Sync fork goes through the same fake-PR path.

    Pass both sides of the merge to `SignMerge` as refs and evaluate them in
    the temp repo, where `base` and `tracking` always exist.

    Tests cover a signed and an unsigned update by merge.

    Fixes #38066

commit 9d3f04eb7e
Author: bircni <bircni@icloud.com>
Date:   Thu Jul 16 23:10:43 2026 +0200

    fix(actions): explain why a blocked or waiting job has not started (#38476)

    When an Actions job is blocked or waiting, the job view only shows the
    generic **Blocked** / **Waiting** label. Users have no way to tell *why*
    a job is stuck — whether it's waiting on dependencies, waiting for a
    runner that doesn't exist, waiting for a runner whose labels don't
    match, or simply queued behind busy runners.

    The current-job detail line now surfaces the actual cause:

    - **Blocked** → lists the dependency jobs (`needs`) that haven't
    finished yet, e.g. *"Waiting for the following jobs to complete:
    build."*
    - **Waiting**, no online runner → *"No runner is online to pick up this
    job."*
    - **Waiting**, online runners but none match `runs-on` → *"No matching
    online runner with label: X"* (reuses the existing string)
    - **Waiting**, a matching runner exists but hasn't claimed the job →
    *"Waiting for a matching runner to become available."*

    The runner lookup reuses the same available-online-runner query the run
    list already performs, and only runs while a selected job is actually
    pending. Dependency resolution is scoped to the same parent job and
    treats matrix expansions of a `need` as pending until all of them
    complete.

commit 2e0aa7ec74
Author: Zettat123 <zettat123@gmail.com>
Date:   Thu Jul 16 14:28:53 2026 -0600

    fix(actions): make `cancelled()` work in job `if` evaluation (#38495)

    Fix #38485
    always provides a nil `JobContext` for the evaluator, which makes
    [`cancelled()`](https://gitea.com/gitea/runner/src/commit/ad967330a8788c9b8ab723abbc1a86d53c3bc5e6/act/exprparser/functions.go#L299)
    panic on `Job.Status` because `Job` is a nil pointer.

commit f0d9af3a18
Author: silverwind <me@silverwind.io>
Date:   Thu Jul 16 19:38:33 2026 +0200

    enhance(ui): use OpenAPI 3.0 spec in API viewer, add spec buttons (#38478)

    Follow-ups from https://github.com/go-gitea/gitea/pull/37038:

    - Render the OpenAPI 3.0 spec in the API viewer, it is richer than the
    Swagger 2.0 rendering
    - Replace the back link with gitea-styled buttons to view both specs and
    return to Gitea, flowing above swagger-ui on viewports where they would
    overlap the title
    - Key `VisibilityModes` by the string enum type, now named
    `VisibilityString`, removing the `string()` casts at API call sites
    - Drop the raw visibility strings from the `Service` settings struct in
    favor of the typed mode fields, which also removes the org default
    visibility row from the admin config page
    - Fix two pre-existing issues surfaced in review: an invalid
    `DEFAULT_USER_VISIBILITY` was silently accepted as public, and the org
    visibility error message showed the enum zero value instead of the
    submitted input

    Co-authored-by: wxiaoguang <wxiaoguang@gmail.com>

commit 02f82a2054
Author: bircni <bircni@icloud.com>
Date:   Thu Jul 16 15:58:31 2026 +0200

    fix(actions): show retention info on hover for expired artifacts (#38477)

    The artifact info hover tooltip (#37100) only worked for live artifacts.
    Hovering an expired/deleted artifact showed nothing, and even on live
    artifacts the retention date was missing on real runs.

    Two root causes:

    1. **Expired artifacts had no tooltip.** In the run view sidebar,
    expired artifacts render in a separate branch that omitted
    `data-tooltip-content` entirely, so there was nothing to hover.
    2. **`ExpiresUnix` was no longer sent.** The `ActionRunAttempt` refactor
    (#37119) dropped `ExpiresUnix` from `fillViewRunResponseArtifacts`, so
    real runs always returned `0` and the tooltip fell back to size-only.
    Only the devtest mock still populated it, which masked the regression.

    Artifacts without a recorded expiry (`expiresUnix <= 0`) still degrade
    gracefully to a size-only tooltip. Both states can be previewed on the
    `/devtest/mock/*` actions run page.

    Co-authored-by: wxiaoguang <wxiaoguang@gmail.com>

commit 1850a108e5
Author: bircni <bircni@icloud.com>
Date:   Thu Jul 16 14:58:05 2026 +0200

    fix(actions): group reusable-workflow matrix legs in the workflow graph (#38475)

    Fixes the UI issue reported in #38466: matrix jobs that invoke a
    reusable workflow (`build-call (linux)`, `build-call (windows)`, …) were
    rendered as separate nodes in the run's workflow graph, while an
    equivalent regular matrix
    (`build (linux)`, `build (windows)`, …) collapsed neatly into a single
    matrix node.

    Before: three loose `build-call (...)` boxes next to one grouped `build` box.
    After: both matrices collapse into a single node.

commit 875b2e8def
Author: wxiaoguang <wxiaoguang@gmail.com>
Date:   Thu Jul 16 19:36:46 2026 +0800

    fix: full file highlighting for git diff with CR char (#38484)

    fix #38481

commit f15868d442
Author: Gaurav Dubey <gauravdubey0107@gmail.com>
Date:   Thu Jul 16 15:21:36 2026 +0530

    fix(packages): serve noarch Alpine index for any requested architecture (#38479)

    Fixes #38456
    The Alpine package registry serves one `APKINDEX.tar.gz` per
    architecture. When a repository contains only `noarch` packages (no
    architecture-specific packages), only the `noarch` index is built.
    Because `apk` substitutes `$ARCH` with the host architecture and
    requests e.g. `x86_64/APKINDEX.tar.gz`, such a repository returned HTTP
    404 and was unusable, matching the report in #38456.
    `GetRepositoryFile` now falls back to the `noarch` index when the
    requested architecture has no index of its own, mirroring the fallback
    already present in the sibling `DownloadPackageFile` handler. `noarch`
    packages are installable on every architecture, so serving them for any
    requested architecture is correct. The index-build side is unchanged;
    only the serving path gains the fallback, so mixed repositories (which
    already merge `noarch` into each per-architecture index) are unaffected.
    This change was implemented with the help of an AI coding assistant,
    which gitea's CONTRIBUTING.md explicitly welcomes when disclosed. I have
    reviewed the change, understand it, and can explain and defend it.
    Added a `NoArchOnly` subtest to `TestPackageAlpine` that publishes only
    a `noarch` package to a fresh repository and asserts that `GET
    .../x86_64/APKINDEX.tar.gz` now returns `200` (previously `404`) and
    that the served index lists the noarch package. Verified locally with
    `go build`/`go vet` on the changed package and a compile of the
    integration test package (`go test -c`); the full integration run relies
    on CI.

    ---------

    Signed-off-by: wxiaoguang <wxiaoguang@gmail.com>
    Co-authored-by: wxiaoguang <wxiaoguang@gmail.com>

commit a77bf48b41
Author: Zettat123 <zettat123@gmail.com>
Date:   Thu Jul 16 01:53:43 2026 -0600

    fix: 500 error when updating user visibility (#38480)

    1. Create a user with `visibility=public`
    2. Update `ALLOWED_USER_VISIBILITY_MODES` setting to `limited, private`
    3. Modify any field other than "User visibility" (e.g. "Full Name")
    4. UI shows 500 error

    Only update the visibility field when it actually changes.

commit 11363e2f0c
Author: silverwind <me@silverwind.io>
Date:   Wed Jul 15 22:10:43 2026 +0200

    chore(renovate): bundle major updates, use chore commit type (#38470)

    1. combine PRs for major/non-major, less PRs is less work with the
    fixups.
    2. always set `chore`, more often than not, this is more correct then
    `fix`.

    ---------

    Signed-off-by: silverwind <me@silverwind.io>

commit 82edc3da01
Author: wxiaoguang <wxiaoguang@gmail.com>
Date:   Thu Jul 16 01:30:01 2026 +0800

    refactor: decouple git.Repository(ctx) from git.Commit & git.Tree (#38464)

    1. Storing "ctx" in a long-living object is wrong
    2. Make the commit & tree cacheable (for the future performance
    optimization)
    3. Also fix some bad designs like `// FIXME: bad design, this field can
    be nil if the commit is from "last commit cache"`

    ref:
    * #33893

commit ed678b9d45
Author: Shudhanshu Singh <sudhanshuwriterblc@gmail.com>
Date:   Wed Jul 15 22:36:34 2026 +0530

    fix(actions): make job list item fully clickable (#38462)

    Clicking the empty space to the right of a job in the Actions sidebar
    didn't switch jobs: the interactive `<a>`/`<button>` used `display:
    contents` and so generated no clickable box.

    Fixes: https://github.com/go-gitea/gitea/issues/38460

    Drop the wrapper `div` and `display: contents`, moving the `.item` and
    layout styles directly onto the `<a>`/`<button>` so the whole row is
    clickable. Reusable-caller `<button>` rows also get `width: 100%` and
    `line-height: inherit` to match the `<a>` rows.

    ---------

    Co-authored-by: silverwind <me@silverwind.io>

commit ce683b34c6
Author: wxiaoguang <wxiaoguang@gmail.com>
Date:   Thu Jul 16 00:57:44 2026 +0800

    fix: mail template for push event (#38467)

    fix #38465

commit fa50ad2aa9
Author: Giteabot <teabot@gitea.io>
Date:   Wed Jul 15 06:32:27 2026 -0700

    chore(deps): update dependency djlint to v1.40.4 (#38428)

commit c86eb7081b
Author: Giteabot <teabot@gitea.io>
Date:   Wed Jul 15 00:14:50 2026 -0700

    fix(deps): update npm dependencies (#38431)

commit 506075c480
Author: Giteabot <teabot@gitea.io>
Date:   Tue Jul 14 23:47:08 2026 -0700

    fix(deps): update go dependencies (#38429)

commit 9fa2bff5fd
Author: Jeremy Stover <jeremy.ryan.stover@gmail.com>
Date:   Tue Jul 14 23:25:50 2026 -0400

    fix(admin): exit dev test queue producer loop when context is cancelled (#38451)

    Co-authored-by: Kadajett <jeremy@semfora.ai>

commit 880ddb5724
Author: xkm <fzc_study@163.com>
Date:   Wed Jul 15 10:36:03 2026 +0800

    fix(actions): prevent bulk actions from affecting all runners (#38453)

    Fix the bug in the site-admin runner bulk actions introduced by #37869:
    the runner IDs are empty then all runners will be deleted.

    Fixes #38449

    ---------

    Co-authored-by: wxiaoguang <wxiaoguang@gmail.com>

commit 7c629e1ba7
Author: GiteaBot <teabot@gitea.io>
Date:   Wed Jul 15 00:45:33 2026 +0000

    [skip ci] Updated translations via Crowdin

commit b6904c9730
Author: Harsh Satyajit Thakur <f20240223@goa.bits-pilani.ac.in>
Date:   Wed Jul 15 04:24:18 2026 +1000

    fix: make "test push webhook" always work (#38425)

    * fix #38309
    * fix #26238
    * fix #37886

    ---------

    Co-authored-by: wxiaoguang <wxiaoguang@gmail.com>

commit 9c08df8bc8
Author: Shudhanshu Singh <sudhanshuwriterblc@gmail.com>
Date:   Tue Jul 14 23:24:55 2026 +0530

    fix(org): align follow button and wrap description (#38448)
    Fixes the organization page header layout issue where:
    1. Long organization descriptions did not wrap and instead stretched the
    header container out of bounds.
    2. The "Follow" button floated dynamically adjacent to the description's
    right edge depending on the description length, instead of remaining at
    a fixed position aligned with the right edge of the page container.

    Fixes https://github.com/go-gitea/gitea/issues/38445
    The flex container `<div class="flex-relaxed-list">` lacked `tw-flex-1`
    (to grow to fill the container) and `tw-min-w-0` (to allow it to shrink
    below its content's size). Consequently, the flex minimum width
    defaulted to `min-content`, stretching the container for long unwrapped
    descriptions.
    Added `tw-flex-1 tw-min-w-0` to the `<div class="flex-relaxed-list">`
    container in `templates/org/header.tmpl`. This restricts the width,
    enables proper text wrapping, and fixes the "Follow" button to the right
    edge of the content container.
    Before
    <img width="1300" height="615" alt="image"
    src="https://github.com/user-attachments/assets/11e6ab99-b847-45ff-8bdb-8622bfeee8aa"
    />
    After
    <img width="1300" height="615" alt="image"
    src="https://github.com/user-attachments/assets/84ac0633-b192-4be5-8226-13bfad3ab2ec"
    />

    ---------

    Co-authored-by: wxiaoguang <wxiaoguang@gmail.com>

commit 0e4d93537a
Author: silverwind <me@silverwind.io>
Date:   Tue Jul 14 18:30:16 2026 +0200

    fix(actions): populate `github.event` for scheduled runs (#38446)

    Scheduled runs stored a `null` event payload, so
    `github.event.repository`/`sender`/`organization` were empty in
    scheduled workflows. Every other event carries them, and so does GitHub
    Actions. `CreateScheduleTask` now synthesizes them.

commit da5a004fc4
Author: Giteabot <teabot@gitea.io>
Date:   Tue Jul 14 04:04:08 2026 -0700

    chore(deps): update npm dependencies (major) (#38432)

commit ed9b02985a
Author: Giteabot <teabot@gitea.io>
Date:   Tue Jul 14 01:48:58 2026 -0700

    fix(deps): update module github.com/google/go-github/v88 to v89 (#38433)

commit f12a0a9183
Author: Giteabot <teabot@gitea.io>
Date:   Tue Jul 14 01:24:40 2026 -0700

    chore(deps): update action dependencies (#38430)

commit d15cfa363a
Author: wxiaoguang <wxiaoguang@gmail.com>
Date:   Mon Jul 13 14:38:41 2026 +0800

    chore: don't auto refresh the merge box when user has interacted with it (#38435)

    Otherwise, the user just isn't able to use "auto merge" form

commit f69e15afe7
Author: bircni <bircni@icloud.com>
Date:   Sun Jul 12 19:14:09 2026 +0200

    fix: various security fixes (#38406)

    Addresses a batch of privately reported security issues, grouped by
    area:

    - **SSRF** - migration PR-patch/asset fetches, OAuth2 avatar & OpenID
    discovery, pull-mirror URL re-validation, and the outbound proxy path.
    - **Access-token scope** - prevent scope escalation on token creation;
    keep public-only tokens confined (feeds, packages, Actions listings,
    star/watch lists, limited/private owners).
    - **Access control / disclosure** - go-get default-branch leak, webhook
    authorization-header leak, watch clearing on private transitions,
    label/attachment scoping.
    - **Denial of service** - input bounds for npm dist-tags, Debian control
    files, Arch file lists, and SSH keys.

    Not breaking - existing configs keep working - but two changes are worth
    a look:

    - **New SSRF protection** Outbound requests (migrations, OAuth2 avatars,
    OpenID discovery, pull mirrors, proxy path) are now validated against
    the allow/block host lists. If your instance legitimately reaches
    internal hosts, you may need to add them to
    `[security].ALLOWED_HOST_LIST` (and the relevant `ALLOW_LOCALNETWORKS`
    settings).
    - **Deprecation** `[webhook].ALLOWED_HOST_LIST` is deprecated and will
    be removed in a future release. Use `[security].ALLOWED_HOST_LIST`
    instead; the old key still works for now.

    ---------

    Co-authored-by: TheFox0x7 <thefox0x7@gmail.com>
    Co-authored-by: techknowlogick <techknowlogick@gitea.io>
    Co-authored-by: Lunny Xiao <xiaolunwen@gmail.com>
    Co-authored-by: wxiaoguang <wxiaoguang@gmail.com>
    Co-authored-by: Zettat123 <zettat123@gmail.com>

commit d2bd1589fe
Author: TowyTowy <85077986+TowyTowy@users.noreply.github.com>
Date:   Sun Jul 12 15:38:34 2026 +0200

    fix(util): reject invalid characters between time-estimate units (#38416)

    `TimeEstimateParse` (used by the issue time-estimate form) only checked
    that the first token starts at the beginning of the string and the last
    token ends at its end, but never checked the gaps between consecutive
    tokens. Non-whitespace garbage embedded between two valid units was
    silently dropped and the string accepted with a wrong value instead of
    being reported as invalid.

    Examples that were wrongly accepted before this change:

    - `1h 2x 3m` → 3780s (parsed as 1h3m)
    - `1h_2m`    → 3720s
    - `1h,1m`    → 3660s

    All three now return an "invalid time string" error, while valid inputs
    such as `1h 1m 1s` and `1h1m1s` keep working.

    Reject any non-whitespace content between two matched units.

    ---------

    Signed-off-by: TowyTowy <towy@airreps.link>
    Signed-off-by: wxiaoguang <wxiaoguang@gmail.com>
    Co-authored-by: wxiaoguang <wxiaoguang@gmail.com>

commit b998c3c1aa
Author: Shudhanshu Singh <sudhanshuwriterblc@gmail.com>
Date:   Sun Jul 12 17:44:37 2026 +0530

    feat(actions): implement adaptive auto-refresh for workflow runs list (#38329)
    This PR implements an optimized, adaptive client-side auto-refresh
    mechanism for the Gitea Actions workflow runs list page. It allows users
    to see workflow progress updates dynamically without having to reload
    the page.

    Fixes https://github.com/go-gitea/gitea/issues/37457
    ---------

    Signed-off-by: wxiaoguang <wxiaoguang@gmail.com>
    Co-authored-by: wxiaoguang <wxiaoguang@gmail.com>

commit 65c5a5ff7b
Author: Lovepreet Singh <lovepreet.singh61182@gmail.com>
Date:   Sun Jul 12 17:03:14 2026 +0530

    fix(turnstile): route CAPTCHA verification through the configured proxy (#38412)

    Fixes #38217

    Turnstile CAPTCHA verification uses `http.DefaultClient`, so the request
    to `challenges.cloudflare.com` bypasses Gitea's configured HTTP proxy —
    unlike other outbound HTTP clients such as the update checker
    (`modules/updatechecker/update_checker.go`) and migrations. In
    deployments where egress is only permitted through the configured proxy,
    verification fails.

    Build the client with `proxy.Proxy()` as the transport proxy, mirroring
    the update checker:

    ```go
    func httpClient() *http.Client {
    	return &http.Client{
    		Transport: &http.Transport{
    			Proxy: proxy.Proxy(),
    		},
    	}
    }
    ```

    The client is built per call (rather than a package-level var) because
    `proxy.Proxy()` reads `setting.Proxy` when invoked; building it at
    request time ensures it reflects the loaded settings. When no proxy is
    configured, behavior is unchanged (`proxy.Proxy()` returns a no-op /
    `http.ProxyFromEnvironment`).

    ---------

    Co-authored-by: wxiaoguang <wxiaoguang@gmail.com>

commit aba0eb1749
Author: Harsh Satyajit Thakur <f20240223@goa.bits-pilani.ac.in>
Date:   Sun Jul 12 20:54:59 2026 +1000

    fix: represent a deleted assignee team as a Ghost team (#38413)

    Fixes #35472.

    `Comment.LoadAssigneeUserAndTeam` already has a Ghost user fallback
    for a deleted assignee user, but the parallel branch for a deleted
    assignee team just swallowed the not-found error and left
    `AssigneeTeam` as `nil`. This is inconsistent (the reporter's example
    shows `assignee` becoming a Ghost user while `assignee_team` becomes
    `null`), and it's also a latent nil pointer bug: other code that
    assumes `AssigneeTeam` is set once this function returns without
    error will panic.

    Added `organization.NewGhostTeam()` / `Team.IsGhost()`, mirroring the
    existing `user_model.NewGhostUser()` / `User.IsGhost()` pattern, and
    used it in the same fallback branch.

    Co-authored-by: wxiaoguang <wxiaoguang@gmail.com>

commit 678b5aba30
Author: GiteaBot <teabot@gitea.io>
Date:   Sun Jul 12 00:54:22 2026 +0000

    [skip ci] Updated translations via Crowdin

commit bd5f881c51
Author: wxiaoguang <wxiaoguang@gmail.com>
Date:   Sun Jul 12 01:36:10 2026 +0800

    fix: refresh pull request merge box when the commit status is pending (#38410)

commit d3d57dd9b4
Author: Yarden Shoham <git@yardenshoham.com>
Date:   Sat Jul 11 16:29:41 2026 +0300

    chore: remove Yarden Shoham from maintainers (#38407)

commit 1bbd127a1a
Author: wxiaoguang <wxiaoguang@gmail.com>
Date:   Sat Jul 11 21:03:42 2026 +0800

    fix: actions task state concurrent update (#38405)

    fix #38333

commit f803f8e269
Author: bircni <bircni@icloud.com>
Date:   Fri Jul 10 23:43:32 2026 +0200

    fix(actions): keep workflow run trailing on one row with long branch names (#38382)

    The flex-list refactor (#37505) raised the shared `.item-trailing`
    selector's specificity, so its `flex-wrap: wrap` started overriding the
    run list's intended `flex-wrap: nowrap` — a long branch name pushed the
    trailing content past its fixed 280px width and wrapped the kebab menu
    onto its own line.

    ---------

    Co-authored-by: wxiaoguang <wxiaoguang@gmail.com>

commit 8401fe7c54
Author: bircni <bircni@icloud.com>
Date:   Fri Jul 10 21:18:47 2026 +0200

    fix(pull): re-evaluate review official flag on target branch change (#38319)

    The `official` flag of a pull request review is computed against the
    target branch's protection rules at submit time and stored on the review
    record. `ChangeTargetBranch` updated the base branch but never
    re-evaluated it, so an `official` approval obtained against an
    unprotected branch could be retargeted onto a protected branch and
    satisfy its required approvals, bypassing the branch protection.

    This re-evaluates the `official` flag of the latest approve/reject
    reviews against the new base branch whenever the target branch changes.

commit c12e92c21d
Author: Shudhanshu Singh <sudhanshuwriterblc@gmail.com>
Date:   Sat Jul 11 00:08:09 2026 +0530

    fix(web): use locale-aware date formatting for contribution calendar tooltips (#38398)

    The contribution calendar manually constructed localized date strings
    instead of using the browser's locale-aware date formatting. Replace
    this with `toLocaleDateString()` to correctly format dates for all
    locales and calendar systems, including non-Gregorian calendars.

    Fixes https://github.com/go-gitea/gitea/issues/38375

commit aab3242f7b
Author: bircni <bircni@icloud.com>
Date:   Fri Jul 10 19:30:43 2026 +0200

    fix(security): harden access checks and migration validation (#38324)

    Harden access checks for issue dependencies, team repository membership,
    notifications, stars, tracked times and repository migrations.

commit f452c369ac
Author: bircni <bircni@icloud.com>
Date:   Fri Jul 10 18:39:01 2026 +0200

    fix: enforce public-only token scope and harden push options / locale parsing (#38323)

    - **Locale DoS:** the `Locale` middleware passed the raw
    `Accept-Language` header to `ParseAcceptLanguage`, whose guard only
    counts `-` while the scanner aliases `_` to `-` — a large `_`-separated
    header on an unauthenticated request burned CPU. The header is now
    length-bounded before parsing.
    - **Public-only token scope:** `GET /teams/{id}/repos`,
    `.../repos/{org}/{repo}`, `/teams/{id}/activities/feeds`, and
    `/users/{username}/orgs/{org}/permissions` still returned private
    repo/activity/permission data to a public-only token. They now filter
    via `TokenCanAccessRepo` / `ApplyPublicOnly` and reject non-public org
    permissions.
    - **Push-option visibility:** `repo.private` / `repo.template` push
    options were applied to any existing repo, letting an owner/admin
    silently flip visibility bypassing audit, webhooks, and notifications.
    They are now honored only on push-to-create.

commit c5c991b1a4
Author: wxiaoguang <wxiaoguang@gmail.com>
Date:   Fri Jul 10 18:52:00 2026 +0800

    fix: co-author detection (#38392)

    Committer can also be co-author, it should only not be included in the
    co-author list if it is not in the "Co-author-by" list.

    * Author & Co-author: they changed the code (attribution)
    * Committer: they submitted the commit but didn't change the code (e.g.:
    maintainer signed a commit)

    Fix #38384

commit 362539b78e
Author: bircni <bircni@icloud.com>
Date:   Fri Jul 10 00:21:44 2026 +0200

    fix(api): stop leaking private repo metadata after access revocation (#38321)

    The `/user/starred` and `/user/subscriptions` endpoints returned private
    repositories a user had starred/watched even after their access to those
    repositories was revoked, still exposing the repository name,
    description and visibility (including later metadata changes).

    Private repositories in the starred/watched queries are now gated on the
    actor's current access via `AccessibleRepositoryCondition`, so users who
    no longer have access no longer receive the metadata. Public
    repositories and public-only tokens are unaffected.

commit 66a3723cbb
Author: bircni <bircni@icloud.com>
Date:   Thu Jul 9 23:43:08 2026 +0200

    fix(lfs): require proof of possession for cross-repo objects (#38322)

    The LFS batch and upload handlers linked an object that already existed
    in the content store but was not linked to the current repo whenever the
    token's user could access it in another repo. Deploy-key tokens carry
    the repo owner's identity, so a single-repo write deploy key could link
    and then download objects from any repo the owner can see.

    This drops the cross-repo access check: the batch handler now makes the
    client upload (hash-verified) any object not yet linked to the repo, and
    the upload handler skips proof of possession only when the object is
    already linked to the current repo.

commit 27e33b7ba1
Author: bircni <bircni@icloud.com>
Date:   Thu Jul 9 22:31:14 2026 +0200

    fix: incorrect co-author detection on commit page (#38386)

    The commit page built its "co-authored by" list from
    `AllParticipantIdentities()[1:]`, which only drops the author and leaves
    the committer in the list even though the committer is already shown
    separately as "committed by". This caused the committer to be wrongly
    rendered as a co-author (issue #38384): a commit authored by
    `silverwind`, committed by `bircni`, with a `Co-authored-by: silverwind`
    trailer displayed "co-authored by bircni" instead of the actual trailer
    identity. This adds a `Commit.CoAuthorIdentities()` method that excludes
    both the author and the committer, uses it on the commit page, and
    covers the fix with a regression test.

    Closes #38384

commit 761470c01d
Author: Zettat123 <zettat123@gmail.com>
Date:   Thu Jul 9 09:34:56 2026 -0600

    enhance(actions): only create filtered-out workflow commit status for required contexts (#38371)

    Follow #38237
    triggered due to a filter (e.g. `paths` or `branches`) mismatch.
    However, for non-required workflows, creating "skipped" commit statuses
    for them would generate a lot of noise.

    To address this issue, this PR adds a check before creating commit
    status:

    - For the context that matches any required status check patterns, a
    "skipped" commit status will be created. The `Required` label can inform
    users that this status check is required, but has been skipped because
    of a filter mismatch.
    - For a non-required context, nothing will be created.

    NOTE: Reducing noise is a best-effort approach and isn't entirely
    accurate. When creating commit statuses, it is impossible to predict
    which branch protection rule will take effect. Therefore, we have to
    compare the commit status context against the required patterns from all
    rules. If any rule matches, the context is considered "required".

commit c0bbd82cd4
Author: silverwind <me@silverwind.io>
Date:   Thu Jul 9 16:26:59 2026 +0200

    fix(ui): restore commits table column widths (#38379)

    https://github.com/go-gitea/gitea/pull/37594 widened the author column
    from `three wide` to `four wide`, leaving a large empty gap around the
    SHA column in the common single-author case. The old author cell was
    capped at 180px, so the wider column only adds whitespace: avatar-stack
    names ellipsize at 240px each, and wider multi-author rows still expand
    naturally in the auto-layout table. Restore the pre-existing
    `three`/`eight` widths.

    Co-authored-by: bircni <bircni@icloud.com>

commit 7fd34ff033
Author: silverwind <me@silverwind.io>
Date:   Thu Jul 9 15:25:01 2026 +0200

    test(e2e): fix race in pdf file render test (#38380)

    `data-render-name` is set before the plugin's async render runs, so
    measuring the container height right after the attribute appears can
    observe the pre-render 48px height when the `pdfobject` chunk loads
    slowly (flaked in CI). Poll for the height instead, like the asciicast
    test in the same file does.

commit 1e682a26eb
Author: wxiaoguang <wxiaoguang@gmail.com>
Date:   Thu Jul 9 20:39:03 2026 +0800

    refactor: introduce ActivePageTimer to help to do partial page refresh (#38372)

    Before, the logic is already there for "pull merge box".

    After, the logic is extracted into a general class ActivePageTimer and
    will help more pages (including #38329)

commit 3b3a06e06f
Author: GiteaBot <teabot@gitea.io>
Date:   Thu Jul 9 00:56:40 2026 +0000

    [skip ci] Updated translations via Crowdin

commit 545ed92354
Author: Milwad Khosravi <98118400+milwad-dev@users.noreply.github.com>
Date:   Thu Jul 9 01:22:06 2026 +0330

    chore(typo): fix grammar in comments, API docs and error messages (#38370)

commit 49ef93940a
Author: wxiaoguang <wxiaoguang@gmail.com>
Date:   Wed Jul 8 08:16:32 2026 +0800

    fix: golang html template url escaping (#38363)

    fix #38362

commit 308a6f12ae
Author: bircni <bircni@icloud.com>
Date:   Tue Jul 7 21:16:20 2026 +0200

    perf(actions): debounce runner heartbeat writes and throttle task picks (#38281)

    3 reductions in the DB load generated by many runners polling
    `FetchTask`:

    **1. Debounce runner heartbeat writes**
    Every poll wrote `last_online`, and every `UpdateTask`/`UpdateLog` wrote
    `last_active` — while a runner streams logs that is many writes per
    second per runner. These are now persisted only when stale enough to
    actually affect the active/offline status (`ShouldPersistLastOnline` /
    `ShouldPersistLastActive`), using the existing columns.

    **2. Throttle concurrent task picks**
    A new in-process semaphore (`MAX_CONCURRENT_TASK_PICKS`) bounds how many
    runners run the task-assignment transaction at once, so a fleet polling
    together cannot stampede the query. Throttled polls retry on their next
    poll without advancing the runner's tasks version.

    **3. Paginate the task-pick query**
    `CreateTaskForRunner` previously loaded every waiting job in the
    runner's scope into memory on each poll (no `LIMIT`). Now it pages
    through the waiting backlog oldest-first with `LIMIT`, claiming the
    first label-matching job.

    ---------

    Co-authored-by: Zettat123 <zettat123@gmail.com>

commit 97078b96cf
Author: bircni <bircni@icloud.com>
Date:   Tue Jul 7 19:35:21 2026 +0200

    fix(mirror): disable HTTP redirects on pull mirror sync (#38320)

    Pull mirror sync ran `git fetch` / `remote update` / `remote prune`
    without disabling HTTP redirects. A mirror remote that later starts
    redirecting to an otherwise-blocked or internal address could be used as
    an SSRF/exfiltration vector on scheduled syncs, bypassing the
    allow/block validation applied at migration time.

    This sets `http.followRedirects=false` on all three remote-contacting
    commands in the pull mirror path, matching the existing guard already
    present on the clone path.

commit 6507f1fd94
Author: Giteabot <teabot@gitea.io>
Date:   Tue Jul 7 09:31:17 2026 -0700

    chore(deps): update dependency djlint to v1.40.1 (#38354)

commit 0964899799
Author: Giteabot <teabot@gitea.io>
Date:   Tue Jul 7 09:17:10 2026 -0700

    fix(deps): update npm dependencies (#38352)

commit 550efdcdfd
Author: Giteabot <teabot@gitea.io>
Date:   Tue Jul 7 05:41:01 2026 -0700

    chore(deps): update action dependencies (#38353)

commit b96bd22372
Author: Giteabot <teabot@gitea.io>
Date:   Tue Jul 7 03:16:00 2026 -0700

    fix(deps): update go dependencies (#38346)

commit a74f618ade
Author: wxiaoguang <wxiaoguang@gmail.com>
Date:   Tue Jul 7 15:32:25 2026 +0800

    fix: minio init check (#38355)

    Fix the buggy behavior introduced by "S3: log human readable error on connection failure (#26856)"

commit 2b89e2ac97
Author: Copilot <198982749+Copilot@users.noreply.github.com>
Date:   Tue Jul 7 07:08:05 2026 +0000

    fix(pulls): add `branch-name` option for `DEFAULT_TITLE_SOURCE` (#38356)

    Adds a new `branch-name` value for the `[repository.pull-request]`
    `DEFAULT_TITLE_SOURCE` setting that always uses the normalized branch
    name as the PR title, regardless of commit count.

    Fix #38317

    ---------

    Co-authored-by: wxiaoguang <wxiaoguang@gmail.com>

commit 26bff7f47e
Author: wxiaoguang <wxiaoguang@gmail.com>
Date:   Tue Jul 7 14:40:12 2026 +0800

    fix: org project view assignee list (#38357)

    fix #38129

commit 582217a0da
Author: Shudhanshu Singh <sudhanshuwriterblc@gmail.com>
Date:   Tue Jul 7 00:00:58 2026 +0530

    feat(webhook): add reviewer name to MS Teams review request notifications (#38289)

    Include the requested reviewer's username (along with their full name in
    parentheses, if available) and render the `Repository` and `Pull
    request` fields as clickable links in Microsoft Teams webhook
    notifications.

    Fixes: https://github.com/go-gitea/gitea/issues/38270

    <img width="1246" height="651" alt="image"
    src="https://github.com/user-attachments/assets/7299ce10-c6d4-4c89-a05a-a258d72c00e5"
    />

    ---------

    Signed-off-by: Shudhanshu Singh <sudhanshuwriterblc@gmail.com>
    Co-authored-by: wxiaoguang <wxiaoguang@gmail.com>

commit a46e331637
Author: Giteabot <teabot@gitea.io>
Date:   Mon Jul 6 11:04:10 2026 -0700

    chore(deps): update action dependencies (#38340)

commit 580cc26d63
Author: Lunny Xiao <xiaolunwen@gmail.com>
Date:   Mon Jul 6 10:07:58 2026 -0700

    chore: Upgrade xorm to 1.4.1 (#38224)

    Fix #22275

    Changelog: https://gitea.com/xorm/xorm/compare/v1.3.11..v1.4.1

commit e3d83bcf9c
Author: Giteabot <teabot@gitea.io>
Date:   Mon Jul 6 09:40:40 2026 -0700

    chore(deps): update tool dependencies (#38344)

    This PR contains the following updates:

    | Package | Change |
    [Age](https://docs.renovatebot.com/merge-confidence/) |
    [Confidence](https://docs.renovatebot.com/merge-confidence/) |
    |---|---|---|---|
    |
    [github.com/editorconfig-checker/editorconfig-checker/v3](https://redirect.github.com/editorconfig-checker/editorconfig-checker)
    | `v3.7.0` → `v3.8.0` |
    ![age](https://developer.mend.io/api/mc/badges/age/go/github.com%2feditorconfig-checker%2feditorconfig-checker%2fv3/v3.8.0?slim=true)
    |
    ![confidence](https://developer.mend.io/api/mc/badges/confidence/go/github.com%2feditorconfig-checker%2feditorconfig-checker%2fv3/v3.7.0/v3.8.0?slim=true)
    |
    | golang.org/x/vuln | `v1.4.0` → `v1.5.0` |
    ![age](https://developer.mend.io/api/mc/badges/age/go/golang.org%2fx%2fvuln/v1.5.0?slim=true)
    |
    ![confidence](https://developer.mend.io/api/mc/badges/confidence/go/golang.org%2fx%2fvuln/v1.4.0/v1.5.0?slim=true)
    |

commit 44f927eacf
Author: Giteabot <teabot@gitea.io>
Date:   Mon Jul 6 07:13:28 2026 -0700

    fix(deps): update npm dependencies (#38342)

commit 35413d5b65
Author: Giteabot <teabot@gitea.io>
Date:   Mon Jul 6 06:56:31 2026 -0700

    chore(deps): update dependency djlint to v1.40.0 (#38341)

commit e797a27d4e
Author: Zettat123 <zettat123@gmail.com>
Date:   Sun Jul 5 22:38:44 2026 -0600

    fix(actions): release claimed task if context is cancelled during `FetchTask` (#38343)

    When a runner's `FetchTask` request context is cancelled after the job
    is claimed but before the task reaches the runner (e.g. request
    timeout), the job was left referencing a running task no runner ever
    executes, so it stayed unpickable.

    Fix: Check the context after assembling the task and release the task so
    the job returns to waiting status for another runner.

commit 4b15260277
Author: GiteaBot <teabot@gitea.io>
Date:   Mon Jul 6 01:02:23 2026 +0000

    [skip ci] Updated translations via Crowdin

commit 18fdc77130
Author: GiteaBot <teabot@gitea.io>
Date:   Sun Jul 5 01:02:27 2026 +0000

    [skip ci] Updated translations via Crowdin

commit 2c2691b969
Author: Zettat123 <zettat123@gmail.com>
Date:   Sat Jul 4 14:30:12 2026 -0600

    test: compare key file contents instead of `FileInfo` in `TestInitKeys` (#38330)

    `TestInitKeys` verified whether a host key file was regenerated by
    comparing `os.FileInfo` before and after a `InitDefaultHostKeys` call.
    On systems where the OS clock / filesystem timestamp granularity is
    coarse, both writes land in the same tick and get an identical mtime.
    The resulting `FileInfo` is then byte-for-byte equal even though the key
    was actually regenerated, so `assert.NotEqual` fails.

    Since a regenerated key always produces different random bytes,
    comparing the content can reliably detect regeneration.

commit 08d4abbb46
Author: wxiaoguang <wxiaoguang@gmail.com>
Date:   Sun Jul 5 03:00:22 2026 +0800

    docs: describe duties of mergers prior to merging a PR (#38308)

    Signed-off-by: wxiaoguang <wxiaoguang@gmail.com>
    Signed-off-by: delvh <dev.lh@web.de>
    Co-authored-by: delvh <dev.lh@web.de>

commit e4ef995f2a
Author: Lunny Xiao <xiaolunwen@gmail.com>
Date:   Sat Jul 4 06:02:17 2026 -0700

    fix(release): validate web attachment renames against allowed types (#38314)

    This fixes the web release edit flow so renamed release attachments are
    validated against `[repository.release] ALLOWED_TYPES`.

    Previously, the API attachment edit endpoint already enforced release
    attachment type restrictions, but the web release edit form passed
    `attachment-edit-*` values into `release_service.UpdateRelease`, which
    updated attachment names directly without validating the new filename
    against `setting.Repository.Release.AllowedTypes`.

    As a result, a user with repository write access could rename an
    existing release attachment to a disallowed extension through the web
    UI.

    ---------

    Co-authored-by: wxiaoguang <wxiaoguang@gmail.com>

commit 7fdfb8d642
Author: GiteaBot <teabot@gitea.io>
Date:   Sat Jul 4 00:56:26 2026 +0000

    [skip ci] Updated translations via Crowdin

commit d4c4142123
Author: bircni <bircni@icloud.com>
Date:   Fri Jul 3 22:35:47 2026 +0200

    fix(actions): make runner list pagination order deterministic (#38313)

    The runner-listing API endpoints (`admin`, `org`, `user`, `repo`, and
    `shared`) return runners in a non-deterministic order across pages. When
    paging through runners, some runners from page 1 could reappear on page
    2 (and others get skipped entirely).

    The cause is in `FindRunnerOptions.ToOrders()`. Most sort modes order by
    a **non-unique** column only:

    - default / `online` / `offline` → `last_online`
    - `alphabetically` / `reversealphabetically` → `name`

    When multiple runners tie on the sort key (e.g. every offline runner
    shares `last_online = 0`, or two runners have the same name), the
    database is free to return the tied rows in any order between separate
    queries. Combined with `LIMIT`/`OFFSET` pagination, this means the same
    runner can land on more than one page.

    Append the unique primary key `id` as a stable tiebreaker to each
    non-unique sort order:

    The `newest`/`oldest` modes already sort by the unique `id`, so they are
    left unchanged.

commit f7fd510224
Author: bircni <bircni@icloud.com>
Date:   Fri Jul 3 20:07:37 2026 +0200

    fix(release): gate draft release attachments on web download endpoints (#38318)

    Draft-release access control was enforced only on the API release
    endpoints (`/api/v1/repos/{owner}/{repo}/releases/...`) but not on the
    UUID-based web attachment endpoints (`/attachments/{uuid}`,
    `/{owner}/{repo}/attachments/{uuid}`,
    `/{owner}/{repo}/releases/attachments/{uuid}`).

    Anyone who obtained an attachment UUID — including unauthenticated
    callers — could download files belonging to a hidden draft release,
    since `ServeAttachment` only checked repo-level read permission and
    never the release's draft state.

commit 38a5824753
Author: silverwind <me@silverwind.io>
Date:   Fri Jul 3 09:22:27 2026 +0200

    ci(snap): build snaps natively instead of on launchpad (#38312)

    The nightly snap build fails with `snapcraft remote-build`'s
    `BadRequest()`: it force-pushes Gitea's full history to a fresh
    Launchpad repo each run and creates the recipe before Launchpad has
    indexed the `main` ref. The race is unwinnable at Gitea's repo size, and
    Canonical does not support `remote-build` in CI.

    Build locally on native amd64 + arm64 runners with
    `snapcore/action-build` + `snapcore/action-publish` instead — no
    Launchpad, no race. Drops the `LAUNCHPAD_CREDENTIALS` secret (publishing
    keeps `SNAPCRAFT_STORE_CREDENTIALS`); the `snap/` recipe is unchanged,
    so the same snaps ship to `latest/edge`.

    Co-authored-by: Lunny Xiao <xiaolunwen@gmail.com>

commit e8d2c493bb
Author: silverwind <me@silverwind.io>
Date:   Thu Jul 2 23:09:37 2026 +0200

    chore: update `eslint-plugin-unicorn` to v70 (#38310)

    Bumps to https://github.com/sindresorhus/eslint-plugin-unicorn/releases/tag/v70.0.0,
    enable all new rules, no violations.

    ---------

    Signed-off-by: silverwind <me@silverwind.io>
    Co-authored-by: Claude (Opus 4.8) <noreply@anthropic.com>

commit b09920a537
Author: Shudhanshu Singh <sudhanshuwriterblc@gmail.com>
Date:   Thu Jul 2 20:44:48 2026 +0530

    feat(webhook): support Telegram Bot API 10.1 Rich Messages (#38298)

    Upgrades Gitea's Telegram webhook integration to support Telegram Bot
    API 10.1 (June 2026 release). This enables Gitea webhooks to take
    advantage of rich formatted messages (tables, nested blocks, collapsible
    details, etc.) by routing them through the /sendRichMessage endpoint
    with the new rich_message payload structure.

    Old `/sendMessage` webhook URLs are written to `/sendRichMessage`
    at runtime to prevent the need for database migrations

    Fixes https://github.com/go-gitea/gitea/issues/38118

    ---------

    Co-authored-by: wxiaoguang <wxiaoguang@gmail.com>

commit c6184ed184
Author: silverwind <me@silverwind.io>
Date:   Thu Jul 2 13:55:45 2026 +0200

    chore(snap): drop `armhf` build (#38311)

    Launchpad no longer builds `core24` snaps for `armhf`. Since `snapcraft
    remote-build` submits a single request for all platforms, the `armhf`
    rejection fails with `snapcraft internal error: BadRequest()` and takes
    the `amd64` and `arm64` builds down with it, so nothing gets published.

    Dropping 32-bit ARM from `snap/snapcraft.yaml` and the workflow's
    `--build-for` restores nightly snap publishing for the remaining
    architectures.

commit 8909958055
Author: Shudhanshu Singh <sudhanshuwriterblc@gmail.com>
Date:   Thu Jul 2 10:50:25 2026 +0530

    fix(actions): prevent chevron overlap with log text when timestamps are enabled (#38227)
    This PR resolves a UI alignment bug in the Gitea Actions log viewer
    where the expand/collapse disclosure chevron overlaps with the log text
    (specifically the timestamp) when timestamps are enabled.
    When log timestamps are enabled, the timestamp element
    (`.log-time-stamp`) is rendered as the first element next to the line
    number. Because it only had a default `10px` left margin, it positioned
    itself exactly where the group's expand/collapse chevron is located,
    causing them to overlap.
    Updated the CSS styles in `web_src/js/components/ActionRunJobView.vue`
    to dynamically apply the `21px` margin to whichever element is the first
    visible element after the line number:
    - If the timestamp is visible, it gets the `21px` margin to clear the
    chevron, and the subsequent log message gets a `10px` margin.
    - If the timestamp is hidden, the log message receives the `21px`
    margin.
    **Before:**
    <img width="853" height="348" alt="actions_log_before"
    src="https://github.com/user-attachments/assets/d09a752e-18cb-4fe3-b749-4979cbe45240"
    />

    **After:**
    <img width="862" height="511" alt="actions_log_after"
    src="https://github.com/user-attachments/assets/63063f05-8cd6-4986-a993-ed12f28625c8"
    />

    Fixes #38222.

    ---------

    Signed-off-by: silverwind <me@silverwind.io>
    Co-authored-by: Giteabot <teabot@gitea.io>
    Co-authored-by: silverwind <me@silverwind.io>

commit 638e4bce09
Author: silverwind <me@silverwind.io>
Date:   Wed Jul 1 23:07:34 2026 +0200

    chore: upgrade `go-swagger` to v0.35.0 and enforce zero swagger warnings (#38299)

    Updates `go-swagger` to v0.35.0 and makes swagger generation and
    validation warning-free, with the build now failing on any warning
    (`go-swagger` itself exits `0` on warnings).

    - Generation passes `--enable-allof-compounding` (keeps `$ref` fields
    bare, no spec change) and `--skip-enum-desc` (drops the enum description
    that duplicates `x-go-enum-desc` and was the only source of `allOf`
    noise in the OpenAPI 3.0 output).
    - Fixed warnings at the source: dropped `swagger:strfmt` where it
    conflicts with `required: true` (`required` kept, `time.Time` still maps
    to `date-time`), fixed a malformed `units_map` example, moved the
    `parameterBodies` injection hack to `swagger:parameters`, and removed
    unused responses.

    Fixes: https://github.com/go-gitea/gitea/issues/12508

    ---------

    Co-authored-by: bircni <bircni@icloud.com>

commit a031454586
Author: puni9869 <80308335+puni9869@users.noreply.github.com>
Date:   Thu Jul 2 02:13:46 2026 +0530

    fix: Improve since/until when counting commits for X-Total-Count (#38243)

    Follow up for https://github.com/go-gitea/gitea/pull/38204.

    ---------

    Signed-off-by: puni9869 <80308335+puni9869@users.noreply.github.com>

commit c52a07dcfe
Author: silverwind <me@silverwind.io>
Date:   Wed Jul 1 22:16:42 2026 +0200

    chore: remove eslint-plugin-array-func (#38294)

    The rules from `eslint-plugin-array-func` are redundant with
    `eslint-plugin-unicorn`:

    - `from-map` → `unicorn/prefer-array-from-map`
    - `no-unnecessary-this-arg` → `unicorn/no-array-method-this-argument`
    - `prefer-flat` / `prefer-flat-map` → `unicorn/prefer-array-flat` /
    `unicorn/prefer-array-flat-map` (already disabled here)

    The two remaining rules (`avoid-reverse`, `prefer-array-from`) are niche
    and not worth carrying an extra dependency for.

    Co-authored-by: bircni <bircni@icloud.com>

commit b6ef881a9f
Author: bircni <bircni@icloud.com>
Date:   Wed Jul 1 22:07:44 2026 +0200

    docs: Welcome Zettat to TOC (#38303)

commit 6240d8bf89
Author: Kausthubh J Rao <105716675+Exgene@users.noreply.github.com>
Date:   Thu Jul 2 01:17:47 2026 +0530

    fix(workflows): branch protection status checks fail when workflow uses on: paths filter (#38237)

commit 9cb2719fab
Author: silverwind <me@silverwind.io>
Date:   Wed Jul 1 16:28:36 2026 +0200

    chore: update node.js to v26 (#38285)

    - bump ci, flake and `@types/node` to node 26
    - regenerate flake.lock which is needed for that package
    - refactor workflow to use shared composite action

commit e8654c7e06
Author: silverwind <me@silverwind.io>
Date:   Wed Jul 1 13:17:23 2026 +0200

    refactor: replace `vue-bar-graph` dependency with inlined SVG chart (#38292)

    Inlines the small SVG bar graph into `RepoActivityTopAuthors.vue` (its
    only consumer) and drops the `vue-bar-graph` npm dependency.

    - Bars render at static height (dropped the grow animation).
    - Theme-aware axis color instead of a hardcoded `#555555`.
    - Removed the dangling `role="img"`/`aria-labelledby` on the `<svg>`.
    - Reserve the chart height so the page does not shift when the component
    mounts.

    <img width="416" height="110" alt="Screenshot 2026-07-01 at 11 15 25"
    src="https://github.com/user-attachments/assets/b2db4d0c-20f1-4345-9951-32a908abfaba"
    />
    <img width="419" height="110" alt="Screenshot 2026-07-01 at 11 15 35"
    src="https://github.com/user-attachments/assets/853305a5-575f-4a26-ba3b-12fc51081324"
    />

    fyi @lafriks

    ---------

    Signed-off-by: silverwind <me@silverwind.io>

commit 67a6bd7fc0
Author: Zettat123 <zettat123@gmail.com>
Date:   Wed Jul 1 04:33:16 2026 -0600

    feat(auth): add `disable-2fa` command (#38275)

    This PR adds the `gitea admin user disable-2fa` command to disable 2FA
    for a user

    When the only admin in the instance loses their 2FA credentials, this
    command can be used to disable 2FA, allowing them to log in and reset
    it.

    ---------

    Co-authored-by: Giteabot <teabot@gitea.io>

commit 77e221ffaf
Author: Aidan Fahey <afahey2003@yahoo.com>
Date:   Wed Jul 1 06:03:38 2026 -0400

    fix(oauth2): persist linkAccountData during auto-link 2FA flow (#38274)

    Fixes HTTP 500 when OIDC auto account linking (`ACCOUNT_LINKING=auto`)
    requires local 2FA. `oauth2LinkAccount` set `linkAccount` in the session
    before redirecting to 2FA but did not persist `linkAccountData`, so
    `TwoFactorPost` failed with `not in LinkAccount session`. The manual
    linking flow already stored both, this aligns auto-link with that
    behavior.

    Closes #38171

    ---------

    Co-authored-by: bircni <bircni@icloud.com>
    Co-authored-by: wxiaoguang <wxiaoguang@gmail.com>

commit 458c11bd68
Author: bircni <bircni@icloud.com>
Date:   Wed Jul 1 11:19:47 2026 +0200

    fix(actions): allow Actions bot to push to protected branches (#38284)

    Fixes #38278

    When branch protection matches the branch an Actions workflow pushes to,
    the runner's `git push` is rejected — even though the workflow token has
    `contents: write` and the same push performed with a PAT (write access)
    succeeds. Disabling protection or changing the pattern so it no longer
    matches makes the push work.

    In `preReceiveBranch` (`routers/private/hook_pre_receive.go`), the "can
    the doer push to this protected branch" check resolves the pusher with
    `user_model.GetUserByID(ctx, ctx.opts.UserID)`. For an Actions push the
    user ID is `-2` (the virtual `ActionsUserID`), which has no database
    row, so the lookup fails. Even past that, `CanUserPush` →
    `HasAccessUnit`/whitelist membership cannot evaluate a virtual user and
    returns `false`. As a result the Actions bot was rejected on every
    matching protected branch, despite the earlier `assertCanWriteRef`
    already confirming the token's code-write via
    `GetActionsUserRepoPermission`.

    This was inconsistent: a PAT with identical write access passed the
    exact same check.

    Evaluate the Actions bot against its already-computed token permission
    instead of a user lookup, mirroring the existing
    `IsUserMergeWhitelisted` pattern:

    - Add `CanActionsUserPush` / `CanActionsUserForcePush` on
    `ProtectedBranch`, which take the precomputed `access_model.Permission`.
    - Allow the push when push is enabled, **no** push whitelist is
    enforced, and the token has code-write.
    - Keep the bot blocked when a whitelist is enforced — it cannot be added
    to one, so it must use a pull request. This preserves the whitelist as a
    real security boundary.

    Force-push, signed-commit and protected-file-path checks are untouched.

    ---------

    Signed-off-by: bircni <bircni@icloud.com>
    Co-authored-by: wxiaoguang <wxiaoguang@gmail.com>

commit 3d2bbd25ec
Author: GiteaBot <teabot@gitea.io>
Date:   Wed Jul 1 01:19:35 2026 +0000

    [skip ci] Updated translations via Crowdin

commit 7745720292
Author: Avinash Thakur <19588421+80avin@users.noreply.github.com>
Date:   Wed Jul 1 02:01:13 2026 +0530

    feat: extend <video> tag allowed attributes (#38279)

    autoplay is useless nowadays without "muted" as browsers won't autoplay
    unmuted videos.
    Similarly, other attributes are also commonly used and harmless to keep.

    <!--
    Before submitting:
    - Target the `main` branch; release branches are for backports only.
    - Use a Conventional Commits title, e.g. `fix(repo): handle empty branch
    names`.
    - Read the contributing guidelines:
    https://github.com/go-gitea/gitea/blob/main/CONTRIBUTING.md
    - Documentation changes go to https://gitea.com/gitea/docs

    Describe your change below and link any issue it fixes.
    -->

    ---------

    Signed-off-by: Avinash Thakur <19588421+80avin@users.noreply.github.com>

commit d46d0540d0
Author: bircni <bircni@icloud.com>
Date:   Tue Jun 30 21:59:30 2026 +0200

    fix(actions): include all aggregable run statuses in status filter (#38280)

    The **Status** filter dropdown on the repository Actions run list does
    not let you filter for **Blocked** runs (nor **Cancelled** or
    **Skipped**). These statuses are missing from the dropdown even though a
    run can legitimately end up in any of them.

    A run's status is computed by `aggregateJobStatus`, which can return
    `Blocked`, `Cancelled` and `Skipped`. Because the filter dropdown only
    offered Success, Failure, Waiting, Running and Cancelling, runs in those
    other states existed but were impossible to filter for.

commit e449018730
Author: techknowlogick <techknowlogick@gitea.com>
Date:   Tue Jun 30 18:35:29 2026 +0200

    non-shallow clone for snapcraft

    Signed-off-by: techknowlogick <techknowlogick@gitea.com>

commit e1cdb71845
Author: Vinod-OAI <venkat.vinod@observe.ai>
Date:   Tue Jun 30 20:12:05 2026 +0530

    fix(archiver): use serializable repo-archive queue payload (#38273)

    After upgrading from 1.25.x to 1.26.x, `repo-archive` workers can fail
    to unmarshal queued items:

    ```
    Failed to unmarshal item from queue "repo-archive":
    json: unable to unmarshal into Go convert.Conversion within "/Repo/Units/0/Config":
    cannot derive concrete type for nil interface with finite type set
    ```

    `ArchiveRequest` started embedding `*repo_model.Repository` in 1.26,
    which does not round-trip through the JSON queue.

    This change stores a minimal `archiveQueueItem` (`RepoID`, `Type`,
    `CommitID`, `Paths`) in `repo-archive` and loads the repository in the
    worker. `UnmarshalJSON` accepts legacy payloads that used `RepoID` or
    embedded `Repo.id`.

    Fixes #38272

    <!--
    Before submitting:
    - Target the `main` branch; release branches are for backports only.
    - Use a Conventional Commits title, e.g. `fix(repo): handle empty branch
    names`.
    - Read the contributing guidelines:
    https://github.com/go-gitea/gitea/blob/main/CONTRIBUTING.md
    - Documentation changes go to https://gitea.com/gitea/docs

    Describe your change below and link any issue it fixes.
    -->

    ---------

    Co-authored-by: bircni <bircni@icloud.com>

commit a64131e22d
Author: silverwind <me@silverwind.io>
Date:   Tue Jun 30 15:53:29 2026 +0200

    chore: update eslint plugins and config (#38264)

    1. Bump all eslint dependencies, enable some of the new unicorn rules
    2. Remove `eslint-plugin-de-morgan`, it sometimes causes readability
    issues
    3. Disable some of the unicorn rules that are known to produce
    false-positives
    4. Remove obsolete type cast
    5. Fix one violation of
    https://github.com/sindresorhus/eslint-plugin-unicorn/blob/main/docs/rules/prefer-dom-node-replace-children.md

    ---------

    Signed-off-by: silverwind <me@silverwind.io>

commit 0f0a38c1b9
Author: GiteaBot <teabot@gitea.io>
Date:   Tue Jun 30 01:13:52 2026 +0000

    [skip ci] Updated translations via Crowdin

commit 535f791166
Author: silverwind <me@silverwind.io>
Date:   Tue Jun 30 00:59:08 2026 +0200

    ci: regenerate codemirror languages on renovate npm updates (#38267)

    Adds `make generate-codemirror-languages` to the npm group's
    `postUpgradeTasks` in `renovate.json5`, so renovate regenerates
    `assets/codemirror-languages.json` whenever `@codemirror/language-data`
    (or any npm dep) updates — mirroring the existing `make svg` handling.

    Also reformats the `fileFilters` arrays multi-line and regenerates the
    asset to pick up current upstream linguist languages.

commit b34a09be38
Author: Lunny Xiao <xiaolunwen@gmail.com>
Date:   Mon Jun 29 14:35:26 2026 -0700

    build: fix snapcraft release (#38260)

    Signed-off-by: silverwind <me@silverwind.io>
    Co-authored-by: silverwind <me@silverwind.io>

commit 6f2e328c85
Author: Giteabot <teabot@gitea.io>
Date:   Mon Jun 29 10:22:21 2026 -0700

    chore(deps): update dependency js-yaml to v5 (#38262)

    This PR contains the following updates:

    | Package | Change |
    [Age](https://docs.renovatebot.com/merge-confidence/) |
    [Confidence](https://docs.renovatebot.com/merge-confidence/) |
    |---|---|---|---|
    | [js-yaml](https://redirect.github.com/nodeca/js-yaml) | [`4.2.0` →
    `5.1.0`](https://renovatebot.com/diffs/npm/js-yaml/4.2.0/5.1.0) |
    ![age](https://developer.mend.io/api/mc/badges/age/npm/js-yaml/5.1.0?slim=true)
    |
    ![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/js-yaml/4.2.0/5.1.0?slim=true)
    |

    ---

    <details>
    <summary>nodeca/js-yaml (js-yaml)</summary>
    [`v5.1.0`](https://redirect.github.com/nodeca/js-yaml/blob/HEAD/CHANGELOG.md#510---2026-06-23)

    [Compare
    Source](https://redirect.github.com/nodeca/js-yaml/compare/5.0.0...5.1.0)

    - Collection tags can finalize an incrementally populated carrier into a
      different result value.

    - \[breaking] `quoteStyle` now selects the preferred quote style; use
    the
      restored `forceQuotes` option to force quoting non-key strings.
    [`v5.0.0`](https://redirect.github.com/nodeca/js-yaml/blob/HEAD/CHANGELOG.md#500---2026-06-20)

    [Compare
    Source](https://redirect.github.com/nodeca/js-yaml/compare/4.3.0...5.0.0)

    - Added named exports for schemas, tags, parser events and AST
    utilities.
    - Reworked `JSON_SCHEMA` and `CORE_SCHEMA` with spec-compliant scalar
    resolution
      rules, and added `YAML11_SCHEMA`.
    - Added `realMapTag` for lossless mappings with non-string and complex
    keys.
    Object-based mappings now reject complex keys instead of stringifying
    them.
    - Added `dump()` `transform` option for changing the generated AST
    before
      rendering.
    - Added `dump()` options `seqInlineFirst`, `flowBracketPadding`,
    `flowSkipCommaSpace`, `flowSkipColonSpace`, `quoteFlowKeys`,
    `quoteStyle` and
      `tagBeforeAnchor`.
    - Added formal data layers (events and AST) for modular data pipelines.
      - Added low-level parser (to events), presenter and visitor APIs.
    - Added the [YAML Test
    Suite](https://redirect.github.com/yaml/yaml-test-suite) to the
      test set.

    - See the [migration guide](docs/migrate_v4_to_v5.md) for upgrade notes.
    - Rewritten in TypeScript and reorganized the public API around flat
    named
      exports.
    - Reduced the set of exported schemas:
      - YAML 1.2 schemas: `CORE_SCHEMA` (loader default), `JSON_SCHEMA`,
        `FAILSAFE_SCHEMA`.
    - `YAML11_SCHEMA`, a combination of all YAML 1.1 tags (YAML 1.1 does not
        specify a schema, only "types").
    - `load`/`dump` default behaviour is now specified exactly via schemas:
      - `load` uses `CORE_SCHEMA`, without `!!merge` by default.
    - `dump` uses `YAML11_SCHEMA` + `CORE_SCHEMA` for the quoting check, to
        guarantee backward compatibility by default.
    - `!!set` is now loaded as a JavaScript `Set`.
    - Replaced the `Type` API with a tags API. Similar, but more precise and
      simpler. See examples for details. Tags can be defined via
    `defineScalarTag()`, `defineSequenceTag()` and `defineMappingTag()`, or
    as a
      spread + override of an existing tag.
    - Renamed `Schema.extend()` to `Schema.withTags()`.
    - Expanded YAML 1.2 conformance and improved handling of directives,
    document
      markers, block keys, multiline scalars, tag syntax and other things.
    - `load()` now throws on empty input instead of returning `undefined`.
    - Moved browser builds to the `js-yaml/browser` export.
    - Deprecated the `loadAll` signature with an iterator (still works, but
    is a
      candidate for removal).

    - Removed deprecated `safeLoad()`, `safeLoadAll()` and `safeDump()`
    exports.
    - Removed `DEFAULT_SCHEMA` and the nested `types` export.
    - Removed loader options `onWarning`, `legacy` and `listener`.
    - Removed dumper options `styles`, `replacer`, `noCompatMode`,
    `condenseFlow`,
    `quotingType` and `forceQuotes`. Renamed `noArrayIndent` to
    `seqNoIndent`.
    Formatting and representation are now configured through presenter
    options,
      schemas and tag definitions. See migration guide on how to replace.
    - Removed support for importing internal files from `lib/`.
    [`v4.3.0`](https://redirect.github.com/nodeca/js-yaml/blob/HEAD/CHANGELOG.md#430-3150---2026-06-27)

    [Compare
    Source](https://redirect.github.com/nodeca/js-yaml/compare/4.2.0...4.3.0)

    - Backported `maxTotalMergeKeys` option.

    </details>

    ---

    📅 **Schedule**: (UTC)

    - Branch creation
      - Only on Monday (`* * * * 1`)
    - Automerge
      - At any time (no schedule defined)

    🚦 **Automerge**: Disabled by config. Please merge this manually once you
    are satisfied.

    ♻ **Rebasing**: Whenever PR is behind base branch, or you tick the
    rebase/retry checkbox.

    🔕 **Ignore**: Close this PR and you won't be reminded about this update
    again.

    ---

    - [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check
    this box

    ---

    This PR has been generated by [Mend
    Renovate](https://redirect.github.com/renovatebot/renovate).

    <!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0My4xNDEuNSIsInVwZGF0ZWRJblZlciI6IjQzLjE0MS41IiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6WyJkZXBlbmRlbmNpZXMiXX0=-->

    ---------

    Co-authored-by: silverwind <me@silverwind.io>

commit 55983320ed
Author: Giteabot <teabot@gitea.io>
Date:   Mon Jun 29 10:00:15 2026 -0700

    chore(deps): update actions/cache action to v6 (#38261)

    This PR contains the following updates:

    | Package | Type | Update | Change |
    |---|---|---|---|
    | [actions/cache](https://redirect.github.com/actions/cache) | action |
    major | `v5.0.5` → `v6.1.0` |

    ---

    > [!WARNING]
    > Some dependencies could not be looked up. Check the [Dependency
    Dashboard](../issues/37531) for more information.

    ---

    <details>
    <summary>actions/cache (actions/cache)</summary>
    [`v6.1.0`](https://redirect.github.com/actions/cache/releases/tag/v6.1.0)

    [Compare
    Source](https://redirect.github.com/actions/cache/compare/v6.0.0...v6.1.0)

    - Bump
    [@&#8203;actions/cache](https://redirect.github.com/actions/cache) to
    v6.1.0 - handle read-only cache access by
    [@&#8203;jasongin](https://redirect.github.com/jasongin) in
    [#&#8203;1768](https://redirect.github.com/actions/cache/pull/1768)

    **Full Changelog**:
    <https://github.com/actions/cache/compare/v6...v6.1.0>
    [`v6`](https://redirect.github.com/actions/cache/compare/v6.0.0...v6.0.0)

    [Compare
    Source](https://redirect.github.com/actions/cache/compare/v6.0.0...v6.0.0)
    [`v6.0.0`](https://redirect.github.com/actions/cache/releases/tag/v6.0.0)

    [Compare
    Source](https://redirect.github.com/actions/cache/compare/v5.1.0...v6.0.0)

    - Update packages, migrate to ESM by
    [@&#8203;Samirat](https://redirect.github.com/Samirat) in
    [#&#8203;1760](https://redirect.github.com/actions/cache/pull/1760)

    **Full Changelog**:
    <https://github.com/actions/cache/compare/v5...v6.0.0>
    [`v5.1.0`](https://redirect.github.com/actions/cache/releases/tag/v5.1.0)

    [Compare
    Source](https://redirect.github.com/actions/cache/compare/v5.0.5...v5.1.0)

    - Bump
    [@&#8203;actions/cache](https://redirect.github.com/actions/cache) to
    v5.1.0 - handle read-only cache access by
    [@&#8203;jasongin](https://redirect.github.com/jasongin) in
    [#&#8203;1775](https://redirect.github.com/actions/cache/pull/1775)

    **Full Changelog**:
    <https://github.com/actions/cache/compare/v5...v5.1.0>

    </details>

    ---

    📅 **Schedule**: (UTC)

    - Branch creation
      - Only on Monday (`* * * * 1`)
    - Automerge
      - At any time (no schedule defined)

    🚦 **Automerge**: Disabled by config. Please merge this manually once you
    are satisfied.

    ♻ **Rebasing**: Whenever PR is behind base branch, or you tick the
    rebase/retry checkbox.

    🔕 **Ignore**: Close this PR and you won't be reminded about this update
    again.

    ---

    - [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check
    this box

    ---

    This PR has been generated by [Mend
    Renovate](https://redirect.github.com/renovatebot/renovate).

    <!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0My4xNDEuNSIsInVwZGF0ZWRJblZlciI6IjQzLjE0MS41IiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6WyJkZXBlbmRlbmNpZXMiXX0=-->

commit 6ae42ca9c4
Author: Giteabot <teabot@gitea.io>
Date:   Mon Jun 29 09:09:25 2026 -0700

    fix(deps): update module gitlab.com/gitlab-org/api/client-go/v2 to v2.42.0 (#38266)

    This PR contains the following updates:

    | Package | Change |
    [Age](https://docs.renovatebot.com/merge-confidence/) |
    [Confidence](https://docs.renovatebot.com/merge-confidence/) |
    |---|---|---|---|
    |
    [gitlab.com/gitlab-org/api/client-go/v2](https://gitlab.com/gitlab-org/api/client-go)
    | `v2.40.1` → `v2.42.0` |
    ![age](https://developer.mend.io/api/mc/badges/age/go/gitlab.com%2fgitlab-org%2fapi%2fclient-go%2fv2/v2.42.0?slim=true)
    |
    ![confidence](https://developer.mend.io/api/mc/badges/confidence/go/gitlab.com%2fgitlab-org%2fapi%2fclient-go%2fv2/v2.40.1/v2.42.0?slim=true)
    |

    ---

    > [!WARNING]
    > Some dependencies could not be looked up. Check the [Dependency
    Dashboard](../issues/37531) for more information.

    ---

    <details>
    <summary>gitlab-org/api/client-go
    (gitlab.com/gitlab-org/api/client-go/v2)</summary>
    [`v2.42.0`](https://gitlab.com/gitlab-org/api/client-go/tags/v2.42.0)

    [Compare
    Source](https://gitlab.com/gitlab-org/api/client-go/compare/v2.41.0...v2.42.0)

    - Add missing fields to project level jira integration
    ([!2925](https://gitlab.com/gitlab-org/api/client-go/-/merge_requests/2925))
    by [Heidi Berry](https://gitlab.com/heidi.berry)
    [2.42.0](https://gitlab.com/gitlab-org/api/client-go/compare/v2.41.0...v2.42.0)
    (2026-06-24)
    [`v2.41.0`](https://gitlab.com/gitlab-org/api/client-go/tags/v2.41.0)

    [Compare
    Source](https://gitlab.com/gitlab-org/api/client-go/compare/v2.40.1...v2.41.0)

    - Add missing attributes and endpoints to group
    ([!2905](https://gitlab.com/gitlab-org/api/client-go/-/merge_requests/2905))
    by [Jimmy Spagnola](https://gitlab.com/jspagnola)

    - chore(deps): update docker docker tag to v29.5.3
    ([!2924](https://gitlab.com/gitlab-org/api/client-go/-/merge_requests/2924))
    by [GitLab Dependency
    Bot](https://gitlab.com/gitlab-dependency-update-bot)
    [2.41.0](https://gitlab.com/gitlab-org/api/client-go/compare/v2.40.1...v2.41.0)
    (2026-06-23)

    </details>

    ---

    📅 **Schedule**: (UTC)

    - Branch creation
      - Only on Monday (`* * * * 1`)
    - Automerge
      - At any time (no schedule defined)

    🚦 **Automerge**: Disabled by config. Please merge this manually once you
    are satisfied.

    ♻ **Rebasing**: Whenever PR is behind base branch, or you tick the
    rebase/retry checkbox.

    🔕 **Ignore**: Close this PR and you won't be reminded about this update
    again.

    ---

    - [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check
    this box

    ---

    This PR has been generated by [Mend
    Renovate](https://redirect.github.com/renovatebot/renovate).

    <!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0My4xNDEuNSIsInVwZGF0ZWRJblZlciI6IjQzLjE0MS41IiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6WyJkZXBlbmRlbmNpZXMiXX0=-->

commit 5e5f5f3116
Author: Giteabot <teabot@gitea.io>
Date:   Mon Jun 29 08:10:47 2026 -0700

    fix(deps): update go dependencies (#38194)

    Update go deps and fix discovered issues

    Co-authored-by: silverwind <me@silverwind.io>
    Co-authored-by: wxiaoguang <wxiaoguang@gmail.com>

commit 4ce63a1d57
Author: wxiaoguang <wxiaoguang@gmail.com>
Date:   Mon Jun 29 21:06:25 2026 +0800

    chore: various UI problems (#38263)

    1. fix dirty "list" styles for "githooks" and "webhooks"
    2. fix git hook edit page layout
    3. fix codemirror editor styles
    4. fix incorrect "ui attached header" width

commit 07b18467c0
Author: Giteabot <teabot@gitea.io>
Date:   Mon Jun 29 03:59:14 2026 -0700

    fix: update npm dependencies, fix misc issues (#38257)

    Update all npm dependencies and fix discovered issues.

    Co-authored-by: bircni <bircni@icloud.com>
    Co-authored-by: silverwind <me@silverwind.io>
    Co-authored-by: wxiaoguang <wxiaoguang@gmail.com>

commit e68ee61879
Author: Giteabot <teabot@gitea.io>
Date:   Mon Jun 29 01:30:14 2026 -0700

    chore(deps): update action dependencies (#38258)

    This PR contains the following updates:

    | Package | Type | Update | Change | Pending |
    |---|---|---|---|---|
    | [actions/setup-go](https://redirect.github.com/actions/setup-go) |
    action | minor | `v6.4.0` → `v6.5.0` | |
    | [go-gitea/giteabot](https://redirect.github.com/go-gitea/giteabot) |
    action | patch | `v1.0.3` → `v1.0.4` | |
    | redis | service | digest | `a505f8b` → `c904002` |  |
    |
    [renovatebot/github-action](https://redirect.github.com/renovatebot/github-action)
    | action | patch | `v46.1.15` → `v46.1.16` | `v46.1.17` |

    ---

    <details>
    <summary>actions/setup-go (actions/setup-go)</summary>
    [`v6.5.0`](https://redirect.github.com/actions/setup-go/releases/tag/v6.5.0)

    [Compare
    Source](https://redirect.github.com/actions/setup-go/compare/v6.4.0...v6.5.0)

    - Upgrade actions dependencies by
    [@&#8203;priyagupta108](https://redirect.github.com/priyagupta108) with
    [@&#8203;Copilot](https://redirect.github.com/Copilot) in
    [#&#8203;744](https://redirect.github.com/actions/setup-go/pull/744)
    - Upgrade [@&#8203;types/node](https://redirect.github.com/types/node)
    and typescript-eslint dependencies to resolve npm audit findings by
    [@&#8203;HarithaVattikuti](https://redirect.github.com/HarithaVattikuti)
    in [#&#8203;755](https://redirect.github.com/actions/setup-go/pull/755)
    - Upgrade
    [@&#8203;actions/cache](https://redirect.github.com/actions/cache) to
    5.1.0, log cache write denied by
    [@&#8203;jasongin](https://redirect.github.com/jasongin) in
    [#&#8203;758](https://redirect.github.com/actions/setup-go/pull/758)
    - Upgrade version to 6.5.0 in package.json and package-lock.json by
    [@&#8203;HarithaVattikuti](https://redirect.github.com/HarithaVattikuti)
    in [#&#8203;762](https://redirect.github.com/actions/setup-go/pull/762)

    - [@&#8203;priyagupta108](https://redirect.github.com/priyagupta108)
    with [@&#8203;Copilot](https://redirect.github.com/Copilot) made their
    first contribution in
    [#&#8203;744](https://redirect.github.com/actions/setup-go/pull/744)
    - [@&#8203;jasongin](https://redirect.github.com/jasongin) made their
    first contribution in
    [#&#8203;758](https://redirect.github.com/actions/setup-go/pull/758)

    **Full Changelog**:
    <https://github.com/actions/setup-go/compare/v6...v6.5.0>

    </details>

    <details>
    <summary>go-gitea/giteabot (go-gitea/giteabot)</summary>
    [`v1.0.4`](https://redirect.github.com/go-gitea/giteabot/releases/tag/v1.0.4)

    [Compare
    Source](https://redirect.github.com/go-gitea/giteabot/compare/v1.0.3...v1.0.4)

    - Keep lgtm status up to date on fork and backport PRs by
    [@&#8203;silverwind](https://redirect.github.com/silverwind) in
    [#&#8203;9](https://redirect.github.com/go-gitea/giteabot/pull/9)

    **Full Changelog**:
    <https://github.com/go-gitea/giteabot/compare/v1.0.3...v1.0.4>

    </details>

    <details>
    <summary>renovatebot/github-action (renovatebot/github-action)</summary>
    [`v46.1.16`](https://redirect.github.com/renovatebot/github-action/releases/tag/v46.1.16)

    [Compare
    Source](https://redirect.github.com/renovatebot/github-action/compare/v46.1.15...v46.1.16)

    - update references to renovatebot/github-action to v46.1.15
    ([0013591](https://redirect.github.com/renovatebot/github-action/commit/00135917fdbb8f382071ce3f27c8432ad0f75c2a))

    - **deps:** update dependency
    [@&#8203;types/node](https://redirect.github.com/types/node) to v24.13.0
    ([358d0a4](https://redirect.github.com/renovatebot/github-action/commit/358d0a480c37ecd2b23ab66dcd5170452917642c))
    - **deps:** update dependency
    [@&#8203;types/node](https://redirect.github.com/types/node) to v24.13.1
    ([783fe90](https://redirect.github.com/renovatebot/github-action/commit/783fe90b5a88b8a02d5d6c9bb65c01e36b110545))
    - **deps:** update dependency
    [@&#8203;types/node](https://redirect.github.com/types/node) to v24.13.2
    ([74b1acf](https://redirect.github.com/renovatebot/github-action/commit/74b1acf27101775dfaf2793c89c214898cd33520))
    - **deps:** update dependency
    [@&#8203;types/node](https://redirect.github.com/types/node) to v24.13.2
    ([#&#8203;1049](https://redirect.github.com/renovatebot/github-action/issues/1049))
    ([23dcba0](https://redirect.github.com/renovatebot/github-action/commit/23dcba0a91738a6e394d2e991c307937406b6587))
    - **deps:** update dependency esbuild to v0.28.1 \[security]
    ([#&#8203;1041](https://redirect.github.com/renovatebot/github-action/issues/1041))
    ([54012bd](https://redirect.github.com/renovatebot/github-action/commit/54012bd29e2a1a395bbffede3e46a836aebc3e47))
    - **deps:** update dependency lint-staged to v17
    ([#&#8203;1051](https://redirect.github.com/renovatebot/github-action/issues/1051))
    ([6a9f6dc](https://redirect.github.com/renovatebot/github-action/commit/6a9f6dc5beb03977800c57cd92b5ca15bfc67439))
    - **deps:** update dependency npm-run-all2 to v9
    ([#&#8203;1052](https://redirect.github.com/renovatebot/github-action/issues/1052))
    ([8757a4e](https://redirect.github.com/renovatebot/github-action/commit/8757a4e574f6d5c0ba3fd6a6706c420c5c96e1c9))
    - **deps:** update dependency npm-run-all2 to v9.0.2
    ([2c2c4e5](https://redirect.github.com/renovatebot/github-action/commit/2c2c4e5c89b4c5bfdd31288b8f30d8acf0a3c4a3))
    - **deps:** update linters to v8.60.1
    ([d40e1b7](https://redirect.github.com/renovatebot/github-action/commit/d40e1b7d86f5ce052321dee875f215d0c0db3443))
    - **deps:** update linters to v8.61.0
    ([#&#8203;1043](https://redirect.github.com/renovatebot/github-action/issues/1043))
    ([1e06192](https://redirect.github.com/renovatebot/github-action/commit/1e061929c42cf0828b24480be6f542ba6ccf88a3))
    - **deps:** update node.js to v24.17.0
    ([#&#8203;1050](https://redirect.github.com/renovatebot/github-action/issues/1050))
    ([2cf33bc](https://redirect.github.com/renovatebot/github-action/commit/2cf33bc523576895fa380cf8af2e05336c943486))
    - **deps:** update pnpm to v10.34.2
    ([#&#8203;1048](https://redirect.github.com/renovatebot/github-action/issues/1048))
    ([63ebb9d](https://redirect.github.com/renovatebot/github-action/commit/63ebb9d84b858604f205265f37e642256bf5f295))
    - **deps:** update pnpm to v10.34.3
    ([#&#8203;1054](https://redirect.github.com/renovatebot/github-action/issues/1054))
    ([cd3436d](https://redirect.github.com/renovatebot/github-action/commit/cd3436d028bc86910e9cbf348b1c975a58d90135))
    - **deps:** update pnpm/action-setup action to v6
    ([#&#8203;1053](https://redirect.github.com/renovatebot/github-action/issues/1053))
    ([77e5805](https://redirect.github.com/renovatebot/github-action/commit/77e58054f1f031a8b4f80dcbbd00f65e45643d09))
    - **deps:** update prettier packages to v3.8.4
    ([#&#8203;1045](https://redirect.github.com/renovatebot/github-action/issues/1045))
    ([d688888](https://redirect.github.com/renovatebot/github-action/commit/d688888385cd5bd04a70a7889c8112b7d960512b))
    - **deps:** update semantic-release monorepo to v25.0.4
    ([#&#8203;1046](https://redirect.github.com/renovatebot/github-action/issues/1046))
    ([d2dacc8](https://redirect.github.com/renovatebot/github-action/commit/d2dacc89959d7963d77f06ffadf0abcf1265fdc7))
    - **deps:** update semantic-release monorepo to v25.0.5
    ([#&#8203;1047](https://redirect.github.com/renovatebot/github-action/issues/1047))
    ([d91f80c](https://redirect.github.com/renovatebot/github-action/commit/d91f80c864d00b0ddc134c949cf464395ef1afaa))

    - **deps:** lock file maintenance
    ([26f827f](https://redirect.github.com/renovatebot/github-action/commit/26f827fdc5121b9d4fbe1cf8dcb76d6efe58b78b))

    - **deps:** update ghcr.io/renovatebot/renovate docker tag to v43.214.6
    ([f3fd163](https://redirect.github.com/renovatebot/github-action/commit/f3fd1634318528e2c0bf9402ad11ced1e2583cc4))
    - **deps:** update ghcr.io/renovatebot/renovate docker tag to v43.216.1
    ([8cf15ee](https://redirect.github.com/renovatebot/github-action/commit/8cf15ee083f561ff061f991a7ae7daeef11b0243))
    - **deps:** update ghcr.io/renovatebot/renovate docker tag to v43.216.2
    ([29c9f31](https://redirect.github.com/renovatebot/github-action/commit/29c9f31e4a3ad4f169bbfaf78a3fcbba9569e275))
    - **deps:** update ghcr.io/renovatebot/renovate docker tag to v43.216.4
    ([400f75c](https://redirect.github.com/renovatebot/github-action/commit/400f75cbdb0a8ec5364c9f3f22932c79c91ec56f))
    - **deps:** update ghcr.io/renovatebot/renovate docker tag to v43.217.0
    ([2aea29e](https://redirect.github.com/renovatebot/github-action/commit/2aea29ebc0bebd74676a36c246d9dffc8635aa2a))
    - **deps:** update ghcr.io/renovatebot/renovate docker tag to v43.217.1
    ([268f254](https://redirect.github.com/renovatebot/github-action/commit/268f25430113d2f91e6ab0244171726aff45791d))
    - **deps:** update ghcr.io/renovatebot/renovate docker tag to v43.218.0
    ([ebcc800](https://redirect.github.com/renovatebot/github-action/commit/ebcc800ccdcbca03d3939d07cd5170dcbe3fddf1))
    - **deps:** update ghcr.io/renovatebot/renovate docker tag to v43.219.0
    ([a61593e](https://redirect.github.com/renovatebot/github-action/commit/a61593e15cdcaa203cdf199b01785cbde1b3393b))
    - **deps:** update ghcr.io/renovatebot/renovate docker tag to v43.220.0
    ([#&#8203;1037](https://redirect.github.com/renovatebot/github-action/issues/1037))
    ([0d198c1](https://redirect.github.com/renovatebot/github-action/commit/0d198c1f3cedd5d962195b498b53d23de67b3c7f))
    - **deps:** update ghcr.io/renovatebot/renovate docker tag to v43.222.0
    ([46f2bd6](https://redirect.github.com/renovatebot/github-action/commit/46f2bd6ed2f60e6e68085b7ccb0d408e498ad646))
    - **deps:** update ghcr.io/renovatebot/renovate docker tag to v43.222.1
    ([90deabf](https://redirect.github.com/renovatebot/github-action/commit/90deabf8530cd43db786bef00bb6a5bbbf66e372))
    - **deps:** update ghcr.io/renovatebot/renovate docker tag to v43.224.0
    ([22d7b5c](https://redirect.github.com/renovatebot/github-action/commit/22d7b5c57aa60ca4659f5f24d368812e789f1141))
    - **deps:** update ghcr.io/renovatebot/renovate docker tag to v43.224.1
    ([39a2ba1](https://redirect.github.com/renovatebot/github-action/commit/39a2ba1236cbe85d17c776505eda386398144ed2))
    - **deps:** update ghcr.io/renovatebot/renovate docker tag to v43.225.0
    ([c2f08ab](https://redirect.github.com/renovatebot/github-action/commit/c2f08ab1a1834784134b79fa3a30b83132ff5c51))
    - **deps:** update ghcr.io/renovatebot/renovate docker tag to v43.226.1
    ([75a5340](https://redirect.github.com/renovatebot/github-action/commit/75a5340ae6e848edb49abbeb7343434c84fd144c))
    - **deps:** update ghcr.io/renovatebot/renovate docker tag to v43.227.0
    ([da1079a](https://redirect.github.com/renovatebot/github-action/commit/da1079ac41ddf8ac9d473f3110b9bc2d20e8c823))
    - **deps:** update ghcr.io/renovatebot/renovate docker tag to v43.227.1
    ([26a0ce7](https://redirect.github.com/renovatebot/github-action/commit/26a0ce7c73154e11c6677da35bd23ddf1c77a704))
    - **deps:** update ghcr.io/renovatebot/renovate docker tag to v43.228.0
    ([9dd450f](https://redirect.github.com/renovatebot/github-action/commit/9dd450fe094737324c6740847d34d21d0a12670e))
    - **deps:** update ghcr.io/renovatebot/renovate docker tag to v43.228.1
    ([066bf0a](https://redirect.github.com/renovatebot/github-action/commit/066bf0aa9449c5bd4e2315df33f2986b10299ee7))
    - **deps:** update ghcr.io/renovatebot/renovate docker tag to v43.229.0
    ([edd7e4f](https://redirect.github.com/renovatebot/github-action/commit/edd7e4f83edd2652f40ed3d13236296a75cb9d9c))
    - **deps:** update ghcr.io/renovatebot/renovate docker tag to v43.229.1
    ([64e44a4](https://redirect.github.com/renovatebot/github-action/commit/64e44a4239e1eade784cf0abd54ffc4e82cb40e1))
    - **deps:** update ghcr.io/renovatebot/renovate docker tag to v43.229.2
    ([dce4d1b](https://redirect.github.com/renovatebot/github-action/commit/dce4d1b6ba43914d91ab2a2a713fd384298a42fe))
    - **deps:** update ghcr.io/renovatebot/renovate docker tag to v43.230.0
    ([30fd043](https://redirect.github.com/renovatebot/github-action/commit/30fd04394d4dfe018df48314de0036334d88d119))
    - **deps:** update ghcr.io/renovatebot/renovate docker tag to v43.230.1
    ([425d313](https://redirect.github.com/renovatebot/github-action/commit/425d313d98c58c11780a712fbee72a7e35d25b92))
    - **deps:** update ghcr.io/renovatebot/renovate docker tag to v43.231.0
    ([ae939aa](https://redirect.github.com/renovatebot/github-action/commit/ae939aab83afa3d641843d1d04300091752e09a8))
    - **deps:** update ghcr.io/renovatebot/renovate docker tag to v43.231.1
    ([cac502d](https://redirect.github.com/renovatebot/github-action/commit/cac502de33fd8931d15a849d8eff67d8b75d253c))
    - **deps:** update ghcr.io/renovatebot/renovate docker tag to v43.231.2
    ([242a56f](https://redirect.github.com/renovatebot/github-action/commit/242a56f27d85117d4b0703ff1e381aaafdc0488e))
    - **deps:** update ghcr.io/renovatebot/renovate docker tag to v43.231.3
    ([3b66329](https://redirect.github.com/renovatebot/github-action/commit/3b6632905280f6bc2656245b3916333c3c224c99))
    - **deps:** update ghcr.io/renovatebot/renovate docker tag to v43.232.0
    ([c0502ab](https://redirect.github.com/renovatebot/github-action/commit/c0502aba634bf921fa2af4eb4a052318991265bd))
    - **deps:** update ghcr.io/renovatebot/renovate docker tag to v43.232.1
    ([d46a7eb](https://redirect.github.com/renovatebot/github-action/commit/d46a7ebfc5129ac009353beed92152c3ddc4ce3b))
    - **deps:** update ghcr.io/renovatebot/renovate docker tag to v43.233.1
    ([b476f30](https://redirect.github.com/renovatebot/github-action/commit/b476f3002f23f603eb89450785a8ce68037ebf20))
    - **deps:** update ghcr.io/renovatebot/renovate docker tag to v43.233.2
    ([bc50ad1](https://redirect.github.com/renovatebot/github-action/commit/bc50ad1e38f4e32bed5288aec6e9c303a5e81117))
    - **deps:** update ghcr.io/renovatebot/renovate docker tag to v43.233.3
    ([908f92d](https://redirect.github.com/renovatebot/github-action/commit/908f92dbc49eaefff1e0c8771aa41a957268baa5))
    - **deps:** update ghcr.io/renovatebot/renovate docker tag to v43.233.4
    ([a48bc32](https://redirect.github.com/renovatebot/github-action/commit/a48bc32b6b570fe1fa55975fda7205bbbb98afa3))
    - **deps:** update ghcr.io/renovatebot/renovate docker tag to v43.234.0
    ([c929092](https://redirect.github.com/renovatebot/github-action/commit/c929092dcc2e71fcddf23dc5c9d2cdf70ed17ed4))
    - **deps:** update ghcr.io/zizmorcore/zizmor docker tag to v1.26.1
    ([#&#8203;1055](https://redirect.github.com/renovatebot/github-action/issues/1055))
    ([c878bfb](https://redirect.github.com/renovatebot/github-action/commit/c878bfb5430ce52efc451671e7887a2b5d755ffc))
    - **deps:** update zizmorcore/zizmor-action action to v0.5.7
    ([996e7bc](https://redirect.github.com/renovatebot/github-action/commit/996e7bc84761f298cb8bc5c765895b6db953876b))

    </details>

    ---

    📅 **Schedule**: (UTC)

    - Branch creation
      - Only on Monday (`* * * * 1`)
    - Automerge
      - At any time (no schedule defined)

    🚦 **Automerge**: Disabled by config. Please merge this manually once you
    are satisfied.

    ♻ **Rebasing**: Whenever PR is behind base branch, or you tick the
    rebase/retry checkbox.

    👻 **Immortal**: This PR will be recreated if closed unmerged. Get
    [config
    help](https://redirect.github.com/renovatebot/renovate/discussions) if
    that's undesired.

    ---

    - [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check
    this box

    ---

    This PR has been generated by [Mend
    Renovate](https://redirect.github.com/renovatebot/renovate).

    <!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0My4xNDEuNSIsInVwZGF0ZWRJblZlciI6IjQzLjE0MS41IiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6WyJkZXBlbmRlbmNpZXMiXX0=-->

commit 0c67849e68
Author: metsw24-max <metsw24@gmail.com>
Date:   Mon Jun 29 12:20:22 2026 +0530

    fix(packages): validate debian distribution and component names (#38116)

    **Newline injection into the Debian Release and Packages indices**

    The `distribution` and `component` come straight from the request path
    and are written line by line into the generated `Release` and `Packages`
    files (the `Suite`/`Codename`/`Components` lines and the `Filename:
    pool/<distribution>/<component>/...` line), but `UploadPackageFile` only
    checked they were non-empty. `ctx.PathParam` url-decodes the segment, so
    an encoded newline such as `main%0AInjected-Field: x` is accepted,
    stored and then re-emitted for that distribution, which lets an
    authenticated uploader forge extra fields in the index apt consumes.
    Restricted both values to a conservative name pattern in the handler,
    since that is the layer that accepts them; this should also keep the
    pool paths well formed.

    ---------

    Co-authored-by: wxiaoguang <wxiaoguang@gmail.com>

commit 762c674bc5
Author: Giteabot <teabot@gitea.io>
Date:   Sun Jun 28 23:24:18 2026 -0700

    chore(deps): update python dependencies (#38256)

    This PR contains the following updates:

    | Package | Change |
    [Age](https://docs.renovatebot.com/merge-confidence/) |
    [Confidence](https://docs.renovatebot.com/merge-confidence/) |
    |---|---|---|---|
    | [djlint](https://redirect.github.com/djlint/djLint) | `==1.39.2` →
    `==1.39.4` |
    ![age](https://developer.mend.io/api/mc/badges/age/pypi/djlint/1.39.4?slim=true)
    |
    ![confidence](https://developer.mend.io/api/mc/badges/confidence/pypi/djlint/1.39.2/1.39.4?slim=true)
    |
    | [zizmor](https://docs.zizmor.sh)
    ([source](https://redirect.github.com/zizmorcore/zizmor)) | `==1.25.2` →
    `==1.26.1` |
    ![age](https://developer.mend.io/api/mc/badges/age/pypi/zizmor/1.26.1?slim=true)
    |
    ![confidence](https://developer.mend.io/api/mc/badges/confidence/pypi/zizmor/1.25.2/1.26.1?slim=true)
    |

    ---

    <details>
    <summary>djlint/djLint (djlint)</summary>
    [`v1.39.4`](https://redirect.github.com/djlint/djLint/blob/HEAD/CHANGELOG.md#1394---2026-06-24)

    [Compare
    Source](https://redirect.github.com/djlint/djLint/compare/v1.39.3...v1.39.4)

    - Fix crashes in mypyc-compiled wheels.
    [`v1.39.3`](https://redirect.github.com/djlint/djLint/blob/HEAD/CHANGELOG.md#1393---2026-06-23)

    [Compare
    Source](https://redirect.github.com/djlint/djLint/compare/v1.39.2...v1.39.3)

    - Use Click instead of tqdm for progress output, send progress to
    stderr, respect `--quiet`, and honor `NO_COLOR`. Remove direct
    `colorama` and `tqdm` dependencies now that Click handles CLI colors and
    progress.
    - Avoid false H025 reports after self-closing tags in Django templates.
    - Avoid false H025 reports for multiline Go template attributes.
    - Keep Django child-template reformatting idempotent when inline control
    blocks also appear inside HTML attributes.
    - Respect whitespace-control dashes when applying `blank_line_after_tag`
    and `blank_line_before_tag`.

    </details>

    <details>
    <summary>zizmorcore/zizmor (zizmor)</summary>
    [`v1.26.1`](https://redirect.github.com/zizmorcore/zizmor/releases/tag/v1.26.1)

    [Compare
    Source](https://redirect.github.com/zizmorcore/zizmor/compare/v1.26.0...v1.26.1)

    This is a small corrective release for
    [1.26.0](https://docs.zizmor.sh/release-notes/#&#8203;1260).
    [`v1.26.0`](https://redirect.github.com/zizmorcore/zizmor/releases/tag/v1.26.0)

    [Compare
    Source](https://redirect.github.com/zizmorcore/zizmor/compare/v1.25.2...v1.26.0)
    🌈[🔗](https://docs.zizmor.sh/release-notes/#new-features)

    - New audit:
    [typosquat-uses](https://docs.zizmor.sh/audits/#typosquat-uses) detects
    uses: clauses that reference likely typoed actions
    ([#&#8203;1985](https://redirect.github.com/zizmorcore/zizmor/issues/1985))

    Many thanks to [@&#8203;andrew](https://redirect.github.com/andrew) for
    proposing and implementing this improvement!

    - New audit:
    [unsound-ternary](https://docs.zizmor.sh/audits/#unsound-ternary)
    detects pseudo-ternary expressions that don't evaluate as expected
    ([#&#8203;2085](https://redirect.github.com/zizmorcore/zizmor/issues/2085))

    Many thanks to [@&#8203;terror](https://redirect.github.com/terror) for
    proposing and implementing this improvement!

    - New audit:
    [adhoc-packages](https://docs.zizmor.sh/audits/#adhoc-packages) detects
    run: steps that install packages in an ad-hoc manner
    ([#&#8203;2061](https://redirect.github.com/zizmorcore/zizmor/issues/2061))

    Many thanks to
    [@&#8203;connorshea](https://redirect.github.com/connorshea) for
    proposing and implementing this improvement!
    🌱[🔗](https://docs.zizmor.sh/release-notes/#enhancements)

    - The [cache-poisoning](https://docs.zizmor.sh/audits/#cache-poisoning)
    audit now detects additional cache disablement heuristics
    ([#&#8203;2053](https://redirect.github.com/zizmorcore/zizmor/issues/2053))

    - The
    [known-vulnerable-actions](https://docs.zizmor.sh/audits/#known-vulnerable-actions)
    audit is now configurable. See [the configuration
    documentation](https://docs.zizmor.sh/audits/#known-vulnerable-actions-configuration)
    for details
    ([#&#8203;2084](https://redirect.github.com/zizmorcore/zizmor/issues/2084))

    - The
    [excessive-permissions](https://docs.zizmor.sh/audits/#excessive-permissions)
    audit is now aware of the code-quality permission
    ([#&#8203;2088](https://redirect.github.com/zizmorcore/zizmor/issues/2088))

    - The [unpinned-uses](https://docs.zizmor.sh/audits/#unpinned-uses)
    audit's auto-fix now uses the fully qualified version tag (e.g. #
    v6.0.2) when fixing a major-version ref (e.g.
    [@&#8203;v6](https://redirect.github.com/v6))
    ([#&#8203;2127](https://redirect.github.com/zizmorcore/zizmor/issues/2127))
    🚄[🔗](https://docs.zizmor.sh/release-notes/#performance-improvements)

    - Most online audits are significantly faster, thanks to more precise
    retry handling
    ([#&#8203;2036](https://redirect.github.com/zizmorcore/zizmor/issues/2036))
      Bug Fixes 🐛[🔗](https://docs.zizmor.sh/release-notes/#bug-fixes)

    - Fixed a bug where zizmor's LSP would not recognize dependabot.yaml
    files in its default configuration
    ([#&#8203;2026](https://redirect.github.com/zizmorcore/zizmor/issues/2026))

    Many thanks to [@&#8203;fionn](https://redirect.github.com/fionn) for
    implementing this fix!

    - Fixed a bug where
    [ref-version-mismatch](https://docs.zizmor.sh/audits/#ref-version-mismatch)
    would fail to fully match some version comments
    ([#&#8203;2040](https://redirect.github.com/zizmorcore/zizmor/issues/2040))

    - Fixed a bug where
    [dependabot-cooldown](https://docs.zizmor.sh/audits/#dependabot-cooldown)
    would fail to honor the user's configured days when performing autofixes
    ([#&#8203;2055](https://redirect.github.com/zizmorcore/zizmor/issues/2055))

    - Steps and jobs gated by statically-false if: conditions (e.g. if:
    false, if: ${{ false }}) are now skipped during auditing, since they
    cannot execute
    ([#&#8203;2059](https://redirect.github.com/zizmorcore/zizmor/issues/2059),
    [#&#8203;2069](https://redirect.github.com/zizmorcore/zizmor/issues/2069))

    - Fixed a bug where
    [ref-version-mismatch](https://docs.zizmor.sh/audits/#ref-version-mismatch)
    would fail to identify some valid version comments
    ([#&#8203;2073](https://redirect.github.com/zizmorcore/zizmor/issues/2073))

    - Fixed a bug where
    [unpinned-images](https://docs.zizmor.sh/audits/#unpinned-images) would
    incorrectly flag empty matrix expansions as unpinned container image
    references
    ([#&#8203;2102](https://redirect.github.com/zizmorcore/zizmor/issues/2102))

    - Fixed a bug where
    [unpinned-images](https://docs.zizmor.sh/audits/#unpinned-images) would
    incorrectly flag some matrix expansions as unpinned
    ([#&#8203;2098](https://redirect.github.com/zizmorcore/zizmor/issues/2098))

    - The SARIF (--format=sarif) and GitHub Annotations (--format=github)
    output formats now provide more correct/useful paths, particularly when
    the user provides a relative path as input to zizmor rather than zizmor
    .
    ([#&#8203;1748](https://redirect.github.com/zizmorcore/zizmor/issues/1748),
    [#&#8203;2095](https://redirect.github.com/zizmorcore/zizmor/issues/2095))

    - The [impostor-commit](https://docs.zizmor.sh/audits/#impostor-commit)
    audit no longer suggests auto-fixes, to avoid incorrectly minimizing the
    amount of manual remediation work needed
    ([#&#8203;2054](https://redirect.github.com/zizmorcore/zizmor/issues/2054))

    - The JSON and SARIF outputs no longer contain a misleading prefix key
    ([#&#8203;2095](https://redirect.github.com/zizmorcore/zizmor/issues/2095))

    </details>

    ---

    📅 **Schedule**: (UTC)

    - Branch creation
      - Only on Monday (`* * * * 1`)
    - Automerge
      - At any time (no schedule defined)

    🚦 **Automerge**: Disabled by config. Please merge this manually once you
    are satisfied.

    ♻ **Rebasing**: Whenever PR is behind base branch, or you tick the
    rebase/retry checkbox.

    👻 **Immortal**: This PR will be recreated if closed unmerged. Get
    [config
    help](https://redirect.github.com/renovatebot/renovate/discussions) if
    that's undesired.

    ---

    - [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check
    this box

    ---

    This PR has been generated by [Mend
    Renovate](https://redirect.github.com/renovatebot/renovate).

    <!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0My4xNDEuNSIsInVwZGF0ZWRJblZlciI6IjQzLjE0MS41IiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6WyJkZXBlbmRlbmNpZXMiXX0=-->

commit 8ff71a5e52
Author: wxiaoguang <wxiaoguang@gmail.com>
Date:   Mon Jun 29 14:01:12 2026 +0800

    fix: flex divided list item shrink (#38255)

    don't make the items shrink since they are used as list items.

    fix #38220

commit 8343c47bd1
Author: GiteaBot <teabot@gitea.io>
Date:   Mon Jun 29 01:20:03 2026 +0000

    [skip ci] Updated translations via Crowdin

commit c6b2394585
Author: Copilot <198982749+Copilot@users.noreply.github.com>
Date:   Sun Jun 28 15:36:28 2026 -0700

    fix(actions): authenticate snapcraft before nightly remote build (#38252)

    The `release-nightly-snapcraft` workflow’s `build-and-publish` job was
    failing because `snapcraft remote-build` fell back to interactive
    Launchpad authorization in CI. This change makes authentication explicit
    and non-interactive before the remote build step.

    - **Workflow change**
      - Add an `Authenticate snapcraft` step before `Remote build`.
    - Run `snapcraft login --with` using the existing
    `SNAPCRAFT_STORE_CREDENTIALS` secret.
      - Pin that step to `shell: bash` to support process substitution.

    - **Why this fixes the failure**
      - Prevents CI from entering browser-based Launchpad auth flow.
      - Ensures `remote-build` runs with preloaded credentials.

    ```yaml
    - name: Authenticate snapcraft
      shell: bash
      env:
        SNAPCRAFT_STORE_CREDENTIALS: ${{ secrets.SNAPCRAFT_STORE_CREDENTIALS }}
      run: snapcraft login --with <(printf '%s' "$SNAPCRAFT_STORE_CREDENTIALS")
    ```

    ---------

    Signed-off-by: Lunny Xiao <xiaolunwen@gmail.com>
    Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
    Co-authored-by: Lunny Xiao <xiaolunwen@gmail.com>
    Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>

commit 4f41ad7b91
Author: TheFox0x7 <thefox0x7@gmail.com>
Date:   Sun Jun 28 22:44:26 2026 +0200

    revert(sign): restore gpg (#38251)

    partially revert sigstore signing to avoid causing breaking change for v1.27

commit 4812e35486
Author: Augusto Xavier <augustocbx.dev@gmail.com>
Date:   Sun Jun 28 16:58:25 2026 -0300

    fix(api): respect since/until when counting commits for X-Total-Count (#38204)

    The repository commits API (`GET /repos/{owner}/{repo}/commits`) accepts
    `since` and `until` query parameters and filters the returned page of
    commits by commit date. However, the `X-Total-Count` and `X-Total`
    response headers reported the *unfiltered* total number of commits, so
    the advertised total could be far larger than the number of commits
    actually returned for the requested date range. With a range that
    matches no commits, the page is correctly empty while the headers still
    claim the full repository total.

    `gitrepo.CommitsCount` declared `Since` and `Until` options and the API
    handler populated them, but the function never appended
    `--since`/`--until` to the underlying `git rev-list --count` invocation.
    The date filters were silently dropped, so the count always reflected
    the entire revision history.

    Pass the `Since`/`Until` options through to `git rev-list`, mirroring
    the existing commit-listing path (`commitsByRangeWithTime`). The
    reported total now matches the filtered range used to build the page.

    Added `TestCommitsCountWithSinceUntil` in
    `modules/gitrepo/commit_test.go`, a table-driven unit test against the
    `repo1_bare` fixture covering `since`, `until`, and a bounded
    `since`+`until` range. It fails on the pre-fix code (every case returns
    the full count of 3) and passes after the change. Existing
    `CommitsCount` tests remain green.

    - No new settings, no default changes; this corrects an incorrect header
    value and is backward compatible. Clients that depend on `since`/`until`
    already filter the returned commits, and the headers now agree with that
    filtering.

    Fixes #35886.

    ---

    *AI-assistance disclosure:* this change was developed with the
    assistance of Claude Code (Claude Opus 4.8). I have reviewed and
    understand the change and take responsibility for it.

commit 98c61942aa
Author: TheFox0x7 <thefox0x7@gmail.com>
Date:   Sun Jun 28 21:18:12 2026 +0200

    build(sign): move to sigstore (#38250)

    drops signing with gpg in favor of sigstore based artifact signing

commit cc1df1976b
Author: bircni <bircni@icloud.com>
Date:   Sun Jun 28 20:29:34 2026 +0200

    fix: codemirror regressions (#38248)

commit 1c718da16c
Author: bircni <bircni@icloud.com>
Date:   Sun Jun 28 14:14:39 2026 +0200

    fix(api): support HEAD requests on all API GET endpoints (#38245)

    Fixes #38226

    Add `chi_middleware.GetHead` as the first `BeforeRouting` middleware on
    the API router. This makes every API `GET` endpoint automatically handle
    `HEAD` requests, as required by RFC 9110 §9.3.2.

    Previously, `HEAD` requests to endpoints like `GET
    /repos/{owner}/{repo}/git/commits/{sha}` returned `405 Method Not
    Allowed`.

    The web router already used this same middleware (see
    `routers/web/web.go:261`), so this aligns API behaviour with the web
    router.

    - `routers/api/v1/api.go`: add `chi_middleware.GetHead` middleware to
    the API router
    - `tests/integration/api_repo_git_commits_test.go`: add
    `TestAPIReposGitCommitsHEAD` verifying HEAD returns 200 on a valid ref
    and 404 (not 405) on a missing ref

commit ce8cf22af9
Author: bircni <bircni@icloud.com>
Date:   Sun Jun 28 13:37:16 2026 +0200

    fix(actions): don't swallow HTML entities into linkified URLs (#38239)

    In the Actions log viewer, a double-quoted URL renders with a stray
    extra `;` after it.

    Reported in `gitea/runner#1046`

    Remove the buggy AI slop `linkifyURLs` and use new approach to process
    URLs in text

    ---------

    Signed-off-by: wxiaoguang <wxiaoguang@gmail.com>
    Co-authored-by: wxiaoguang <wxiaoguang@gmail.com>

commit 5b9251150c
Author: Lunny Xiao <xiaolunwen@gmail.com>
Date:   Sun Jun 28 03:53:01 2026 -0700

    fix(actions): address workflow status badge review feedback (#38241)

    Follow
    https://github.com/go-gitea/gitea/pull/38196#discussion_r3487219492

    ---------

    Co-authored-by: wxiaoguang <wxiaoguang@gmail.com>
    Co-authored-by: bircni <bircni@icloud.com>

commit 1d43b736b5
Author: bircni <bircni@icloud.com>
Date:   Sun Jun 28 12:25:56 2026 +0200

    fix(actions): deny fork-PR cross-repo access via collaborative owner (#38214)

    `GetActionsUserRepoPermission` (`models/perm/access/repo_permission.go`)
    decides whether an Actions task token may access a target repo. Its
    cross-repo branches each enforce a fork-PR discriminator — except the
    collaborative-owner branch, which was missing the
    `!task.IsForkPullRequest` guard that its sibling
    `checkSameOwnerCrossRepoAccess` has.

    As a result, when a private repo **B** lists owner **A** as a
    collaborative owner, an attacker-controlled fork pull-request workflow
    whose base repo is owned by A was granted code-read on B — i.e. the
    fork's workflow could clone a third private repository it has no rights
    to (read-only confidentiality breach).

    Add the same fork-PR guard the sibling path already enforces:

    ```go
    if taskRepo.IsPrivate && !task.IsForkPullRequest {
        actionsUnit := repo.MustGetUnit(ctx, unit.TypeActions)
        if actionsUnit.ActionsConfig().IsCollaborativeOwner(taskRepo.OwnerID) {
            return maxPerm, nil
        }
    }
    ```

commit f46c9a9769
Author: Zettat123 <zettat123@gmail.com>
Date:   Sun Jun 28 03:31:35 2026 -0600

    feat(actions): support owner-level and global scoped workflows (#38154)

    This PR adds **scoped workflows** to Gitea Actions. Workflows defined
    centrally in a "source" repository that automatically run on every
    repository in scope: an organization's repositories, or (for instance
    admins) every repository on the instance. Each scoped run executes in
    the consuming repository's own context (its runners, secrets, and
    branch) while its content is read from the source repository, so an org
    or instance can mandate shared CI across many repositories without
    copying workflow files into each one.

    An owner or instance admin registers source repositories on a settings
    page and can mark individual workflows as **required**. A required
    scoped workflow cannot be opted out by a consuming repository and gates
    its pull-request merges; an optional one can be disabled per repository.
    Scoped workflows live under a dedicated `SCOPED_WORKFLOW_DIRS` (default
    `.gitea/scoped_workflows`), kept separate from regular `WORKFLOW_DIRS`.
    New `SCOPED_WORKFLOW_DIRS` setting, validated to not overlap with
    `WORKFLOW_DIRS`. Default: `.gitea/scoped_workflows`
    - New `action_scoped_workflow_source` table mapping a registering owner
    (`owner_id`, where `0` = instance-level) to a source repository, with a
    per-workflow `WorkflowConfigs` map.
    - `ActionRun` gains `WorkflowRepoID` / `WorkflowCommitSHA` (the pinned
    content source) and an `IsScopedRun` flag.
    On consumer events, scoped workflows from the effective sources (the
    owner's own sources plus instance-level ones) are matched and turned
    into runs that execute in the consumer's context, with content pinned to
    the source repo's default-branch commit.

    `on: workflow_run` and `on: schedule` are currently not supported.
    A consuming repository can disable an optional scoped workflow (tracked
    separately from regular `DisabledWorkflows`); required scoped workflows
    can never be disabled, opted out, or bypassed.
    A scoped run's status context format is `"<source repo full name>:
    <workflow display name> / <job> (<event>)"`
    (for example: `my-org/scoped-workflows: db-tests / test-sqlite
    (pull_request)`),
    keeping it distinct from a same-named repo-level workflow and from other
    sources.
    Admins mark workflows required and supply status-check patterns.
    `EffectiveRequiredContexts` appends those patterns to the branch
    protection's required contexts and they are matched
    must-present-and-pass. If the status checks from scoped workflows fail,
    the PR cannot be merged.

    NOTE: scoped workflows' required status checks patterns can protect any
    target branch that has a protection rule, even though the rule's "Status
    Check" is disabled. A target branch with no protection rule cannot be
    protected.

    <details>
      <summary>Screenshots</summary>

    <img width="1400" alt="image"
    src="https://github.com/user-attachments/assets/a5d1db33-15ec-487e-93be-2bc04b4e6643"
    />

    </details>
    A scoped workflow's local `uses: ./...` resolves against the source
    repository. `uses:` directory validation honors the
    instance-configurable `WORKFLOW_DIRS` and `SCOPED_WORKFLOW_DIRS`
    (previously hardcoded to `.gitea`/`.github/workflows`).
    `workflow_dispatch` is supported for scoped workflows (web and API),
    resolving inputs/content from the source repo.
    A process-local LRU cache keyed by source repo ID for the per-source
    workflow parse, so instance-level and owner-level sources don't open the
    source repo and parse workflow files on every event.
    Org / user / admin pages to register and remove sources, search
    repositories, and mark workflows required with their status-check
    patterns. The repository Actions sidebar groups scoped workflows by
    source with owner/instance labels and required/disabled badges.

    <details>
      <summary>Screenshots</summary>

    Scoped workflows setting page:

    <img width="1600" alt="image"
    src="https://github.com/user-attachments/assets/9d19f667-97a5-4935-92b2-e53f105e3642"
    />

    Consumer repo's Actions runs list:

    <img width="1600" alt="image"
    src="https://github.com/user-attachments/assets/a77241f9-0aa9-41aa-ba73-12a9a688cb64"
    />

    - `Owner`: this is a owner-level scoped workflows source repo
    - `Global`: this is a global scoped workflows source repo
    - `Required`: this scoped workflow is required, repo admin cannot
    disable it

    </details>

    ---

    Docs: https://gitea.com/gitea/docs/pulls/447

    ---------

    Co-authored-by: bircni <bircni@icloud.com>

commit c9920b7bd0
Author: Lunny Xiao <xiaolunwen@gmail.com>
Date:   Sun Jun 28 01:06:33 2026 -0700

    fix(oauth): restrict introspection to the token's client (#38042)

    Bind OAuth token introspection responses to the authenticated client.
    Return an inactive response when the token grant belongs to a different
    OAuth application to avoid leaking token metadata across clients.

    Add integration coverage for cross-client introspection attempts against
    both access tokens and refresh tokens.

    Assisted-by: GPT-5.4

commit 0319358e5e
Author: bircni <bircni@icloud.com>
Date:   Sun Jun 28 07:58:29 2026 +0200

    fix(web): Correctly align the "disabled" label on larger workflow names (#38240)

commit 9540292596
Author: guanzi008 <245205080@qq.com>
Date:   Sun Jun 28 07:36:45 2026 +0800

    feat(actions): add workflow status badge modal (#38196)

    - Add a Create Status Badge button for selected Actions workflows.
    - Show badge URL, Markdown, and HTML snippets backed by the existing
    workflow badge route.
    <img width="553" height="470" alt="dyn-a5d565ab915b9ffb6c02ac68113494b0"
    src="https://github.com/user-attachments/assets/43b4ceb9-bbd1-4024-b058-d85ec8325e88"
    />
    <img width="349" height="156" alt="grafik"
    src="https://github.com/user-attachments/assets/6eaec62d-ffb0-45c0-b63d-866a41a66005"
    />

    Fixes https://github.com/go-gitea/gitea/issues/31462

    ---------

    Signed-off-by: guanzi008 <245205080@qq.com>
    Co-authored-by: bircni <bircni@icloud.com>

commit d392fb1438
Author: maximilize <3752128+maximilize@users.noreply.github.com>
Date:   Sat Jun 27 22:41:46 2026 +0200

    fix(packages): accept npm "repository" and "bin" in string form (#38236)

    npm allows `repository` and `bin` in `package.json` to be either an
    object or a plain string (npm docs:
    [repository](https://docs.npmjs.com/cli/v11/configuring-npm/package-json#repository),
    [bin](https://docs.npmjs.com/cli/v11/configuring-npm/package-json#bin)).
    The npm registry creator modeled `repository` as a struct and `bin` as
    `map[string]string`, so publishing a package whose `package.json` uses
    the string form failed with:

    ```
    json: cannot unmarshal string into Go struct field PackageMetadataVersion.PackageMetadata.versions.bin of type map[string]string
    ```

    `modules/packages/npm/creator.go`: add `UnmarshalJSON` to `Repository`
    (string → `URL`) and a `Bin` type with `UnmarshalJSON` (string → a
    single command named after the package, per npm semantics), mirroring
    the existing `License` / `User` string-or-object handling. The stored
    `Metadata` field types are unchanged.

    `bundledDependencies` as a boolean (also noted in #38235) is left out of
    scope — it is rare and semantically different (`true` = bundle all
    deps).

    `TestParsePackage/ValidRepositoryAndBinAsString` parses a package with
    string `repository` and `bin`: it fails on `main` with the error above
    and passes with this change. The full `modules/packages/npm` suite is
    green and `gofmt` is clean.

    Fixes #38235

    _AI disclosure: prepared with AI assistance; I reviewed and verified it
    (reproduction + tests) and can explain and defend the change._

commit 0f5102427e
Author: bircni <bircni@icloud.com>
Date:   Sat Jun 27 19:56:12 2026 +0200

    fix(actions): ensure all waiting jobs get runners in large workflows (#38200)

    Fixes two related bugs that cause jobs in large workflows (50+ parallel
    jobs) to never get a runner assigned even though runners are free.

    When N runners all poll `FetchTask` with a stale `tasksVersion`
    simultaneously, they all query the same waiting job list sorted by
    `(updated, id)` and all pick **job #1**. Only one wins the `UPDATE WHERE
    task_id=0` optimistic lock; the rest return empty-handed but still
    receive `latestVersion` in the response. They then consider themselves
    "up to date" and skip `PickTask` on every subsequent poll, leaving jobs

    **Fix:** `CreateTaskForRunner` now iterates through all matching waiting
    jobs. When the optimistic lock fails on job #1, it immediately tries job
    attempt rolls back cleanly before the next candidate is tried.
    `PickTask` no longer wraps this call in an outer `db.WithTx` (which
    caused `halfCommitter` entanglement that prevented per-attempt
    rollbacks).

    `tasks_version` only bumps when a job transitions **to** waiting (new
    workflow triggered, blocked→unblocked). After a runner finishes its
    current task it polls `FetchTask` with `tasksVersion == latestVersion`,
    so the server skips `PickTask` entirely — the remaining 45 waiting jobs
    are invisible to the now-idle runner.

    **Fix:** Also call `IncreaseTaskVersion` in `UpdateRunJob` when a
    (non-reusable-caller) job transitions to a **done** state. Idle runners
    then see a version mismatch on their next poll and attempt `PickTask`,
    picking up the remaining jobs.

commit cbe1b703dc
Author: Lunny Xiao <xiaolunwen@gmail.com>
Date:   Sat Jun 27 10:24:02 2026 -0700

    refactor: Use db.Get[] instead of db.GetEngine(ctx).Get(bean) to avoid zero value fetching wrong database record (#37977)

    This PR replaces a set of struct-based `Get` lookups with explicit
    `db.Get` / `db.Exist` conditions in places where zero-value fields can
    lead to ambiguous matches or incorrect records being returned.

    The main goal is to make read paths deterministic and avoid accidentally
    matching the wrong row when only part of a struct is populated.

    - replace many `db.GetEngine(ctx).Get(bean)` calls with explicit
    `builder.Eq` conditions across models such as actions, admin tasks,
    issues, pull requests, repositories, users, packages, redirects,
    watches, stars, and follows
    - use quoted column names where needed for reserved fields like `index`,
    `type`, and `name`
    - add dedicated user lookup helpers for:
      - primary email
      - OAuth login source / login name
    - update sign-in and OAuth-related flows to use explicit individual-user
    lookups instead of partially populated `User` structs
    - tighten package property and Terraform lock lookups to avoid ambiguous
    reads and updates
    - keep existing fallback behavior where needed, while removing reliance
    on zero-value struct matching

    These changes primarily affect authentication and account lookup paths:

    - email/username sign-in now re-fetches users through explicit keys
    - OAuth2 auto-linking now resolves users by name or primary email
    explicitly
    - OAuth2 login/sync now looks up users by login source, login type, and
    login name explicitly
    - non-individual accounts are no longer implicitly matched through
    partial user lookups in these flows

    This should reduce the risk of incorrect account matches and make query
    behavior more predictable across the codebase.

    ---------

    Co-authored-by: bircni <bircni@icloud.com>

commit d5e6f273f0
Author: bircni <bircni@icloud.com>
Date:   Sat Jun 27 16:50:30 2026 +0200

    fix(migrations): prevent path traversal in repository restore (#38215)

    The repository restorer (`services/migrations/restore.go`) builds
    `file://` URLs for release attachments and PR patches by joining
    user-supplied paths from `release.yml` and `pull_request.yml` onto the
    dump directory:

    ```go
    *asset.DownloadURL = "file://" + filepath.Join(r.baseDir, *asset.DownloadURL)
    pr.PatchURL        = "file://" + filepath.Join(r.baseDir, pr.PatchURL)
    ```

    `filepath.Join` cleans the path, so a crafted relative value such as
    `../../../../etc/passwd` resolves to an absolute path **outside** the
    dump directory. `uri.Open` then reads it via `os.Open` and stores the
    content as a release attachment, which is retrievable through the API —
    an arbitrary file read (Local File Inclusion) from a dump archive
    supplied to `restore-repo`.

    Add a `localFileURL` helper that resolves the relative path against
    `baseDir` and rejects anything that escapes it. Malicious entries are
    skipped with a warning so a legitimate restore still completes; in-dump
    files keep working unchanged.

    ---------

    Co-authored-by: wxiaoguang <wxiaoguang@gmail.com>

commit 15ee850ede
Author: Keshane Gan <keshanegan@gmail.com>
Date:   Sat Jun 27 07:22:40 2026 -0700

    perf(web): sort the action_run query by a repo-scoped index when possible (#38155)

    The `index` column is unique per repo, but the `id` column is scoped to
    the whole table

    https://github.com/go-gitea/gitea/blob/240d0efa7e3860dfde0eb94932287602cbfae533/models/migrations/v1_27/v331.go#L62-L67.

    We have over 60000 action runs in our repo and loading the "Actions" tab
    has been very slow, so scoping the sort to the repo helps it load much
    faster
    Ran tests based on commit 240d0efa7e

    | Case | Run | Duration |
    |------|-----|----------|
    | Before | 1 | 16717.3ms |
    | Before | 2 | 9052.5ms |
    | Before | 3 | 9347.1ms |
    | Before | 4 | 8091.2ms |
    | Before | 5 | 8732.1ms |
    | **Before** | **Median** | **9052.5ms** |
    | After | 1 | 3654.2ms |
    | After | 2 | 287.4ms |
    | After | 3 | 253.6ms |
    | After | 4 | 278.0ms |
    | After | 5 | 313.6ms |
    | **After** | **Median** | **287.4ms** |

    Speedup of 30x on our instance.
    ```log
    2026/06/26 20:33:06 HTTPRequest [W] router: slow      GET /CareHarmony/SymphonyApp/actions for 127.0.0.1:39730, elapsed 3037.6ms @ actions/actions.go:78(actions.List)
    2026/06/26 20:33:08 models/actions/run_list.go:156:GetRunWorkflowIDs() [W] [Slow SQL Query] SELECT DISTINCT `workflow_id` FROM `action_run` WHERE repo_id=? ORDER BY `workflow_id` ASC [29] - 5.069413167s
    2026/06/26 20:33:12 HTTPRequest [I] router: completed GET /.well-known/appspecific/com.chrome.devtools.json for 127.0.0.1:39748, 404 Not Found in 2.1ms @ public/public.go:45(web.registerWebRoutes.(*Router).Group.registerWebRoutes.func19.FileHandlerFunc)
    2026/06/26 20:33:20 models/db/list.go:208:FindAndCount() [W] [Slow SQL Query] SELECT `id`, `title`, `repo_id`, `owner_id`, `workflow_id`, `index`, `trigger_user_id`, `schedule_id`, `ref`, `commit_sha`, `is_fork_pull_request`, `need_approval`, `approved_by`, `event`, `event_payload`, `trigger_event`, `status`, `version`, `raw_concurrency`, `started`, `stopped`, `previous_duration`, `latest_attempt_id`, `created`, `updated` FROM `action_run` WHERE `action_run`.repo_id=? ORDER BY `action_run`.`id` DESC LIMIT 30 [29] - 11.375193667s
    2026/06/26 20:33:20 HTTPRequest [I] router: completed GET /CareHarmony/SymphonyApp/actions for 127.0.0.1:39730, 200 OK in 16717.3ms @ actions/actions.go:78(actions.List)
    2026/06/26 20:33:20 HTTPRequest [I] router: completed GET /.well-known/appspecific/com.chrome.devtools.json for 127.0.0.1:39730, 404 Not Found in 0.9ms @ public/public.go:45(web.registerWebRoutes.(*Router).Group.registerWebRoutes.func19.FileHandlerFunc)
    2026/06/26 20:33:20 HTTPRequest [I] router: completed GET /avatars/4aa9c7878cdb541dbdd37da61a586af554baf6c0930283e0281edf3a366b8c36?size=48 for 127.0.0.1:39730, 200 OK in 1.0ms @ web/base.go:25(avatars)
    2026/06/26 20:33:20 HTTPRequest [I] router: completed GET /assets/site-manifest.json for 127.0.0.1:35914, 200 OK in 0.1ms @ misc/misc.go:23(misc.SiteManifest)
    2026/06/26 20:33:24 HTTPRequest [I] router: polling   GET /user/events for 127.0.0.1:35882, elapsed 3736.2ms @ events/events.go:18(events.Events)
    2026/06/26 20:33:29 HTTPRequest [W] router: slow      GET /CareHarmony/SymphonyApp/actions for 127.0.0.1:35896, elapsed 3542.4ms @ actions/actions.go:78(actions.List)
    2026/06/26 20:33:35 models/db/list.go:208:FindAndCount() [W] [Slow SQL Query] SELECT `id`, `title`, `repo_id`, `owner_id`, `workflow_id`, `index`, `trigger_user_id`, `schedule_id`, `ref`, `commit_sha`, `is_fork_pull_request`, `need_approval`, `approved_by`, `event`, `event_payload`, `trigger_event`, `status`, `version`, `raw_concurrency`, `started`, `stopped`, `previous_duration`, `latest_attempt_id`, `created`, `updated` FROM `action_run` WHERE `action_run`.repo_id=? ORDER BY `action_run`.`id` DESC LIMIT 30 [29] - 8.581414814s
    2026/06/26 20:33:35 HTTPRequest [I] router: completed GET /CareHarmony/SymphonyApp/actions for 127.0.0.1:35896, 200 OK in 9052.5ms @ actions/actions.go:78(actions.List)
    2026/06/26 20:33:35 HTTPRequest [I] router: completed GET /assets/site-manifest.json for 127.0.0.1:35914, 200 OK in 0.2ms @ misc/misc.go:23(misc.SiteManifest)
    2026/06/26 20:33:35 HTTPRequest [I] router: completed GET /.well-known/appspecific/com.chrome.devtools.json for 127.0.0.1:35896, 404 Not Found in 0.9ms @ public/public.go:45(web.registerWebRoutes.(*Router).Group.registerWebRoutes.func19.FileHandlerFunc)
    2026/06/26 20:33:35 HTTPRequest [I] router: completed GET /avatars/4aa9c7878cdb541dbdd37da61a586af554baf6c0930283e0281edf3a366b8c36?size=48 for 127.0.0.1:39748, 200 OK in 1.2ms @ web/base.go:25(avatars)
    2026/06/26 20:33:39 HTTPRequest [I] router: polling   GET /user/events for 127.0.0.1:35874, elapsed 3818.6ms @ events/events.go:18(events.Events)
    2026/06/26 20:34:05 HTTPRequest [W] router: slow      GET /CareHarmony/SymphonyApp/actions for 127.0.0.1:39730, elapsed 3889.5ms @ actions/actions.go:78(actions.List)
    2026/06/26 20:34:11 models/db/list.go:208:FindAndCount() [W] [Slow SQL Query] SELECT `id`, `title`, `repo_id`, `owner_id`, `workflow_id`, `index`, `trigger_user_id`, `schedule_id`, `ref`, `commit_sha`, `is_fork_pull_request`, `need_approval`, `approved_by`, `event`, `event_payload`, `trigger_event`, `status`, `version`, `raw_concurrency`, `started`, `stopped`, `previous_duration`, `latest_attempt_id`, `created`, `updated` FROM `action_run` WHERE `action_run`.repo_id=? ORDER BY `action_run`.`id` DESC LIMIT 30 [29] - 8.861572113s
    2026/06/26 20:34:11 HTTPRequest [I] router: completed GET /CareHarmony/SymphonyApp/actions for 127.0.0.1:39730, 200 OK in 9347.1ms @ actions/actions.go:78(actions.List)
    2026/06/26 20:34:11 HTTPRequest [I] router: completed GET /assets/site-manifest.json for 127.0.0.1:35914, 200 OK in 0.1ms @ misc/misc.go:23(misc.SiteManifest)
    2026/06/26 20:34:11 HTTPRequest [I] router: completed GET /.well-known/appspecific/com.chrome.devtools.json for 127.0.0.1:39730, 404 Not Found in 0.6ms @ public/public.go:45(web.registerWebRoutes.(*Router).Group.registerWebRoutes.func19.FileHandlerFunc)
    2026/06/26 20:34:11 HTTPRequest [I] router: completed GET /avatars/4aa9c7878cdb541dbdd37da61a586af554baf6c0930283e0281edf3a366b8c36?size=48 for 127.0.0.1:39730, 200 OK in 1.3ms @ web/base.go:25(avatars)
    2026/06/26 20:34:18 HTTPRequest [W] router: slow      GET /CareHarmony/SymphonyApp/actions for 127.0.0.1:39748, elapsed 3974.2ms @ actions/actions.go:78(actions.List)
    2026/06/26 20:34:22 models/db/list.go:208:FindAndCount() [W] [Slow SQL Query] SELECT `id`, `title`, `repo_id`, `owner_id`, `workflow_id`, `index`, `trigger_user_id`, `schedule_id`, `ref`, `commit_sha`, `is_fork_pull_request`, `need_approval`, `approved_by`, `event`, `event_payload`, `trigger_event`, `status`, `version`, `raw_concurrency`, `started`, `stopped`, `previous_duration`, `latest_attempt_id`, `created`, `updated` FROM `action_run` WHERE `action_run`.repo_id=? ORDER BY `action_run`.`id` DESC LIMIT 30 [29] - 7.68828429s
    2026/06/26 20:34:22 HTTPRequest [I] router: completed GET /CareHarmony/SymphonyApp/actions for 127.0.0.1:39748, 200 OK in 8091.2ms @ actions/actions.go:78(actions.List)
    2026/06/26 20:34:22 HTTPRequest [I] router: completed GET /assets/site-manifest.json for 127.0.0.1:35914, 200 OK in 0.1ms @ misc/misc.go:23(misc.SiteManifest)
    2026/06/26 20:34:22 HTTPRequest [I] router: completed GET /.well-known/appspecific/com.chrome.devtools.json for 127.0.0.1:39748, 404 Not Found in 0.7ms @ public/public.go:45(web.registerWebRoutes.(*Router).Group.registerWebRoutes.func19.FileHandlerFunc)
    2026/06/26 20:34:23 HTTPRequest [I] router: completed GET /avatars/4aa9c7878cdb541dbdd37da61a586af554baf6c0930283e0281edf3a366b8c36?size=48 for 127.0.0.1:39748, 200 OK in 0.7ms @ web/base.go:25(avatars)
    2026/06/26 20:34:28 HTTPRequest [W] router: slow      GET /CareHarmony/SymphonyApp/actions for 127.0.0.1:34462, elapsed 3193.2ms @ actions/actions.go:78(actions.List)
    2026/06/26 20:34:34 models/db/list.go:208:FindAndCount() [W] [Slow SQL Query] SELECT `id`, `title`, `repo_id`, `owner_id`, `workflow_id`, `index`, `trigger_user_id`, `schedule_id`, `ref`, `commit_sha`, `is_fork_pull_request`, `need_approval`, `approved_by`, `event`, `event_payload`, `trigger_event`, `status`, `version`, `raw_concurrency`, `started`, `stopped`, `previous_duration`, `latest_attempt_id`, `created`, `updated` FROM `action_run` WHERE `action_run`.repo_id=? ORDER BY `action_run`.`id` DESC LIMIT 30 [29] - 8.180339918s
    2026/06/26 20:34:34 HTTPRequest [I] router: completed GET /CareHarmony/SymphonyApp/actions for 127.0.0.1:34462, 200 OK in 8732.1ms @ actions/actions.go:78(actions.List)
    2026/06/26 20:34:34 HTTPRequest [I] router: completed GET /assets/site-manifest.json for 127.0.0.1:35914, 200 OK in 0.1ms @ misc/misc.go:23(misc.SiteManifest)
    2026/06/26 20:34:34 HTTPRequest [I] router: completed GET /.well-known/appspecific/com.chrome.devtools.json for 127.0.0.1:34462, 404 Not Found in 0.8ms @ public/public.go:45(web.registerWebRoutes.(*Router).Group.registerWebRoutes.func19.FileHandlerFunc)
    2026/06/26 20:34:38 HTTPRequest [I] router: polling   GET /user/events for 127.0.0.1:58102, elapsed 3887.7ms @ events/events.go:18(events.Events)
    ```
    ```log
    2026/06/26 21:24:46 HTTPRequest [I] router: completed GET /CareHarmony/SymphonyApp/actions for 127.0.0.1:51940, 200 OK in 3654.2ms @ actions/actions.go:78(actions.List)
    2026/06/26 21:24:46 HTTPRequest [I] router: completed GET /.well-known/appspecific/com.chrome.devtools.json for 127.0.0.1:51954, 404 Not Found in 0.6ms @ public/public.go:45(web.registerWebRoutes.(*Router).Group.registerWebRoutes.func19.FileHandlerFunc)
    2026/06/26 21:24:46 HTTPRequest [I] router: completed GET /avatars/4aa9c7878cdb541dbdd37da61a586af554baf6c0930283e0281edf3a366b8c36?size=48 for 127.0.0.1:51954, 200 OK in 18.0ms @ web/base.go:25(avatars)
    2026/06/26 21:24:47 HTTPRequest [I] router: completed GET /assets/site-manifest.json for 127.0.0.1:48712, 200 OK in 3.6ms @ misc/misc.go:23(misc.SiteManifest)
    2026/06/26 21:24:49 HTTPRequest [I] router: completed GET /CareHarmony/SymphonyApp/actions for 127.0.0.1:51960, 200 OK in 287.4ms @ actions/actions.go:78(actions.List)
    2026/06/26 21:24:49 HTTPRequest [I] router: completed GET /assets/site-manifest.json for 127.0.0.1:48712, 200 OK in 0.1ms @ misc/misc.go:23(misc.SiteManifest)
    2026/06/26 21:24:49 HTTPRequest [I] router: completed GET /.well-known/appspecific/com.chrome.devtools.json for 127.0.0.1:51956, 404 Not Found in 0.9ms @ public/public.go:45(web.registerWebRoutes.(*Router).Group.registerWebRoutes.func19.FileHandlerFunc)
    2026/06/26 21:24:49 HTTPRequest [I] router: completed GET /avatars/4aa9c7878cdb541dbdd37da61a586af554baf6c0930283e0281edf3a366b8c36?size=48 for 127.0.0.1:51960, 200 OK in 0.5ms @ web/base.go:25(avatars)
    2026/06/26 21:24:51 HTTPRequest [I] router: completed GET /CareHarmony/SymphonyApp/actions for 127.0.0.1:51956, 200 OK in 253.6ms @ actions/actions.go:78(actions.List)
    2026/06/26 21:24:51 HTTPRequest [I] router: completed GET /assets/site-manifest.json for 127.0.0.1:48712, 200 OK in 0.1ms @ misc/misc.go:23(misc.SiteManifest)
    2026/06/26 21:24:51 HTTPRequest [I] router: completed GET /.well-known/appspecific/com.chrome.devtools.json for 127.0.0.1:51956, 404 Not Found in 0.6ms @ public/public.go:45(web.registerWebRoutes.(*Router).Group.registerWebRoutes.func19.FileHandlerFunc)
    2026/06/26 21:24:51 HTTPRequest [I] router: completed GET /avatars/4aa9c7878cdb541dbdd37da61a586af554baf6c0930283e0281edf3a366b8c36?size=48 for 127.0.0.1:51960, 200 OK in 1.4ms @ web/base.go:25(avatars)
    2026/06/26 21:24:53 HTTPRequest [I] router: completed GET /CareHarmony/SymphonyApp/actions for 127.0.0.1:48738, 200 OK in 278.0ms @ actions/actions.go:78(actions.List)
    2026/06/26 21:24:53 HTTPRequest [I] router: completed GET /assets/site-manifest.json for 127.0.0.1:48712, 200 OK in 0.1ms @ misc/misc.go:23(misc.SiteManifest)
    2026/06/26 21:24:53 HTTPRequest [I] router: completed GET /.well-known/appspecific/com.chrome.devtools.json for 127.0.0.1:48738, 404 Not Found in 0.8ms @ public/public.go:45(web.registerWebRoutes.(*Router).Group.registerWebRoutes.func19.FileHandlerFunc)
    2026/06/26 21:24:53 HTTPRequest [I] router: completed GET /avatars/4aa9c7878cdb541dbdd37da61a586af554baf6c0930283e0281edf3a366b8c36?size=48 for 127.0.0.1:51960, 200 OK in 0.6ms @ web/base.go:25(avatars)
    2026/06/26 21:24:55 HTTPRequest [I] router: completed GET /CareHarmony/SymphonyApp/actions for 127.0.0.1:48738, 200 OK in 313.6ms @ actions/actions.go:78(actions.List)
    2026/06/26 21:24:55 HTTPRequest [I] router: completed GET /assets/site-manifest.json for 127.0.0.1:48712, 200 OK in 0.1ms @ misc/misc.go:23(misc.SiteManifest)
    2026/06/26 21:24:55 HTTPRequest [I] router: completed GET /.well-known/appspecific/com.chrome.devtools.json for 127.0.0.1:48738, 404 Not Found in 0.8ms @ public/public.go:45(web.registerWebRoutes.(*Router).Group.registerWebRoutes.func19.FileHandlerFunc)
    2026/06/26 21:24:55 HTTPRequest [I] router: completed GET /avatars/4aa9c7878cdb541dbdd37da61a586af554baf6c0930283e0281edf3a366b8c36?size=48 for 127.0.0.1:48738, 200 OK in 0.6ms @ web/base.go:25(avatars)
    2026/06/26 21:24:58 HTTPRequest [I] router: polling   GET /user/events for 127.0.0.1:48738, elapsed 3035.2ms @ events/events.go:18(events.Events)
    ```

    ---------

    Signed-off-by: Keshane Gan <kgan@care-harmony.com>

commit 16c3216dc6
Author: wxiaoguang <wxiaoguang@gmail.com>
Date:   Sat Jun 27 20:09:01 2026 +0800

    fix: js string split (#38233)

    fix #38229

commit b565f3e00a
Author: Giteabot <teabot@gitea.io>
Date:   Sat Jun 27 04:27:56 2026 -0700

    fix(deps): update module golang.org/x/image to v0.43.0 [security] (#38219)

    This PR contains the following updates:

    | Package | Change |
    [Age](https://docs.renovatebot.com/merge-confidence/) |
    [Confidence](https://docs.renovatebot.com/merge-confidence/) |
    |---|---|---|---|
    | [golang.org/x/image](https://pkg.go.dev/golang.org/x/image) |
    [`v0.42.0` →
    `v0.43.0`](https://cs.opensource.google/go/x/image/+/refs/tags/v0.42.0...refs/tags/v0.43.0)
    |
    ![age](https://developer.mend.io/api/mc/badges/age/go/golang.org%2fx%2fimage/v0.43.0?slim=true)
    |
    ![confidence](https://developer.mend.io/api/mc/badges/confidence/go/golang.org%2fx%2fimage/v0.42.0/v0.43.0?slim=true)
    |

    ---
    golang.org/x/image
    [CVE-2026-46601](https://nvd.nist.gov/vuln/detail/CVE-2026-46601) /
    [GO-2026-5061](https://pkg.go.dev/vuln/GO-2026-5061)

    <details>
    <summary>More information</summary>
    The webp decoder can panic when processing a VP8 chunk with dimensions
    that do not match the canvas size.
    Unknown
    - [https://go.dev/cl/787681](https://go.dev/cl/787681)
    - [https://go.dev/issue/79869](https://go.dev/issue/79869)

    This data is provided by
    [OSV](https://osv.dev/vulnerability/GO-2026-5061) and the [Go
    Vulnerability Database](https://redirect.github.com/golang/vulndb)
    ([CC-BY 4.0](https://redirect.github.com/golang/vulndb#license)).
    </details>

    ---
    [CVE-2026-46602](https://nvd.nist.gov/vuln/detail/CVE-2026-46602) /
    [GO-2026-5062](https://pkg.go.dev/vuln/GO-2026-5062)

    <details>
    <summary>More information</summary>
    The TIFF decoder does not set a limit on the size of tiles in tiled
    images, permitting a malicious or corrupt image containing a very large
    tile to cause unbounded memory consumption.
    Unknown
    - [https://go.dev/cl/788422](https://go.dev/cl/788422)
    - [https://go.dev/issue/79905](https://go.dev/issue/79905)

    This data is provided by
    [OSV](https://osv.dev/vulnerability/GO-2026-5062) and the [Go
    Vulnerability Database](https://redirect.github.com/golang/vulndb)
    ([CC-BY 4.0](https://redirect.github.com/golang/vulndb#license)).
    </details>

    ---
    in golang.org/x/image
    [CVE-2026-46604](https://nvd.nist.gov/vuln/detail/CVE-2026-46604) /
    [GO-2026-5066](https://pkg.go.dev/vuln/GO-2026-5066)

    <details>
    <summary>More information</summary>
    The TIFF decoder can panic when decoding an invalid image with an
    out-of-bounds strip offset.
    Unknown
    - [https://go.dev/cl/788421](https://go.dev/cl/788421)
    - [https://go.dev/issue/80122](https://go.dev/issue/80122)

    This data is provided by
    [OSV](https://osv.dev/vulnerability/GO-2026-5066) and the [Go
    Vulnerability Database](https://redirect.github.com/golang/vulndb)
    ([CC-BY 4.0](https://redirect.github.com/golang/vulndb#license)).
    </details>

    ---

    📅 **Schedule**: (UTC)

    - Branch creation
      - ""
    - Automerge
      - At any time (no schedule defined)

    🚦 **Automerge**: Disabled by config. Please merge this manually once you
    are satisfied.

    ♻ **Rebasing**: Whenever PR is behind base branch, or you tick the
    rebase/retry checkbox.

    🔕 **Ignore**: Close this PR and you won't be reminded about this update
    again.

    ---

    - [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check
    this box

    ---

    This PR has been generated by [Mend
    Renovate](https://redirect.github.com/renovatebot/renovate).

    <!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0My4xNDEuNSIsInVwZGF0ZWRJblZlciI6IjQzLjE0MS41IiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6WyJkZXBlbmRlbmNpZXMiXX0=-->

commit 122ebcf0a8
Author: bircni <bircni@icloud.com>
Date:   Fri Jun 26 20:35:13 2026 +0200

    fix(api): deny private org member enumeration via /members (#38213)

commit 1b0992eb2e
Author: Aidan Fahey <afahey2003@yahoo.com>
Date:   Fri Jun 26 12:58:24 2026 -0400

    fix(actions): fix 500 error when canceling a canceling task (#38223)

commit c2f130d352
Author: bircni <bircni@icloud.com>
Date:   Thu Jun 25 14:38:39 2026 +0200

    fix(mssql): convert legacy DATETIME columns to DATETIME2 (#38216)

    On MSSQL databases created by old Gitea versions, the real datetime
    columns `external_login_user.expires_at` and `lfs_lock.created` were
    created as `DATETIME`. `DATETIME` parses datetime literals in a
    locale-dependent way, so the ISO string `'YYYY-MM-DD HH:MM:SS'` that
    xorm sends fails to convert when the session language is not English
    (e.g. German defaults to `dmy`):

    ```
    mssql: Bei der Konvertierung eines nvarchar-Datentyps in einen datetime-Datentyp liegt der Wert außerhalb des gültigen Bereichs.
    ```

    This breaks linking an external (OAuth/Keycloak) account to an existing
    user, and LFS lock creation, with a 500 error.

    Current xorm already maps `time.Time` to the locale-independent
    `DATETIME2` for new installs, so only legacy databases are affected.
    This adds migration `341` that converts these columns to `DATETIME2` on
    legacy MSSQL databases (no-op on other databases and on columns already
    using `DATETIME2`).

    A full audit of persisted `time.Time` columns in `models/` confirmed
    these two are the only real datetime columns affected — every other time
    value is stored as a unix-timestamp integer.

    A regression test (MSSQL-only, mirroring the existing v338 pattern)
    downgrades the columns to legacy `DATETIME`, runs the migration, asserts
    the type becomes `DATETIME2`, and verifies an ISO datetime insert
    succeeds under `SET LANGUAGE German`.

    Fixes #38211

commit 2e1be0b114
Author: Giteabot <teabot@gitea.io>
Date:   Wed Jun 24 14:13:13 2026 -0700

    fix(deps): update npm dependencies (#38203)

    This PR contains the following updates:

    | Package | Change |
    [Age](https://docs.renovatebot.com/merge-confidence/) |
    [Confidence](https://docs.renovatebot.com/merge-confidence/) |
    |---|---|---|---|
    |
    [asciinema-player](https://redirect.github.com/asciinema/asciinema-player)
    | [`3.15.1` →
    `3.16.0`](https://renovatebot.com/diffs/npm/asciinema-player/3.15.1/3.16.0)
    |
    ![age](https://developer.mend.io/api/mc/badges/age/npm/asciinema-player/3.16.0?slim=true)
    |
    ![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/asciinema-player/3.15.1/3.16.0?slim=true)
    |
    |
    [eslint-plugin-sonarjs](https://redirect.github.com/SonarSource/SonarJS/blob/master/packages/analysis/src/jsts/rules/README.md)
    ([source](https://redirect.github.com/SonarSource/SonarJS)) | [`4.0.3` →
    `4.1.0`](https://renovatebot.com/diffs/npm/eslint-plugin-sonarjs/4.0.3/4.1.0)
    |
    ![age](https://developer.mend.io/api/mc/badges/age/npm/eslint-plugin-sonarjs/4.1.0?slim=true)
    |
    ![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/eslint-plugin-sonarjs/4.0.3/4.1.0?slim=true)
    |
    | [happy-dom](https://redirect.github.com/capricorn86/happy-dom) |
    [`20.10.5` →
    `20.10.6`](https://renovatebot.com/diffs/npm/happy-dom/20.10.5/20.10.6)
    |
    ![age](https://developer.mend.io/api/mc/badges/age/npm/happy-dom/20.10.6?slim=true)
    |
    ![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/happy-dom/20.10.5/20.10.6?slim=true)
    |
    | [pnpm](https://pnpm.io)
    ([source](https://redirect.github.com/pnpm/pnpm/tree/HEAD/pnpm)) |
    [`11.7.0` →
    `11.8.0`](https://renovatebot.com/diffs/npm/pnpm/11.7.0/11.8.0) |
    ![age](https://developer.mend.io/api/mc/badges/age/npm/pnpm/11.8.0?slim=true)
    |
    ![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/pnpm/11.7.0/11.8.0?slim=true)
    |

    ---

    <details>
    <summary>asciinema/asciinema-player (asciinema-player)</summary>
    [`v3.16.0`](https://redirect.github.com/asciinema/asciinema-player/releases/tag/v3.16.0):
    3.16.0

    [Compare
    Source](https://redirect.github.com/asciinema/asciinema-player/compare/v3.15.1...v3.16.0)

    This is a significant release, with a new keystroke overlay and major
    improvements to recording playback.

    Notable changes:

    - New optional keystroke overlay, toggled with the `k` key
    - New `cursorMode` option: `"blinking"`, `"steady"` or `"hidden"`
    - TypeScript definitions included in the npm package
    - More reliable loading, playback, seeking, stepping and looping
    - Recording load failures are now emitted via the `error` event
    - Audio loading failures no longer prevent recording playback
    - Improved rendering of Powerline and box-drawing symbols
    - Improved accessibility of control bar buttons
    - Standalone bundle is now compatible with LibreJS

    The new
    [`keystrokeOverlay`](https://docs.asciinema.org/manual/player/options/#keystrokeoverlay)
    option displays keys pressed during a recording:

    ```javascript
    AsciinemaPlayer.create("/demo.cast", document.getElementById("demo"), {
      keystrokeOverlay: true
    });
    ```

    Recent keystrokes are shown in the lower-right corner. Consecutive text
    input is grouped, while repeated special keys use a counter, such as
    `Ret × 3`.

    The overlay is disabled by default and can be toggled during playback
    with the `k` key. It requires a recording containing input events
    (`asciinema rec --capture-input ...`).

    Demo:

    [![asciicast](https://asciinema.org/a/1258082.svg)](https://asciinema.org/a/1258082)

    The new
    [`cursorMode`](https://docs.asciinema.org/manual/player/options/#cursormode)
    option controls cursor visibility:

    ```javascript
    AsciinemaPlayer.create("/demo.cast", document.getElementById("demo"), {
      cursorMode: "steady"
    });
    ```

    Supported modes are `"blinking"` (the default), `"steady"` and
    `"hidden"`.

    The recording playback engine has been significantly reworked. This
    fixes several edge cases involving reverse stepping, marker pauses,
    looping, seeking, posters and audio playback.

    Missing or invalid audio now falls back to terminal-only playback. Fatal
    recording load errors are emitted through the new
    [`error`](https://docs.asciinema.org/manual/player/api/#error-event)
    event.

    `getCurrentTime()` and `getDuration()` now return their values directly,
    as documented.

    The npm package now includes TypeScript definitions for the player API,
    options, recording sources, parsers and events.

    </details>

    <details>
    <summary>SonarSource/SonarJS (eslint-plugin-sonarjs)</summary>
    [`v4.1.0`](https://redirect.github.com/SonarSource/SonarJS/compare/93ac7229b60beb637a7d91644c086f3b854072d9...4ce51a6eec04a87ee57b30792c3103823aad5bdb)

    [Compare
    Source](https://redirect.github.com/SonarSource/SonarJS/compare/93ac7229b60beb637a7d91644c086f3b854072d9...4ce51a6eec04a87ee57b30792c3103823aad5bdb)

    </details>

    <details>
    <summary>capricorn86/happy-dom (happy-dom)</summary>
    [`v20.10.6`](https://redirect.github.com/capricorn86/happy-dom/releases/tag/v20.10.6)

    [Compare
    Source](https://redirect.github.com/capricorn86/happy-dom/compare/v20.10.5...v20.10.6)

    - Await NodeJS internal ReadableStream promise during teardown - By
    **[@&#8203;capricorn86](https://redirect.github.com/capricorn86)** in
    task
    [#&#8203;2217](https://redirect.github.com/capricorn86/happy-dom/issues/2217)

    </details>

    <details>
    <summary>pnpm/pnpm (pnpm)</summary>
    [`v11.8.0`](https://redirect.github.com/pnpm/pnpm/releases/tag/v11.8.0):
    pnpm 11.8

    [Compare
    Source](https://redirect.github.com/pnpm/pnpm/compare/v11.7.0...v11.8.0)

    - [`c112b61`](https://redirect.github.com/pnpm/pnpm/commit/c112b61):
    Added a `--dry-run` option to `pnpm install`. It runs a full dependency
    resolution and reports what an install would change, but writes nothing
    to disk (no lockfile, no `node_modules`) and always exits with code 0.
    This mirrors the preview semantics of `npm install --dry-run`
    [#&#8203;7340](https://redirect.github.com/pnpm/pnpm/issues/7340).
    - [`179ebc4`](https://redirect.github.com/pnpm/pnpm/commit/179ebc4):
    `pnpm run --no-bail` now exits with a non-zero exit code when any of the
    executed scripts fail, while still running every matched script to
    completion. This makes the exit-code behavior of `--no-bail` consistent
    between recursive and non-recursive runs (recursive runs already failed
    at the end). Previously, a non-recursive `pnpm run --no-bail` always
    exited with code 0, even when a script failed
    [#&#8203;8013](https://redirect.github.com/pnpm/pnpm/issues/8013).
    - [`0474a9c`](https://redirect.github.com/pnpm/pnpm/commit/0474a9c):
    Added support for generating Node.js package maps at
    `node_modules/.package-map.json` during isolated and hoisted installs.
    Added the `node-experimental-package-map` setting to inject the
    generated map into pnpm-managed Node.js script environments, and the
    `node-package-map-type` setting to choose between `standard` and `loose`
    package maps.
    - [`dcededc`](https://redirect.github.com/pnpm/pnpm/commit/dcededc):
    `pnpm sbom` now marks components reachable only through
    `devDependencies` with CycloneDX `scope: "excluded"` and the
    `cdx:npm:package:development` property. The `excluded` scope documents
    "component usage for test and other non-runtime purposes", which matches
    the semantics of a devDependency; the property is the CycloneDX
    npm-taxonomy marker emitted by `@cyclonedx/cyclonedx-npm`, so both
    modern (scope) and existing (property) consumers are covered. Components
    reachable at runtime (including installed `optionalDependencies`) omit
    `scope` and default to `required`.
    - [`1495cb0`](https://redirect.github.com/pnpm/pnpm/commit/1495cb0):
    Added per-package SBOM generation with `--out` and `--split` flags. Use
    `--out out/%s.cdx.json` to write one SBOM per workspace package to
    individual files, or `--split` for NDJSON output to stdout. When
    `--filter` selects a single package, the SBOM root component now uses
    that package's metadata. Workspace inter-dependencies (`workspace:`
    protocol) and their transitive dependencies are included. Author,
    repository, and license fall back to the root manifest when the package
    doesn't define them.
    - [`293921a`](https://redirect.github.com/pnpm/pnpm/commit/293921a):
    feat(view): support searching project manifest upward when package name
    is omitted

    When running `pnpm view` without a package name, the command now
    searches
    upward for the nearest project manifest (`package.json`, `package.yaml`,
    or `package.json5`) and uses its `name` field.
      If the manifest exists but lacks a `name` field, an error is thrown.

      This change also replaces the `find-up` dependency with `empathic` for
      improved performance and consistency across workspace tools.

    - [`29ab905`](https://redirect.github.com/pnpm/pnpm/commit/29ab905):
    Fixed `pnpm update` overriding the version range policy of a named
    catalog whose name parses as a version (e.g. `catalog:express4-21`). The
    `catalog:` reference carries no pinning of its own, so the prefix from
    the catalog entry (such as `~`) is now preserved instead of being
    widened to `^`
    [#&#8203;10321](https://redirect.github.com/pnpm/pnpm/issues/10321).

    - [`bee4bf4`](https://redirect.github.com/pnpm/pnpm/commit/bee4bf4):
    Security: validate config dependency names and versions from the env
    lockfile (`pnpm-lock.yaml`) before using them to build filesystem paths.
    A committed lockfile with a traversal-shaped `configDependencies` name
    (such as `../../PWNED`) or version (such as `../../../PWNED`) could
    previously cause `pnpm install` to create symlinks or write package
    files outside `node_modules/.pnpm-config` and the store. Names must now
    be valid npm package names and versions must be exact semver versions;
    the same validation is applied to optional subdependencies of config
    dependencies, and to the legacy workspace-manifest format before any
    lockfile is written. See
    [GHSA-qrv3-253h-g69c](https://redirect.github.com/pnpm/pnpm/security/advisories/GHSA-qrv3-253h-g69c).

    - [`96bdd57`](https://redirect.github.com/pnpm/pnpm/commit/96bdd57): Fix
    `link:` workspace protocol switching to `file:` after `pnpm rm` is run
    from inside a workspace package whose target workspace dependency has
    its own dependencies, when `injectWorkspacePackages: true` is set.
    Follow-up to
    [#&#8203;10575](https://redirect.github.com/pnpm/pnpm/pull/10575), which
    fixed the same symptom for workspace packages without dependencies.

    - [`302a2f7`](https://redirect.github.com/pnpm/pnpm/commit/302a2f7): No
    longer warn about using both `packageManager` and
    `devEngines.packageManager` when the two fields pin the same package
    manager at the same version with the same integrity hash (e.g. both
    `pnpm@11.5.1+sha512.…`). Previously the hash was stripped from the
    legacy `packageManager` field but not from `devEngines.packageManager`,
    so even identical specifications looked like a mismatch
    [#&#8203;12028](https://redirect.github.com/pnpm/pnpm/issues/12028).

    The warning still fires on any genuine divergence, and several cases now
    state the specific reason instead of a single generic message: a
    different package manager, a different version, or contradictory
    integrity hashes for the same version.

    - [`3f0fb21`](https://redirect.github.com/pnpm/pnpm/commit/3f0fb21):
    Fixed the progress line showing leftover characters from external
    processes that write to the terminal between progress updates (e.g. an
    SSH passphrase prompt would leave a fragment like `added 0sa':`). The
    interactive reporter now redraws each frame in place, erasing to the end
    of the display before reprinting, so any such remnants are cleared
    [#&#8203;12350](https://redirect.github.com/pnpm/pnpm/issues/12350).

    - [`564619f`](https://redirect.github.com/pnpm/pnpm/commit/564619f):
    Fixed `pnpm approve-builds` reporting "no packages awaiting approval"
    when a build-script dependency whose approval was revoked (e.g. after
    `git stash` drops the `allowBuilds` from `pnpm-workspace.yaml`) is
    re-added. The revoked packages are now correctly recorded in
    `.modules.yaml` so `approve-builds` can find them.
    [#&#8203;12221](https://redirect.github.com/pnpm/pnpm/issues/12221)

    - [`3d1fd20`](https://redirect.github.com/pnpm/pnpm/commit/3d1fd20):
    Skip the redundant "target bin directory already contains an exe called
    node" warning on Windows when the existing `node.exe` already matches
    the target (same hard link or identical content)
    [pnpm/pnpm#12203](https://redirect.github.com/pnpm/pnpm/issues/12203).

    - [`1b02b47`](https://redirect.github.com/pnpm/pnpm/commit/1b02b47): Fix
    macOS Gatekeeper blocking native binaries (`.node`, `.dylib`, `.so`) by
    removing the `com.apple.quarantine` extended attribute after importing
    them from the store.

    When pnpm imports files from its content-addressable store into
    `node_modules`, macOS preserves extended attributes, including
    `com.apple.quarantine`. If this xattr is present on a store blob (e.g.
    it was first written under a Gatekeeper-enabled app such as a Git
    client), it propagates to `node_modules`, and Gatekeeper blocks the
    native binary from loading even though pnpm already verified the file's
    integrity against the lockfile.

    After importing a package, pnpm now strips `com.apple.quarantine` from
    its native binaries, matching Homebrew's behaviour of dropping
    quarantine from verified downloads. The cleanup is macOS-only, runs in a
    single batched `xattr` call per package, is restricted to native
    binaries (other files are untouched), and is non-fatal (it logs a
    warning on unexpected errors).

    Fixes
    [#&#8203;11056](https://redirect.github.com/pnpm/pnpm/issues/11056)

    - [`61969fb`](https://redirect.github.com/pnpm/pnpm/commit/61969fb): Fix
    `pnpm install` with `optimisticRepeatInstall` incorrectly reporting
    `Already up to date` when `pnpm-lock.yaml` changed but project manifests
    did not. This affected workflows such as checking out or restoring only
    the lockfile
    [#&#8203;12100](https://redirect.github.com/pnpm/pnpm/issues/12100).

    Also fixes `checkDepsStatus` to use the correct lockfile path when
    `useGitBranchLockfile` is enabled, so the optimistic fast-path and
    lockfile modification detection work with `pnpm-lock.<branch>.yaml`
    files instead of always stat'ing `pnpm-lock.yaml`. Merge-conflict
    detection now reads the resolved lockfile name as well, and with
    `mergeGitBranchLockfiles` enabled every `pnpm-lock.*.yaml` is scanned
    for modifications and conflicts. The git branch is now resolved by
    reading `.git/HEAD` directly (no process spawn) and uses the workspace
    directory rather than `process.cwd()`.

    - [`5c12968`](https://redirect.github.com/pnpm/pnpm/commit/5c12968): Fix
    recursive updates of transitive dependencies when the update command
    mixes transitive dependency patterns with direct dependency selectors.
    For example, `pnpm up -r "@&#8203;babel/core" uuid` now updates matching
    transitive `@babel/core` dependencies even when `uuid` is a direct
    dependency selector
    [#&#8203;12103](https://redirect.github.com/pnpm/pnpm/issues/12103).

    - [`9d79ba1`](https://redirect.github.com/pnpm/pnpm/commit/9d79ba1):
    Register the `pnpm update --no-save` flag in the CLI help and option
    parser.

    - [`0474a9c`](https://redirect.github.com/pnpm/pnpm/commit/0474a9c):
    Fixed `pnpm import` for Yarn v2 lockfiles when `js-yaml` v4 is
    installed.

    - [`9e0c375`](https://redirect.github.com/pnpm/pnpm/commit/9e0c375):
    Fixed `pnpm install` repeatedly prompting to remove and reinstall
    `node_modules` in a workspace package when `enableGlobalVirtualStore` is
    enabled. The post-install build step recorded a per-project
    `node_modules/.pnpm` virtual store directory in
    `node_modules/.modules.yaml`, overwriting the global `<storeDir>/links`
    value the install step had written. The next install then detected a
    virtual-store mismatch (`ERR_PNPM_UNEXPECTED_VIRTUAL_STORE`). The build
    step now derives the same global virtual store directory as the install
    step
    [#&#8203;12307](https://redirect.github.com/pnpm/pnpm/issues/12307).

    - [`223d060`](https://redirect.github.com/pnpm/pnpm/commit/223d060):
    Document the `--cpu`, `--os` and `--libc` flags in the output of `pnpm
    install --help`. These flags were already supported but were only
    documented on the website
    [#&#8203;12359](https://redirect.github.com/pnpm/pnpm/issues/12359).

    - [`e85aea2`](https://redirect.github.com/pnpm/pnpm/commit/e85aea2):
    Avoid reading `README.md` from disk when publishing if the publish
    manifest already provides a `readme` field. The README is now only read
    lazily, inside `createExportableManifest`, when it is actually needed.

    - [`3188ae7`](https://redirect.github.com/pnpm/pnpm/commit/3188ae7):
    Fixed `pnpm peers check` to accept loose peer dependency ranges such as
    `>=3.16.0 || >=4.0.0-` when the installed peer version satisfies the
    range
    [#&#8203;12149](https://redirect.github.com/pnpm/pnpm/issues/12149).

    - [`531f2a3`](https://redirect.github.com/pnpm/pnpm/commit/531f2a3):
    Fixed `pnpm update` rewriting a `workspace:` dependency that points at a
    local path (e.g. `workspace:../packages/foo/dist`) into a normalized
    `link:` or version-range specifier. Such specifiers are now preserved
    verbatim when the workspace protocol is preserved
    [#&#8203;3902](https://redirect.github.com/pnpm/pnpm/issues/3902).

    - [`fe66535`](https://redirect.github.com/pnpm/pnpm/commit/fe66535):
    Fixed a lockfile non-convergence bug where an incremental install kept a
    duplicate transitive dependency that a fresh install would not produce.
    When a package is reused from the lockfile, its child edges are taken
    verbatim and bypass the preferred-versions walk, so a transitive
    dependency could stay pinned to an older version even after a direct
    dependency resolved to a higher version that satisfies the same range.
    The resolver now refreshes such a stale pin to the higher
    direct-dependency version during resolution — so the older version is
    never resolved or fetched, and the incremental result converges to the
    fresh one.

    - [`6d35338`](https://redirect.github.com/pnpm/pnpm/commit/6d35338):
    `pnpm install` detects changes inside local file dependencies again. The
    optimistic repeat-install fast path only tracks manifest and lockfile
    modification times, so edits inside a local dependency's directory (or a
    repacked local tarball) were reported as "Already up to date". Projects
    with local file dependencies (`file:` and bare local path or tarball
    specifiers, declared directly or through `pnpm.overrides`) now always
    run a full install, which refetches those dependencies, matching pnpm
    v10 behavior
    [#&#8203;11795](https://redirect.github.com/pnpm/pnpm/issues/11795).

    - [`4ca9247`](https://redirect.github.com/pnpm/pnpm/commit/4ca9247):
    Preserve the existing Node.js runtime version prefix when resolving
    `node@runtime:<range>` to a concrete version.

    - [`30c7590`](https://redirect.github.com/pnpm/pnpm/commit/30c7590):
    Create shorter CAFS temporary package directories to leave room for
    lifecycle scripts that create IPC socket paths under TMPDIR.

    - [`13815ad`](https://redirect.github.com/pnpm/pnpm/commit/13815ad):
    Reporter output (warnings, progress) for `pnpm store` and `pnpm config`
    subcommands now goes to stderr instead of stdout. This fixes scripts
    that capture their stdout (e.g. `PNPM_STORE=$(pnpm store path)`, `pnpm
    config list --json | jq`) from getting warnings mixed into the result.

    - [`1c05876`](https://redirect.github.com/pnpm/pnpm/commit/1c05876):
    Avoid relinking unchanged child dependencies and remove stale child
    links during warm installs.

    - [`817f99d`](https://redirect.github.com/pnpm/pnpm/commit/817f99d):
    Fixed lockfile churn where a package's `transitivePeerDependencies`
    could be dropped (and shift between packages) when the package
    participates in a dependency cycle. A cycle re-entry resolves against
    truncated children, so it must not be cached as "pure"; otherwise
    sibling occurrences of the same package short-circuit and lose
    transitive peers depending on traversal order
    [#&#8203;5108](https://redirect.github.com/pnpm/pnpm/issues/5108).

    - [`eba03e0`](https://redirect.github.com/pnpm/pnpm/commit/eba03e0): Fix
    `pnpm install` reporting "Already up to date" after a catalog entry in
    `pnpm-workspace.yaml` was reverted to a previous version. After an
    update modified a catalog, the workspace state cache stored the
    pre-update catalog versions, so reverting the entry back to its original
    version was not detected as an outdated state
    [#&#8203;12418](https://redirect.github.com/pnpm/pnpm/issues/12418).

    - [`3b54d79`](https://redirect.github.com/pnpm/pnpm/commit/3b54d79):
    `pnpm update` now keeps lockfile `overrides` that resolve through a
    catalog in sync with the catalog. Previously, when an override
    referenced a catalog (e.g. `overrides: { foo: 'catalog:' }`) and `pnpm
    update` bumped that catalog entry, the lockfile's `catalogs` advanced
    while the resolved `overrides` kept the old version. The resulting
    lockfile was internally inconsistent, so a later `pnpm install
    --frozen-lockfile` failed with `ERR_PNPM_LOCKFILE_CONFIG_MISMATCH`.

    - [`9d0a300`](https://redirect.github.com/pnpm/pnpm/commit/9d0a300):
    Fixed `pnpm version --recursive` so it honors the workspace selection.
    In recursive mode the version bump now applies to the packages resolved
    from the workspace filter (`selectedProjectsGraph`), matching the
    behavior of `pnpm publish --recursive`, instead of always bumping every
    workspace package
    [#&#8203;11348](https://redirect.github.com/pnpm/pnpm/issues/11348).

    <!-- sponsors -->

    <table>
      <tbody>
        <tr>
          <td align="center" valign="middle">
    <a href="https://bit.cloud/?utm_source=pnpm&utm_medium=release_notes"
    target="_blank" rel="noopener noreferrer"><img
    src="https://pnpm.io/img/users/bit.svg" width="80" alt="Bit"></a>
          </td>
        </tr>
        <tr>
          <td align="center" valign="middle">
    <a href="https://openai.com/?utm_source=pnpm&utm_medium=release_notes"
    target="_blank" rel="noopener noreferrer">
              <picture>
    <source media="(prefers-color-scheme: light)"
    srcset="https://pnpm.io/img/users/openai_dark.svg" />
    <source media="(prefers-color-scheme: dark)"
    srcset="https://pnpm.io/img/users/openai_light.svg" />
    <img src="https://pnpm.io/img/users/openai_dark.svg" width="160"
    alt="OpenAI" />
              </picture>
            </a>
          </td>
        </tr>
      </tbody>
    </table>

    <table>
      <tbody>
        <tr>
          <td align="center" valign="middle">
    <a href="https://sanity.io/?utm_source=pnpm&utm_medium=release_notes"
    target="_blank" rel="noopener noreferrer">
              <picture>
    <source media="(prefers-color-scheme: light)"
    srcset="https://pnpm.io/img/users/sanity.svg" />
    <source media="(prefers-color-scheme: dark)"
    srcset="https://pnpm.io/img/users/sanity_light.svg" />
    <img src="https://pnpm.io/img/users/sanity.svg" width="120" alt="Sanity"
    />
              </picture>
            </a>
          </td>
          <td align="center" valign="middle">
    <a href="https://discord.com/?utm_source=pnpm&utm_medium=release_notes"
    target="_blank" rel="noopener noreferrer">
              <picture>
    <source media="(prefers-color-scheme: light)"
    srcset="https://pnpm.io/img/users/discord.svg" />
    <source media="(prefers-color-scheme: dark)"
    srcset="https://pnpm.io/img/users/discord_light.svg" />
    <img src="https://pnpm.io/img/users/discord.svg" width="220"
    alt="Discord" />
              </picture>
            </a>
          </td>
          <td align="center" valign="middle">
    <a href="https://vite.dev/?utm_source=pnpm&utm_medium=release_notes"
    target="_blank" rel="noopener noreferrer"><img
    src="https://pnpm.io/img/users/vitejs.svg" width="42" alt="Vite"></a>
          </td>
        </tr>
        <tr>
          <td align="center" valign="middle">
    <a href="https://serpapi.com/?utm_source=pnpm&utm_medium=release_notes"
    target="_blank" rel="noopener noreferrer">
              <picture>
    <source media="(prefers-color-scheme: light)"
    srcset="https://pnpm.io/img/users/serpapi_dark.svg" />
    <source media="(prefers-color-scheme: dark)"
    srcset="https://pnpm.io/img/users/serpapi_light.svg" />
    <img src="https://pnpm.io/img/users/serpapi_dark.svg" width="160"
    alt="SerpApi" />
              </picture>
            </a>
          </td>
          <td align="center" valign="middle">
    <a
    href="https://coderabbit.ai/?utm_source=pnpm&utm_medium=release_notes"
    target="_blank" rel="noopener noreferrer">
              <picture>
    <source media="(prefers-color-scheme: light)"
    srcset="https://pnpm.io/img/users/coderabbit.svg" />
    <source media="(prefers-color-scheme: dark)"
    srcset="https://pnpm.io/img/users/coderabbit_light.svg" />
    <img src="https://pnpm.io/img/users/coderabbit.svg" width="220"
    alt="CodeRabbit" />
              </picture>
            </a>
          </td>
          <td align="center" valign="middle">
    <a
    href="https://stackblitz.com/?utm_source=pnpm&utm_medium=release_notes"
    target="_blank" rel="noopener noreferrer">
              <picture>
    <source media="(prefers-color-scheme: light)"
    srcset="https://pnpm.io/img/users/stackblitz.svg" />
    <source media="(prefers-color-scheme: dark)"
    srcset="https://pnpm.io/img/users/stackblitz_light.svg" />
    <img src="https://pnpm.io/img/users/stackblitz.svg" width="190"
    alt="Stackblitz" />
              </picture>
            </a>
          </td>
        </tr>
        <tr>
          <td align="center" valign="middle">
    <a href="https://workleap.com/?utm_source=pnpm&utm_medium=release_notes"
    target="_blank" rel="noopener noreferrer">
              <picture>
    <source media="(prefers-color-scheme: light)"
    srcset="https://pnpm.io/img/users/workleap.svg" />
    <source media="(prefers-color-scheme: dark)"
    srcset="https://pnpm.io/img/users/workleap_light.svg" />
    <img src="https://pnpm.io/img/users/workleap.svg" width="190"
    alt="Workleap" />
              </picture>
            </a>
          </td>
          <td align="center" valign="middle">
    <a href="https://nx.dev/?utm_source=pnpm&utm_medium=release_notes"
    target="_blank" rel="noopener noreferrer">
              <picture>
    <source media="(prefers-color-scheme: light)"
    srcset="https://pnpm.io/img/users/nx.svg" />
    <source media="(prefers-color-scheme: dark)"
    srcset="https://pnpm.io/img/users/nx_light.svg" />
    <img src="https://pnpm.io/img/users/nx.svg" width="50" alt="Nx" />
              </picture>
            </a>
          </td>
        </tr>
      </tbody>
    </table>

    <!-- sponsors end -->

    </details>

    ---

    📅 **Schedule**: (UTC)

    - Branch creation
      - Only on Monday (`* * * * 1`)
    - Automerge
      - At any time (no schedule defined)

    🚦 **Automerge**: Disabled by config. Please merge this manually once you
    are satisfied.

    ♻ **Rebasing**: Whenever PR is behind base branch, or you tick the
    rebase/retry checkbox.

    👻 **Immortal**: This PR will be recreated if closed unmerged. Get
    [config
    help](https://redirect.github.com/renovatebot/renovate/discussions) if
    that's undesired.

    ---

    - [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check
    this box

    ---

    This PR has been generated by [Mend
    Renovate](https://redirect.github.com/renovatebot/renovate).

    <!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0My4xNDEuNSIsInVwZGF0ZWRJblZlciI6IjQzLjE0MS41IiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6WyJkZXBlbmRlbmNpZXMiXX0=-->

    ---------

    Co-authored-by: wxiaoguang <wxiaoguang@gmail.com>

commit ef927f9fa3
Author: Eyüp Can Akman <eyupcanakman@gmail.com>
Date:   Wed Jun 24 08:38:02 2026 +0300

    feat(api): support ref suffixes in compare (#38148)

    Compare API requests with a `^` or `~N` revision suffix (for example
    `compare/main...feature^`) were rejected with `400 Unsupported
    comparison syntax: ref with suffix`. The fix resolves the suffix to a
    commit before comparing, so `base...head^` and `~N` work on either side,
    the same as git.

    Only `^`/`~N` navigation is resolved. Pull request creation still
    requires plain branch refs, and the web compare page keeps rejecting
    suffixes since its branch selectors need separate UI work.

    Closes #33943

commit 59d4825a95
Author: Giteabot <teabot@gitea.io>
Date:   Tue Jun 23 01:25:02 2026 -0700

    chore(deps): update module golang.org/x/vuln to v1.4.0 (#38201)

commit 10da460c1b
Author: GiteaBot <teabot@gitea.io>
Date:   Tue Jun 23 01:11:28 2026 +0000

    [skip ci] Updated translations via Crowdin

commit 2003cf4e87
Author: Giteabot <teabot@gitea.io>
Date:   Mon Jun 22 13:46:55 2026 -0700

    chore(deps): update actions/checkout action to v7 (#38199)

commit 736ab982c8
Author: Royce Remer <royceremer@gmail.com>
Date:   Mon Jun 22 11:29:06 2026 -0700

    enhance: allow builtin default git config options to be overridden (#38172)

    This is really a follow-up to
    [#38148](https://github.com/go-gitea/gitea/pull/35305) , instead of
    having specific mappings of options for git configurations, just honor
    any user-provided gitconfig. I include a test which points out the
    specific config I have which was previously not honored, but more
    generally this means that gitea now only *adds* new gitconfig and never
    overwrites any config provided under `[git.config]`.

    ---------

    Signed-off-by: Royce Remer <royceremer@gmail.com>
    Co-authored-by: wxiaoguang <wxiaoguang@gmail.com>

commit 08a18d36a6
Author: GiteaBot <teabot@gitea.io>
Date:   Mon Jun 22 17:52:08 2026 +0000

    [skip ci] Updated translations via Crowdin

commit 8a6697123f
Author: Giteabot <teabot@gitea.io>
Date:   Mon Jun 22 02:23:46 2026 -0700

    chore(deps): update action dependencies (#38191)

    This PR contains the following updates:

    | Package | Type | Update | Change |
    |---|---|---|---|
    |
    [crowdin/github-action](https://redirect.github.com/crowdin/github-action)
    | action | patch | `v2.16.2` → `v2.16.3` |
    | [pnpm/action-setup](https://redirect.github.com/pnpm/action-setup) |
    action | patch | `v6.0.8` → `v6.0.9` |

    ---

    <details>
    <summary>crowdin/github-action (crowdin/github-action)</summary>
    [`v2.16.3`](https://redirect.github.com/crowdin/github-action/releases/tag/v2.16.3)

    [Compare
    Source](https://redirect.github.com/crowdin/github-action/compare/v2.16.2...v2.16.3)

    - CLI
    [4.14.3](https://redirect.github.com/crowdin/crowdin-cli/releases/tag/4.14.3)
    by [@&#8203;andrii-bodnar](https://redirect.github.com/andrii-bodnar)

    **Full Changelog**:
    <https://github.com/crowdin/github-action/compare/v2.16.2...v2.16.3>

    </details>

    <details>
    <summary>pnpm/action-setup (pnpm/action-setup)</summary>
    [`v6.0.9`](https://redirect.github.com/pnpm/action-setup/releases/tag/v6.0.9)

    [Compare
    Source](https://redirect.github.com/pnpm/action-setup/compare/v6.0.8...v6.0.9)

    - fix: update pnpm to v11.7.0 by
    [@&#8203;zkochan](https://redirect.github.com/zkochan) in
    [#&#8203;267](https://redirect.github.com/pnpm/action-setup/pull/267)

    **Full Changelog**:
    <https://github.com/pnpm/action-setup/compare/v6...v6.0.9>

    </details>

    ---

    📅 **Schedule**: (UTC)

    - Branch creation
      - Only on Monday (`* * * * 1`)
    - Automerge
      - At any time (no schedule defined)

    🚦 **Automerge**: Disabled by config. Please merge this manually once you
    are satisfied.

    ♻ **Rebasing**: Whenever PR is behind base branch, or you tick the
    rebase/retry checkbox.

    👻 **Immortal**: This PR will be recreated if closed unmerged. Get
    [config
    help](https://redirect.github.com/renovatebot/renovate/discussions) if
    that's undesired.

    ---

    - [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check
    this box

    ---

    This PR has been generated by [Mend
    Renovate](https://redirect.github.com/renovatebot/renovate).

    <!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0My4xNDEuNSIsInVwZGF0ZWRJblZlciI6IjQzLjE0MS41IiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6WyJkZXBlbmRlbmNpZXMiXX0=-->

    Co-authored-by: bircni <bircni@icloud.com>

commit 2cd4506120
Author: Giteabot <teabot@gitea.io>
Date:   Mon Jun 22 01:39:44 2026 -0700

    fix(deps): update npm dependencies (#38193)

    This PR contains the following updates:

    | Package | Change |
    [Age](https://docs.renovatebot.com/merge-confidence/) |
    [Confidence](https://docs.renovatebot.com/merge-confidence/) |
    |---|---|---|---|
    | @&#8203;codemirror/search | [`6.7.0` →
    `6.7.1`](https://renovatebot.com/diffs/npm/@codemirror%2fsearch/6.7.0/6.7.1)
    |
    ![age](https://developer.mend.io/api/mc/badges/age/npm/@codemirror%2fsearch/6.7.1?slim=true)
    |
    ![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/@codemirror%2fsearch/6.7.0/6.7.1?slim=true)
    |
    | [@playwright/test](https://playwright.dev)
    ([source](https://redirect.github.com/microsoft/playwright)) | [`1.60.0`
    →
    `1.61.0`](https://renovatebot.com/diffs/npm/@playwright%2ftest/1.60.0/1.61.0)
    |
    ![age](https://developer.mend.io/api/mc/badges/age/npm/@playwright%2ftest/1.61.0?slim=true)
    |
    ![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/@playwright%2ftest/1.60.0/1.61.0?slim=true)
    |
    | [happy-dom](https://redirect.github.com/capricorn86/happy-dom) |
    [`20.10.2` →
    `20.10.5`](https://renovatebot.com/diffs/npm/happy-dom/20.10.2/20.10.5)
    |
    ![age](https://developer.mend.io/api/mc/badges/age/npm/happy-dom/20.10.5?slim=true)
    |
    ![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/happy-dom/20.10.2/20.10.5?slim=true)
    |
    | [pnpm](https://pnpm.io)
    ([source](https://redirect.github.com/pnpm/pnpm/tree/HEAD/pnpm)) |
    [`11.5.3` →
    `11.7.0`](https://renovatebot.com/diffs/npm/pnpm/11.5.3/11.7.0) |
    ![age](https://developer.mend.io/api/mc/badges/age/npm/pnpm/11.7.0?slim=true)
    |
    ![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/pnpm/11.5.3/11.7.0?slim=true)
    |
    | [vitest](https://vitest.dev)
    ([source](https://redirect.github.com/vitest-dev/vitest/tree/HEAD/packages/vitest))
    | [`4.1.8` →
    `4.1.9`](https://renovatebot.com/diffs/npm/vitest/4.1.8/4.1.9) |
    ![age](https://developer.mend.io/api/mc/badges/age/npm/vitest/4.1.9?slim=true)
    |
    ![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/vitest/4.1.8/4.1.9?slim=true)
    |
    | [vue](https://vuejs.org/)
    ([source](https://redirect.github.com/vuejs/core)) | [`3.5.37` →
    `3.5.38`](https://renovatebot.com/diffs/npm/vue/3.5.37/3.5.38) |
    ![age](https://developer.mend.io/api/mc/badges/age/npm/vue/3.5.38?slim=true)
    |
    ![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/vue/3.5.37/3.5.38?slim=true)
    |
    | [vue-tsc](https://redirect.github.com/vuejs/language-tools)
    ([source](https://redirect.github.com/vuejs/language-tools/tree/HEAD/packages/tsc))
    | [`3.3.4` →
    `3.3.5`](https://renovatebot.com/diffs/npm/vue-tsc/3.3.4/3.3.5) |
    ![age](https://developer.mend.io/api/mc/badges/age/npm/vue-tsc/3.3.5?slim=true)
    |
    ![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/vue-tsc/3.3.4/3.3.5?slim=true)
    |

    ---

    <details>
    <summary>microsoft/playwright (@&#8203;playwright/test)</summary>
    [`v1.61.0`](https://redirect.github.com/microsoft/playwright/releases/tag/v1.61.0)

    [Compare
    Source](https://redirect.github.com/microsoft/playwright/compare/v1.60.0...v1.61.0)

    New [Credentials](https://playwright.dev/docs/api/class-credentials)
    virtual authenticator, available via
    [browserContext.credentials](https://playwright.dev/docs/api/class-browsercontext#browser-context-credentials),
    lets tests register passkeys and answer `navigator.credentials.create()`
    / `navigator.credentials.get()` ceremonies in the page — no real
    hardware key required, works in all browsers:

    ```js
    const context = await browser.newContext();

    // Seed a passkey your backend provisioned for a test user.
    await context.credentials.create('example.com', {
      id: credentialId,
      userHandle,
      privateKey,
      publicKey,
    });
    await context.credentials.install();

    const page = await context.newPage();
    await page.goto('https://example.com/login');
    // The page's navigator.credentials.get() is answered with the seeded passkey.
    ```

    You can also let the app register a passkey once in a setup test, read
    it back with
    [credentials.get()](https://playwright.dev/docs/api/class-credentials#credentials-get),
    and seed it into later tests — see
    [Credentials](https://playwright.dev/docs/api/class-credentials) for
    details.

    New [WebStorage](https://playwright.dev/docs/api/class-webstorage) API,
    available via
    [page.localStorage](https://playwright.dev/docs/api/class-page#page-local-storage)
    and
    [page.sessionStorage](https://playwright.dev/docs/api/class-page#page-session-storage),
    reads and writes the page's storage for the current origin:

    ```js
    await page.localStorage.setItem('token', 'abc');
    const token = await page.localStorage.getItem('token');
    const items = await page.sessionStorage.items();
    ```

    -
    [apiResponse.securityDetails()](https://playwright.dev/docs/api/class-apiresponse#api-response-security-details)
    and
    [apiResponse.serverAddr()](https://playwright.dev/docs/api/class-apiresponse#api-response-server-addr)
    mirror the browser-side
    [response.securityDetails()](https://playwright.dev/docs/api/class-response#response-security-details)
    and
    [response.serverAddr()](https://playwright.dev/docs/api/class-response#response-server-addr).

    - New option `artifactsDir` in
    [browserType.connectOverCDP()](https://playwright.dev/docs/api/class-browsertype#browser-type-connect-over-cdp)
    controls where artifacts such as traces and downloads are stored when
    attached to an existing browser.
    - New option `cursor` in
    [screencast.showActions()](https://playwright.dev/docs/api/class-screencast#screencast-show-actions)
    controls the cursor decoration rendered for pointer actions.
    - The `onFrame` callback in
    [screencast.start()](https://playwright.dev/docs/api/class-screencast#screencast-start)
    now receives a `timestamp` of when the frame was presented by the
    browser.

    - The
    [testOptions.video](https://playwright.dev/docs/api/class-testoptions#test-options-video)
    option now supports the same set of modes as `trace`: new
    `'on-all-retries'`, `'retain-on-first-failure'` and
    `'retain-on-failure-and-retries'` values. See the [video modes
    table](https://playwright.dev/docs/test-use-options#video-modes) for
    which runs are recorded and kept in each mode.
    - Supported `expect.soft.poll(...)`.
    - New
    [fullConfig.argv](https://playwright.dev/docs/api/class-fullconfig#full-config-argv)
    — a snapshot of `process.argv` from the runner process, handy for
    reading custom arguments passed after the `--` separator.
    - New
    [fullConfig.failOnFlakyTests](https://playwright.dev/docs/api/class-fullconfig#full-config-fail-on-flaky-tests)
    mirrors the config option, so reporters can explain why a flaky run
    failed.
    -
    [testInfo.errors](https://playwright.dev/docs/api/class-testinfo#test-info-errors)
    now lists each sub-error of an `AggregateError` as a separate entry.
    - New `-G` command line shorthand for `--grep-invert`.

    - Playwright now supports Ubuntu 26.04.
    - HAR and trace recordings now include WebSocket requests.

    - Chromium 149.0.7827.55
    - Mozilla Firefox 151.0
    - WebKit 26.5

    This version was also tested against the following stable channels:

    - Google Chrome 149
    - Microsoft Edge 149

    </details>

    <details>
    <summary>capricorn86/happy-dom (happy-dom)</summary>
    [`v20.10.5`](https://redirect.github.com/capricorn86/happy-dom/releases/tag/v20.10.5)

    [Compare
    Source](https://redirect.github.com/capricorn86/happy-dom/compare/v20.10.4...v20.10.5)

    - Adds cache to query selector parser - By
    **[@&#8203;capricorn86](https://redirect.github.com/capricorn86)** in
    task
    [#&#8203;2142](https://redirect.github.com/capricorn86/happy-dom/issues/2142)
    - The selector parser degraded in performance in v20.6.3 to solve more
    complex selectors
    - Parsing is still a bit slower, but the cache will hopefully mitigate
    most of the problem
    [`v20.10.4`](https://redirect.github.com/capricorn86/happy-dom/releases/tag/v20.10.4)

    [Compare
    Source](https://redirect.github.com/capricorn86/happy-dom/compare/v20.10.3...v20.10.4)

    - Coerce null qualifiedName to empty string in createDocument - By
    **[@&#8203;Firer](https://redirect.github.com/Firer)** in task
    [#&#8203;2206](https://redirect.github.com/capricorn86/happy-dom/issues/2206)
    [`v20.10.3`](https://redirect.github.com/capricorn86/happy-dom/releases/tag/v20.10.3)

    [Compare
    Source](https://redirect.github.com/capricorn86/happy-dom/compare/v20.10.2...v20.10.3)

    - Fix "\~=" attribute selector matching hyphenated substrings in CSS
    selectors - By
    **[@&#8203;mixelburg](https://redirect.github.com/mixelburg)** in task
    [#&#8203;2194](https://redirect.github.com/capricorn86/happy-dom/issues/2194)

    </details>

    <details>
    <summary>pnpm/pnpm (pnpm)</summary>
    [`v11.7.0`](https://redirect.github.com/pnpm/pnpm/releases/tag/v11.7.0):
    pnpm 11.7

    [Compare
    Source](https://redirect.github.com/pnpm/pnpm/compare/v11.6.0...v11.7.0)

    - Added a new setting `frozenStore` (`--frozen-store`) that lets `pnpm
    install` run against a package store on a read-only filesystem (e.g. a
    Nix store, a read-only bind mount, an OCI layer). When enabled, pnpm
    opens the store's SQLite `index.db` through the `immutable=1` URI —
    bypassing the WAL/`-shm` sidecar creation that otherwise fails on a
    read-only directory — and suppresses every store-write path (the
    `index.db` writer and the project-registry write). Pair it with
    `--offline --frozen-lockfile` against a fully-populated store. Under the
    global virtual store, package directories live inside the store, so if
    the store is missing the build output of a package whose lifecycle
    scripts are approved (or that has a patch), pnpm fails up front with
    `ERR_PNPM_FROZEN_STORE_NEEDS_BUILD` rather than crashing mid-build on a
    read-only write — seed the store with those builds first. Incompatible
    with `--force` and with a configured pnpr server, since both write into
    the store; the side-effects cache is likewise not written under
    `frozenStore`. If the store is missing its content directory, the
    install fails fast with `ERR_PNPM_FROZEN_STORE_INCOMPLETE` rather than
    attempting to initialize it. The read-only `immutable=1` open requires
    Node.js >=22.15.0, >=23.11.0, or >=24.0.0; on older runtimes
    `--frozen-store` fails with a clear
    `ERR_PNPM_FROZEN_STORE_UNSUPPORTED_NODE` error. Bin-linking also
    tolerates a read-only store: under the global virtual store a package's
    bin source lives inside the store, so the `chmod` that makes it
    executable would be refused — with `EPERM`/`EACCES`, or with `EROFS` on
    a genuinely read-only filesystem. That `chmod` is redundant when the
    seed already ships its bins executable with a normalized shebang, so it
    is now skipped in that case, while a non-executable bin (or one still
    carrying a Windows CRLF shebang) on a read-only store still errors.
    - When
    [`pacquet`](https://redirect.github.com/pnpm/pnpm/tree/main/pacquet)
    (the Rust port of pnpm) is declared in `configDependencies`, pnpm now
    delegates dependency **resolution** to it too — not just materialization
    — provided the installed pacquet is new enough to support full resolving
    installs (>= 0.11.7).

    Previously pacquet only ran in frozen-install mode: pnpm always resolved
    the dependency graph itself (writing `pnpm-lock.yaml`) and handed
    pacquet a finished lockfile to fetch / import / link. With pacquet >=
    0.11.7, a non-frozen `pnpm install` (default isolated `nodeLinker`,
    plain install) is delegated to pacquet end-to-end in a single pass —
    pacquet resolves the manifests, writes the lockfile, and materializes
    `node_modules`. pnpm detects the capability from the installed pacquet's
    version; older pacquet releases keep the resolve-then-materialize split,
    and `add` / `update` / `remove` still resolve in pnpm (it has to mutate
    the manifests first). This remains an opt-in preview of the Rust install
    engine
    [#&#8203;11723](https://redirect.github.com/pnpm/pnpm/issues/11723).
    - Added a new opt-in `--batch` flag to `pnpm publish --recursive` that
    sends all selected packages to the registry in a single `PUT
    /-/pnpm/v1/publish` request instead of one request per package. The
    target registry has to implement the batch publish endpoint (pnpr does);
    registries that don't are reported with a clear
    `ERR_PNPM_BATCH_PUBLISH_UNSUPPORTED` error. The batch is processed
    all-or-nothing by pnpr: if any package in the batch fails validation,
    none of the packages are published.

    - Reject path-traversal and reserved dependency aliases (such as
    `../../../escape`, `.bin`, `.pnpm`, or `node_modules`) that come from a
    lockfile rather than a freshly resolved manifest. A crafted lockfile
    alias could otherwise be joined directly under a hoisted `node_modules`
    directory, letting package files be written outside the intended install
    root or overwrite pnpm-owned layout.

      The fix adds two layers:

    - The `nodeLinker: hoisted` graph builder now validates each alias at
    the directory sink (`safeJoinModulesDir`), matching the validation pnpm
    already performs when resolving aliases from manifests.
    - The lockfile verification gate (`verifyLockfileResolutions`) now runs
    an always-on, policy-independent check that rejects any importer or
    snapshot dependency alias that is not a valid package name, failing the
    install early — before any fetch or filesystem work — for every node
    linker at once.

    - Made shared package child resolution deterministic when the same
    package is reached through multiple contexts. pnpm now chooses the
    shallowest occurrence, then importer order, then parent path, instead of
    letting request timing decide the child context and missing-peer report
    [pnpm/pnpm#12358](https://redirect.github.com/pnpm/pnpm/issues/12358).

    - Fix garbled summary line after submitting `pnpm update -i` and `pnpm
    audit --fix -i`. The interactive checkbox prompt previously printed
    every selected choice's full table row (label, current/target versions,
    workspace, URL) joined by commas, producing a wall of text after
    pressing Enter. The summary now lists only the selected package names
    (or vulnerability keys) by setting an explicit `short` per choice; the
    in-progress selection UI is unchanged.

    - Prevent `pnpm patch-remove` from removing files outside the configured
    patches directory.

    - Fixed `pnpm publish` ignoring `strictSsl: false` when publishing to
    registries with self-signed certificates. The `strictSSL` option is now
    forwarded to `libnpmpublish` / `npm-registry-fetch` so that
    `strict-ssl=false` in `.npmrc` or `strictSsl: false` in
    `pnpm-workspace.yaml` is respected during publish, the same way it is
    for `pnpm install`
    [pnpm/pnpm#12012](https://redirect.github.com/pnpm/pnpm/issues/12012).

    - Fixed `Cannot destructure property 'manifest' of
    'manifestsByPath[rootDir]' as it is undefined` regression introduced in
    11.6.0 when running `pnpm add <pkg>` outside a workspace on Windows.
    `selectProjectByDir` was keying the resulting `ProjectsGraph` by
    `opts.dir` instead of `project.rootDir`, so downstream `manifestsByPath`
    lookups missed when the two paths normalized differently (typically
    drive-letter casing).
    [pnpm/pnpm#12379](https://redirect.github.com/pnpm/pnpm/issues/12379)

    - Git dependencies that point to a subdirectory of a repository
    (`repo#commit&path:/sub/dir`) keep their `path` in the lockfile again.
    Since the integrity of git-hosted tarballs started being pinned in the
    lockfile, any install that actually downloaded the tarball rebuilt the
    lockfile resolution as `{ integrity, tarball, gitHosted }` and dropped
    the `path` field, while installs served from the store kept it — so the
    field disappeared seemingly at random. Without `path`, later installs
    from that lockfile silently unpacked the repository root instead of the
    subdirectory
    [#&#8203;12304](https://redirect.github.com/pnpm/pnpm/issues/12304).

    - Fixed nondeterministic lockfile output that made `pnpm dedupe --check`
    fail intermittently in CI. When a locked peer provider was pinned for a
    dependency that has no child dependencies of its own, the pinned
    provider leaked into the shared parent scope, so siblings resolved after
    it could pick up an optional peer they should not see. Which siblings
    were affected depended on resolution order, which varies with network
    timing.

    - Sped up `pnpm install` with a frozen lockfile by running lockfile
    verification (the policy revalidation gate added for
    `minimumReleaseAge`/`trustPolicy` and the tarball-URL anti-tamper check)
    concurrently with fetching and linking instead of blocking the whole
    install on it. Dependency lifecycle scripts are still held back until
    verification succeeds, so no script runs on an unverified lockfile: if
    verification fails the install aborts before any dependency build, and
    if linking finishes first the install waits for the verification verdict
    before completing.

    - User-defined `npm_config_*` environment variables are now preserved
    during lifecycle script execution. Previously, all `npm_`-prefixed env
    vars were stripped, which caused user-set variables like
    `npm_config_platform_arch` to be lost
    [pnpm/pnpm#12399](https://redirect.github.com/pnpm/pnpm/issues/12399).

    - pnpm can now use different auth tokens for different package scopes,
    even when those scopes use the same registry URL.

    Previously, auth was selected only by registry URL. If `@org-a` and
    `@org-b` both used `https://npm.pkg.github.com/`, they had to share the
    same token. This caused problems for registries that issue tokens per
    organization or per scope.

    Configure a scope-specific token by adding the package scope after the
    registry URL in the auth key:

      ```ini
      @&#8203;org-a:registry=https://npm.pkg.github.com/
      @&#8203;org-b:registry=https://npm.pkg.github.com/

      //npm.pkg.github.com/:@&#8203;org-a:_authToken=${ORG_A_TOKEN}
      //npm.pkg.github.com/:@&#8203;org-b:_authToken=${ORG_B_TOKEN}

      //npm.pkg.github.com/:_authToken=${FALLBACK_TOKEN}
      ```

    `pnpm login --registry=https://npm.pkg.github.com --scope=@&#8203;org-a`
    writes the token to the same scope-specific auth key.

    When installing or publishing `@org-a/*`, pnpm uses `ORG_A_TOKEN`. For
    `@org-b/*`, pnpm uses `ORG_B_TOKEN`. Packages without a matching scope
    continue to use the registry-wide fallback token.

    - `pnpm setup` no longer prompts to approve build scripts for
    `@pnpm/exe` when installing the standalone executable. pnpm links the
    platform-specific binary itself, so the package's install scripts are
    skipped during the global self-install
    [#&#8203;12377](https://redirect.github.com/pnpm/pnpm/issues/12377).

    - Close lockfile reads deterministically before rewriting lockfiles and
    keep pacquet's virtual store directory length aligned with pnpm on
    Windows.

    - A `304 Not Modified` answer from the registry now renews the cached
    metadata file's mtime, so the `minimumReleaseAge` freshness shortcut
    keeps serving resolutions from the cache. Previously, once a cached
    packument grew older than `minimumReleaseAge`, every subsequent install
    re-validated it against the registry forever, because a 304 never
    rewrites the file.

    - Updated dependency ranges. Notably:

      - `@pnpm/logger` peer dependency range moved to `^1100.0.0`.
    - `msgpackr` 1.11.8 → 2.0.4 (store index files remain byte-compatible in
    both directions).
    - `open` ^7.4.2 → ^11.0.0, `memoize` ^10 → ^11, `cli-truncate` ^5 → ^6,
    `pidtree` ^0.6 → ^1.
    - `@yarnpkg/core` 4.5.0 → 4.8.0, `@rushstack/worker-pool` 0.7.7 →
    0.7.18, `@cyclonedx/cyclonedx-library` 10.0.0 → 10.1.0,
    `@pnpm/config.nerf-dart` ^1 → ^2, `@pnpm/log.group` 3.0.2 → 4.0.1,
    `@pnpm/util.lex-comparator` ^3 → ^4.

    - Updated `@zkochan/cmd-shim` to v9.0.6.

    - Fixed a Windows-only hang where a failed command could take 20–46
    seconds to exit. On error, pnpm enumerates descendant processes (via
    `pidtree`) to terminate them, which on Windows shells out to
    `wmic`/PowerShell `Get-CimInstance Win32_Process` — a lookup that is
    extremely slow on some machines. The lookup is now bounded by a short
    timeout so it can no longer stall the process exit.

    <!-- sponsors -->

    <table>
      <tbody>
        <tr>
          <td align="center" valign="middle">
    <a href="https://bit.cloud/?utm_source=pnpm&utm_medium=release_notes"
    target="_blank"><img src="https://pnpm.io/img/users/bit.svg" width="80"
    alt="Bit"></a>
          </td>
        </tr>
        <tr>
          <td align="center" valign="middle">
    <a href="https://openai.com/?utm_source=pnpm&utm_medium=release_notes"
    target="_blank">
              <picture>
    <source media="(prefers-color-scheme: light)"
    srcset="https://pnpm.io/img/users/openai_dark.svg" />
    <source media="(prefers-color-scheme: dark)"
    srcset="https://pnpm.io/img/users/openai_light.svg" />
    <img src="https://pnpm.io/img/users/openai_dark.svg" width="160"
    alt="OpenAI" />
              </picture>
            </a>
          </td>
        </tr>
      </tbody>
    </table>

    <table>
      <tbody>
        <tr>
          <td align="center" valign="middle">
    <a href="https://sanity.io/?utm_source=pnpm&utm_medium=release_notes"
    target="_blank">
              <picture>
    <source media="(prefers-color-scheme: light)"
    srcset="https://pnpm.io/img/users/sanity.svg" />
    <source media="(prefers-color-scheme: dark)"
    srcset="https://pnpm.io/img/users/sanity_light.svg" />
    <img src="https://pnpm.io/img/users/sanity.svg" width="120" alt="Sanity"
    />
              </picture>
            </a>
          </td>
          <td align="center" valign="middle">
    <a href="https://discord.com/?utm_source=pnpm&utm_medium=release_notes"
    target="_blank">
              <picture>
    <source media="(prefers-color-scheme: light)"
    srcset="https://pnpm.io/img/users/discord.svg" />
    <source media="(prefers-color-scheme: dark)"
    srcset="https://pnpm.io/img/users/discord_light.svg" />
    <img src="https://pnpm.io/img/users/discord.svg" width="220"
    alt="Discord" />
              </picture>
            </a>
          </td>
          <td align="center" valign="middle">
    <a href="https://vite.dev/?utm_source=pnpm&utm_medium=release_notes"
    target="_blank"><img src="https://pnpm.io/img/users/vitejs.svg"
    width="42" alt="Vite"></a>
          </td>
        </tr>
        <tr>
          <td align="center" valign="middle">
    <a href="https://serpapi.com/?utm_source=pnpm&utm_medium=release_notes"
    target="_blank">
              <picture>
    <source media="(prefers-color-scheme: light)"
    srcset="https://pnpm.io/img/users/serpapi_dark.svg" />
    <source media="(prefers-color-scheme: dark)"
    srcset="https://pnpm.io/img/users/serpapi_light.svg" />
    <img src="https://pnpm.io/img/users/serpapi_dark.svg" width="160"
    alt="SerpApi" />
              </picture>
            </a>
          </td>
          <td align="center" valign="middle">
    <a
    href="https://coderabbit.ai/?utm_source=pnpm&utm_medium=release_notes"
    target="_blank">
              <picture>
    <source media="(prefers-color-scheme: light)"
    srcset="https://pnpm.io/img/users/coderabbit.svg" />
    <source media="(prefers-color-scheme: dark)"
    srcset="https://pnpm.io/img/users/coderabbit_light.svg" />
    <img src="https://pnpm.io/img/users/coderabbit.svg" width="220"
    alt="CodeRabbit" />
              </picture>
            </a>
          </td>
          <td align="center" valign="middle">
    <a
    href="https://stackblitz.com/?utm_source=pnpm&utm_medium=release_notes"
    target="_blank">
              <picture>
    <source media="(prefers-color-scheme: light)"
    srcset="https://pnpm.io/img/users/stackblitz.svg" />
    <source media="(prefers-color-scheme: dark)"
    srcset="https://pnpm.io/img/users/stackblitz_light.svg" />
    <img src="https://pnpm.io/img/users/stackblitz.svg" width="190"
    alt="Stackblitz" />
              </picture>
            </a>
          </td>
        </tr>
        <tr>
          <td align="center" valign="middle">
    <a href="https://workleap.com/?utm_source=pnpm&utm_medium=release_notes"
    target="_blank">
              <picture>
    <source media="(prefers-color-scheme: light)"
    srcset="https://pnpm.io/img/users/workleap.svg" />
    <source media="(prefers-color-scheme: dark)"
    srcset="https://pnpm.io/img/users/workleap_light.svg" />
    <img src="https://pnpm.io/img/users/workleap.svg" width="190"
    alt="Workleap" />
              </picture>
            </a>
          </td>
          <td align="center" valign="middle">
    <a href="https://nx.dev/?utm_source=pnpm&utm_medium=release_notes"
    target="_blank">
              <picture>
    <source media="(prefers-color-scheme: light)"
    srcset="https://pnpm.io/img/users/nx.svg" />
    <source media="(prefers-color-scheme: dark)"
    srcset="https://pnpm.io/img/users/nx_light.svg" />
    <img src="https://pnpm.io/img/users/nx.svg" width="50" alt="Nx" />
              </picture>
            </a>
          </td>
        </tr>
      </tbody>
    </table>

    <!-- sponsors end -->
    [`v11.6.0`](https://redirect.github.com/pnpm/pnpm/releases/tag/v11.6.0):
    pnpm 11.6

    [Compare
    Source](https://redirect.github.com/pnpm/pnpm/compare/v11.5.3...v11.6.0)
    (action may be required)

    Following
    [GHSA-3qhv-2rgh-x77r](https://redirect.github.com/pnpm/pnpm/security/advisories/GHSA-3qhv-2rgh-x77r),
    pnpm no longer expands `${ENV_VAR}` placeholders that come from a
    **repository-controlled** config file, because a malicious repository
    could otherwise use them to leak your environment secrets (npm tokens,
    CI job tokens, etc.) to an attacker-controlled registry during install.
    This applies to:

    - the project/workspace `.npmrc` — `registry`, `@scope:registry`, proxy
    URLs, URL-scoped keys (`//host/…`), and credential values (`_authToken`,
    `_auth`, `_password`, `username`, `tokenHelper`, `cert`, `key`);
    - registry URLs in `pnpm-workspace.yaml`.

    Environment variables are **still** expanded in trusted config: your
    user-level `~/.npmrc`, the global config, CLI options, and environment
    config.

    **If your authentication broke after upgrading**, move the token out of
    the committed `.npmrc`:

    ```sh
    pnpm config set "//registry.npmjs.org/:_authToken" "$NPM_TOKEN"
    ```

    Or keep the `${NPM_TOKEN}` line but put it in your user-level `~/.npmrc`
    instead of the repo. In **GitHub Actions**, `actions/setup-node` with
    `registry-url` already writes a user-level `.npmrc`, so
    `NODE_AUTH_TOKEN` keeps working. For other CI where editing each
    pipeline is hard, set `PNPM_CONFIG_NPMRC_AUTH_FILE=.npmrc` (or
    `NPM_CONFIG_USERCONFIG=.npmrc`) in the CI environment to declare the
    project `.npmrc` trusted.

    See <https://pnpm.io/npmrc> for full migration details.

    - `pnpm install` completes without re-resolving when `pnpm-lock.yaml`
    was deleted but `node_modules` is intact: the up-to-date check now
    treats the current lockfile (`node_modules/.pnpm/lock.yaml`) — the
    record of what the previous install materialized — as the wanted
    lockfile, verifies the manifests still match it, restores
    `pnpm-lock.yaml` from it, and reports "Already up to date". Previously
    this scenario triggered a full resolution and a re-verification of every
    locked package against the registry.

    - [`615c669`](https://redirect.github.com/pnpm/pnpm/commit/615c669):
    Added support for configuring URL-scoped registry settings through
    `npm_config_//…` and `pnpm_config_//…` environment variables, for
    example:

      ```text
      npm_config_//registry.npmjs.org/:_authToken=<token>
      pnpm_config_//registry.npmjs.org/:_authToken=<token>
      ```

    This provides a file-free way to supply registry authentication. Because
    the registry a value applies to is encoded in the (trusted) environment
    variable name, it is host-scoped by construction and cannot be
    redirected to another registry by repository-controlled config. The
    environment value is treated as trusted config: it takes precedence over
    a project/workspace `.npmrc` but is still overridden by command-line
    options. When the same key is provided through both prefixes,
    `pnpm_config_` wins.

    - Raised the default network concurrency from `min(64, max(cpuCores * 3,
    16))` to `min(96, max(cpuCores * 3, 64))`. Package downloads are
    I/O-bound, not CPU-bound, so deriving the floor from the core count left
    machines with few cores (for example 4-vCPU CI runners) downloading only
    16 tarballs at a time and unable to saturate a low-latency registry. The
    `networkConcurrency` setting still overrides the default.

    - Improved the warning printed when a project `.npmrc` uses an
    environment variable in a registry/proxy URL or in registry credentials.
    The message now explains why the setting was ignored and how to migrate
    it to a trusted source — for example by moving the line to the
    user-level `~/.npmrc` or running `pnpm config set "<key>" <value>` —
    with a link to <https://pnpm.io/npmrc>. The `pnpm config set` example is
    only suggested when the key has no `${...}` placeholder, so the snippet
    is always safe to copy-paste.
    - Print a "Lockfile passes supply-chain policies (verified 2h ago)"
    message when lockfile verification is skipped because a cached verdict
    for the same lockfile content and policy is reused. Previously the
    cached short-circuit was completely silent, which made it look like the
    policy gate never ran
    [#&#8203;12324](https://redirect.github.com/pnpm/pnpm/issues/12324).
    - Platform-specific optional dependencies are now skipped even when
    their `os`/`cpu`/`libc` fields are missing from the registry metadata or
    the lockfile. Some registries strip these fields from the package
    metadata, which made pnpm download and install the binaries of every
    platform regardless of `supportedArchitectures`. The missing platform
    fields of an optional dependency are now inferred from its name (e.g.
    `@nx/nx-win32-arm64-msvc` → `os: win32`, `cpu: arm64`), so
    foreign-platform binaries are skipped without even downloading them
    [#&#8203;11702](https://redirect.github.com/pnpm/pnpm/issues/11702).

    <!-- sponsors -->

    <table>
      <tbody>
        <tr>
          <td align="center" valign="middle">
    <a href="https://bit.cloud/?utm_source=pnpm&utm_medium=release_notes"
    target="_blank"><img src="https://pnpm.io/img/users/bit.svg" width="80"
    alt="Bit"></a>
          </td>
        </tr>
        <tr>
          <td align="center" valign="middle">
    <a href="https://openai.com/?utm_source=pnpm&utm_medium=release_notes"
    target="_blank">
              <picture>
    <source media="(prefers-color-scheme: light)"
    srcset="https://pnpm.io/img/users/openai_dark.svg" />
    <source media="(prefers-color-scheme: dark)"
    srcset="https://pnpm.io/img/users/openai_light.svg" />
    <img src="https://pnpm.io/img/users/openai_dark.svg" width="160"
    alt="OpenAI" />
              </picture>
            </a>
          </td>
        </tr>
      </tbody>
    </table>

    <table>
      <tbody>
        <tr>
          <td align="center" valign="middle">
    <a href="https://sanity.io/?utm_source=pnpm&utm_medium=release_notes"
    target="_blank">
              <picture>
    <source media="(prefers-color-scheme: light)"
    srcset="https://pnpm.io/img/users/sanity.svg" />
    <source media="(prefers-color-scheme: dark)"
    srcset="https://pnpm.io/img/users/sanity_light.svg" />
    <img src="https://pnpm.io/img/users/sanity.svg" width="120" alt="Sanity"
    />
              </picture>
            </a>
          </td>
          <td align="center" valign="middle">
    <a href="https://discord.com/?utm_source=pnpm&utm_medium=release_notes"
    target="_blank">
              <picture>
    <source media="(prefers-color-scheme: light)"
    srcset="https://pnpm.io/img/users/discord.svg" />
    <source media="(prefers-color-scheme: dark)"
    srcset="https://pnpm.io/img/users/discord_light.svg" />
    <img src="https://pnpm.io/img/users/discord.svg" width="220"
    alt="Discord" />
              </picture>
            </a>
          </td>
          <td align="center" valign="middle">
    <a href="https://vite.dev/?utm_source=pnpm&utm_medium=release_notes"
    target="_blank"><img src="https://pnpm.io/img/users/vitejs.svg"
    width="42" alt="Vite"></a>
          </td>
        </tr>
        <tr>
          <td align="center" valign="middle">
    <a href="https://serpapi.com/?utm_source=pnpm&utm_medium=release_notes"
    target="_blank">
              <picture>
    <source media="(prefers-color-scheme: light)"
    srcset="https://pnpm.io/img/users/serpapi_dark.svg" />
    <source media="(prefers-color-scheme: dark)"
    srcset="https://pnpm.io/img/users/serpapi_light.svg" />
    <img src="https://pnpm.io/img/users/serpapi_dark.svg" width="160"
    alt="SerpApi" />
              </picture>
            </a>
          </td>
          <td align="center" valign="middle">
    <a
    href="https://coderabbit.ai/?utm_source=pnpm&utm_medium=release_notes"
    target="_blank">
              <picture>
    <source media="(prefers-color-scheme: light)"
    srcset="https://pnpm.io/img/users/coderabbit.svg" />
    <source media="(prefers-color-scheme: dark)"
    srcset="https://pnpm.io/img/users/coderabbit_light.svg" />
    <img src="https://pnpm.io/img/users/coderabbit.svg" width="220"
    alt="CodeRabbit" />
              </picture>
            </a>
          </td>
          <td align="center" valign="middle">
    <a
    href="https://stackblitz.com/?utm_source=pnpm&utm_medium=release_notes"
    target="_blank">
              <picture>
    <source media="(prefers-color-scheme: light)"
    srcset="https://pnpm.io/img/users/stackblitz.svg" />
    <source media="(prefers-color-scheme: dark)"
    srcset="https://pnpm.io/img/users/stackblitz_light.svg" />
    <img src="https://pnpm.io/img/users/stackblitz.svg" width="190"
    alt="Stackblitz" />
              </picture>
            </a>
          </td>
        </tr>
        <tr>
          <td align="center" valign="middle">
    <a href="https://workleap.com/?utm_source=pnpm&utm_medium=release_notes"
    target="_blank">
              <picture>
    <source media="(prefers-color-scheme: light)"
    srcset="https://pnpm.io/img/users/workleap.svg" />
    <source media="(prefers-color-scheme: dark)"
    srcset="https://pnpm.io/img/users/workleap_light.svg" />
    <img src="https://pnpm.io/img/users/workleap.svg" width="190"
    alt="Workleap" />
              </picture>
            </a>
          </td>
          <td align="center" valign="middle">
    <a href="https://nx.dev/?utm_source=pnpm&utm_medium=release_notes"
    target="_blank">
              <picture>
    <source media="(prefers-color-scheme: light)"
    srcset="https://pnpm.io/img/users/nx.svg" />
    <source media="(prefers-color-scheme: dark)"
    srcset="https://pnpm.io/img/users/nx_light.svg" />
    <img src="https://pnpm.io/img/users/nx.svg" width="50" alt="Nx" />
              </picture>
            </a>
          </td>
        </tr>
      </tbody>
    </table>

    <!-- sponsors end -->

    </details>

    <details>
    <summary>vitest-dev/vitest (vitest)</summary>
    [`v4.1.9`](https://redirect.github.com/vitest-dev/vitest/releases/tag/v4.1.9)

    [Compare
    Source](https://redirect.github.com/vitest-dev/vitest/compare/v4.1.8...v4.1.9)

    - Fix `importOriginal` with optimizer and query import \[backport to v4]
    - by **Hiroshi Ogawa**, **David Harris**, **Codex**and **Vladimir** in
    [#&#8203;10546](https://redirect.github.com/vitest-dev/vitest/issues/10546)
    [<samp>(a5180)</samp>](https://redirect.github.com/vitest-dev/vitest/commit/a5180190c)
    - **browser**:
    - Wait for orchestrator readiness before resolving browser sessions
    \[backport to v4] - by **Vladimir** and **Séamus O'Connor** in
    [#&#8203;10555](https://redirect.github.com/vitest-dev/vitest/issues/10555)
    [<samp>(7fb29)</samp>](https://redirect.github.com/vitest-dev/vitest/commit/7fb29651a)
    - Wait for iframe tester readiness before preparing \[backport to v4] -
    by **Vladimir** and **Séamus O'Connor** in
    [#&#8203;10497](https://redirect.github.com/vitest-dev/vitest/issues/10497)
    and
    [#&#8203;10556](https://redirect.github.com/vitest-dev/vitest/issues/10556)
    [<samp>(fbc62)</samp>](https://redirect.github.com/vitest-dev/vitest/commit/fbc626c40)
    - **mocker**:
    - Hoist vi.mock() for vite-plus/test imports \[backport to v4] - by
    **Hiroshi Ogawa**, **LongYinan**, **Claude Opus 4.8** and **Vladimir**
    in
    [#&#8203;10548](https://redirect.github.com/vitest-dev/vitest/issues/10548)
    [<samp>(2c955)</samp>](https://redirect.github.com/vitest-dev/vitest/commit/2c9559c02)
    - **pool**:
    - Prevent test run hang on worker crash \[backport to v4] - by **Ari
    Perkkiö** and **Jattioui Ismail** in
    [#&#8203;10543](https://redirect.github.com/vitest-dev/vitest/issues/10543)
    and
    [#&#8203;10564](https://redirect.github.com/vitest-dev/vitest/issues/10564)
    [<samp>(934b0)</samp>](https://redirect.github.com/vitest-dev/vitest/commit/934b0f587)
    GitHub](https://redirect.github.com/vitest-dev/vitest/compare/v4.1.8...v4.1.9)

    </details>

    <details>
    <summary>vuejs/core (vue)</summary>
    [`v3.5.38`](https://redirect.github.com/vuejs/core/blob/HEAD/CHANGELOG.md#3538-2026-06-11)

    [Compare
    Source](https://redirect.github.com/vuejs/core/compare/v3.5.37...v3.5.38)

    </details>

    <details>
    <summary>vuejs/language-tools (vue-tsc)</summary>
    [`v3.3.5`](https://redirect.github.com/vuejs/language-tools/blob/HEAD/CHANGELOG.md#335-2026-06-13)

    [Compare
    Source](https://redirect.github.com/vuejs/language-tools/compare/v3.3.4...v3.3.5)

    - **fix:** include event modifiers in duplicate listener checks
    ([#&#8203;6097](https://redirect.github.com/vuejs/language-tools/issues/6097))
    - Thanks to [@&#8203;KazariEX](https://redirect.github.com/KazariEX)!

    </details>

    ---

    📅 **Schedule**: (UTC)

    - Branch creation
      - Only on Monday (`* * * * 1`)
    - Automerge
      - At any time (no schedule defined)

    🚦 **Automerge**: Disabled by config. Please merge this manually once you
    are satisfied.

    ♻ **Rebasing**: Whenever PR is behind base branch, or you tick the
    rebase/retry checkbox.

    👻 **Immortal**: This PR will be recreated if closed unmerged. Get
    [config
    help](https://redirect.github.com/renovatebot/renovate/discussions) if
    that's undesired.

    ---

    - [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check
    this box

    ---

    This PR has been generated by [Mend
    Renovate](https://redirect.github.com/renovatebot/renovate).

    <!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0My4xNDEuNSIsInVwZGF0ZWRJblZlciI6IjQzLjE0MS41IiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6WyJkZXBlbmRlbmNpZXMiXX0=-->

commit 649cb6ff3e
Author: bircni <bircni@icloud.com>
Date:   Mon Jun 22 08:16:09 2026 +0200

    fix(actions): show run index in run view and fix summary graph height (#38165)

    - Display the per-repository run number as `#N` next to the run title in
    the run view, matching the runs list and GitHub
    - Add the run `Index` to the run view API response (and the devtest
    mock) to support that
    - Restore the summary panel's `flex: 1` so the workflow graph fills the
    right-column height even when a run has no job summaries
    - Keep the job-summary section content-sized so it doesn't compete with
    the graph for height
    - Gate the devtest mock job summaries to a subset of runs so the devtest
    page also exercises the no-summary layout

    <img width="521" height="232" alt="image"
    src="https://github.com/user-attachments/assets/a1f2f20b-65bd-4d98-ba6a-b8135580a6de"
    />

commit a4781dde89
Author: puni9869 <80308335+puni9869@users.noreply.github.com>
Date:   Mon Jun 22 11:15:24 2026 +0530

    fix(indexer): fix assignee filters in issue search (#38021)

    fix(indexer): fix assignee filters in issue search (#38021)

    Issue search filtering still relied on the legacy single-assignee field,
    so searches such as "Assigned to you" could miss issues when a keyword
    query was used.

    Index all issue assignee IDs and add an explicit no_assignee field so
    specific, any-assignee, and no-assignee filters work consistently across
    Bleve, Elasticsearch, and Meilisearch.

    Fixes #36299.

commit 7684221ed4
Author: bircni <bircni@icloud.com>
Date:   Mon Jun 22 06:51:16 2026 +0200

    feat(actions): implement `jobs.<job_id>.continue-on-error` (#38100)

    Support `continue-on-error` for workflow jobs when aggregating an
    Actions workflow run status.

    Previously, `continue-on-error` was parsed from workflow YAML but was
    not persisted or used when calculating the overall run result. As a
    result, a failed job could incorrectly fail the entire workflow even
    when the workflow explicitly allowed that job to fail.

    This PR stores the parsed `continue-on-error` value on each action run
    job and treats failed jobs with `continue-on-error: true` as successful
    when computing the workflow run status, matching GitHub Actions
    behavior.

    - Add `ContinueOnError` to `jobparser.Job`.
    - Add `continue_on_error` to `ActionRunJob` with a `NOT NULL DEFAULT
    FALSE` migration.
    - Populate `ActionRunJob.ContinueOnError` when creating workflow run
    jobs.
    - Update workflow status aggregation so failed `continue-on-error` jobs
    do not fail the overall run.
    - Leave `resolveCheckNeeds` unchanged so dependent jobs still see the
    job result as `failure` and are skipped by default.

    This is backward compatible.

    If only the runner or only the server is updated, `continue-on-error`
    continues to degrade to the previous behavior and is effectively ignored
    until both sides support it.

    Related runner PR: https://gitea.com/gitea/runner/pulls/1032

    ---------

    Signed-off-by: bircni <bircni@icloud.com>
    Co-authored-by: Lunny Xiao <xiaolunwen@gmail.com>

commit 2c2611eab9
Author: Giteabot <teabot@gitea.io>
Date:   Sun Jun 21 21:08:48 2026 -0700

    chore(deps): update dependency djlint to v1.39.2 (#38192)

    This PR contains the following updates:

    | Package | Change |
    [Age](https://docs.renovatebot.com/merge-confidence/) |
    [Confidence](https://docs.renovatebot.com/merge-confidence/) |
    |---|---|---|---|
    | [djlint](https://redirect.github.com/djlint/djLint) | `==1.39.0` →
    `==1.39.2` |
    ![age](https://developer.mend.io/api/mc/badges/age/pypi/djlint/1.39.2?slim=true)
    |
    ![confidence](https://developer.mend.io/api/mc/badges/confidence/pypi/djlint/1.39.0/1.39.2?slim=true)
    |

    ---

    <details>
    <summary>djlint/djLint (djlint)</summary>
    [`v1.39.2`](https://redirect.github.com/djlint/djLint/blob/HEAD/CHANGELOG.md#1392---2026-06-11)

    [Compare
    Source](https://redirect.github.com/djlint/djLint/compare/v1.39.0...v1.39.2)

    v1.39.1 was not published due to mypyc compilation error.

    - Fix mypyc compilation.

    </details>

    ---

    📅 **Schedule**: (UTC)

    - Branch creation
      - Only on Monday (`* * * * 1`)
    - Automerge
      - At any time (no schedule defined)

    🚦 **Automerge**: Disabled by config. Please merge this manually once you
    are satisfied.

    ♻ **Rebasing**: Whenever PR is behind base branch, or you tick the
    rebase/retry checkbox.

    🔕 **Ignore**: Close this PR and you won't be reminded about this update
    again.

    ---

    - [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check
    this box

    ---

    This PR has been generated by [Mend
    Renovate](https://redirect.github.com/renovatebot/renovate).

    <!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0My4xNDEuNSIsInVwZGF0ZWRJblZlciI6IjQzLjE0MS41IiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6WyJkZXBlbmRlbmNpZXMiXX0=-->

    Co-authored-by: bircni <bircni@icloud.com>

commit 685b62c60f
Author: bircni <bircni@icloud.com>
Date:   Mon Jun 22 05:50:02 2026 +0200

    fix(api): don't expose private org membership via public_members (#38145)

commit e5891263f8
Author: Lunny Xiao <xiaolunwen@gmail.com>
Date:   Sun Jun 21 10:13:18 2026 -0700

    docs: update changelog for 1.26.3 & 1.26.4 (#38178)

    Front port changelog for 1.26.3 & 1.26.4

    ---------

    Co-authored-by: bircni <bircni@icloud.com>

commit 180af33f86
Author: bircni <bircni@icloud.com>
Date:   Sun Jun 21 16:34:07 2026 +0200

    perf: Various performance regression fixes (#38078)

    Fixes five N+1 / O(n) query patterns found across common user paths.
    Each uses a bulk query that already existed elsewhere in the codebase.

    | Location | Problem | Introduced in |
    | -------------------------------- |
    -------------------------------------------------------------------------------------------------------------------------------
    | ------------- |
    | `IssueList.LoadIsRead` | `.In("issue_id")` missing its arg — xorm
    generates `WHERE 0=1`, so `IsRead` is **never** set; every issue always
    appears unread | #29515 |
    | `ParseCommitsWithStatus` | `GetLatestCommitStatus` called once per
    commit (O(n) queries on commit list / PR commits tab) | #33605 |
    | `getReleaseInfos` (release list) | `GetLatestCommitStatus` called once
    per release for CI badges | #29149 |
    | User milestone dashboard | O(n×m) nested loop matching milestones to
    repos | #26300 |
    | `findCodeComments` (PR diff) | `LoadResolveDoer` + `LoadReactions`
    called per inline comment — up to ~150 queries on a PR with 50 comments
    | #20821 |

    ---------

    Co-authored-by: Lauris B <lauris@nix.lv>

commit ceec230fc0
Author: wxiaoguang <wxiaoguang@gmail.com>
Date:   Sun Jun 21 19:57:22 2026 +0800

    fix: walk git log context error handling (#38182)

    Fix #38177

    Make WalkGitLog can handle EOF and context errors correctly, and don't
    export these private functions & methods & structs.

commit 804b9bf120
Author: silverwind <me@silverwind.io>
Date:   Sun Jun 21 08:07:13 2026 +0200

    chore: upgrade eslint plugins, remove `eslint-plugin-github` (#38046)

    - Bump `eslint`, `typescript-eslint` and `eslint-plugin-unicorn` (to
    v68), and configure the rules added in unicorn v66/v67/v68.
    - Remove `eslint-plugin-github` and its workarounds (rules, type stub,
    pnpm peer override, in-code `eslint-disable` comments); the rules worth
    keeping are covered by `unicorn` equivalents.
    - Apply the resulting fixes and autofixes across the JS codebase.

    _Prepared with Claude (Opus 4.8)._

    ---------

    Signed-off-by: wxiaoguang <wxiaoguang@gmail.com>
    Co-authored-by: wxiaoguang <wxiaoguang@gmail.com>

commit 5368542f8e
Author: bircni <bircni@icloud.com>
Date:   Sat Jun 20 22:26:22 2026 +0200

    fix(cli): default must-change-password to false for bot users (#38175)

commit 645b10087d
Author: TheFox0x7 <thefox0x7@gmail.com>
Date:   Fri Jun 19 23:18:17 2026 +0200

    fix(hostmacher): patch incorrect private list (#38170)

    regression from #38039

commit a12f980793
Author: SEONGHYUN HONG <s3onghyun.hong@gmail.com>
Date:   Fri Jun 19 05:48:27 2026 +0900

    docs: fix duplicated word in foreachref doc comment (#38161)

    The Format doc comment read "See See git-for-each-ref(1)" — removed the
    duplicated "See" (the sibling field comments use a single "See").

    Signed-off-by: s3onghyun <s3onghyun.hong@gmail.com>

commit 21bcca798b
Author: wxiaoguang <wxiaoguang@gmail.com>
Date:   Fri Jun 19 02:21:41 2026 +0800

    fix: csp (#38162)

    ref:
    https://github.com/go-gitea/gitea/issues/8707#issuecomment-4741577316
2026-07-19 20:40:20 +03:00

78 lines
3.8 KiB
TypeScript

// keep this file lightweight, it's imported into IIFE chunk in bootstrap
import {html} from '../utils/html.ts';
import type {Intent} from '../types.ts';
/** Extract a message string from an unknown caught value. */
export function errorMessage(err: unknown): string {
return (err as Error)?.message || String(err);
}
/** Extract a name string from an unknown caught value. */
export function errorName(err: unknown): string {
return (err as Error)?.name ?? '';
}
export function showGlobalErrorMessage(msg: string, msgType: Intent = 'error', details?: string) {
const parentContainer = document.querySelector('.page-content') ?? document.body;
if (!parentContainer) {
alert(`${msgType}: ${msg}`);
return;
}
// compact the message to a data attribute to avoid too many duplicated messages
const msgCompact = `${msgType}-${msg.trim()}`.replace(/[^-\w\u{80}-\u{10FFFF}]+/gu, '');
let msgContainer = parentContainer.querySelector<HTMLDivElement>(`.js-global-error[data-global-error-msg-compact="${CSS.escape(msgCompact)}"]`);
if (!msgContainer) {
const el = document.createElement('div');
el.innerHTML = html`<div class="ui container js-global-error tw-my-[--page-spacing]"><details class="ui ${msgType} message"><summary></summary></details></div>`;
msgContainer = el.firstElementChild as HTMLDivElement;
}
// merge duplicated messages into "the message (count)" format
const msgCount = Number(msgContainer.getAttribute(`data-global-error-msg-count`)) + 1;
msgContainer.setAttribute(`data-global-error-msg-compact`, msgCompact);
msgContainer.setAttribute(`data-global-error-msg-count`, msgCount.toString());
const msgElem = msgContainer.querySelector('details')!;
const msgSummary = msgElem.querySelector('summary')!;
msgSummary.textContent = msg + (msgCount > 1 ? ` (${msgCount})` : '');
if (details) {
let msgDetailsPre = msgElem.querySelector('pre');
if (!msgDetailsPre) msgDetailsPre = document.createElement('pre');
msgDetailsPre.textContent = details;
msgElem.append(msgDetailsPre);
}
parentContainer.prepend(msgContainer);
}
// Detect whether an error originated from Gitea's own scripts, not from
// browser extensions or other external scripts.
const extensionRe = /(chrome|moz|safari(-web)?)-extension:\/\//;
export function isGiteaError(filename: string, stack: string): boolean {
if (extensionRe.test(filename) || extensionRe.test(stack)) return false;
const assetBaseUrl = new URL(`${window.config.assetUrlPrefix}/`, window.location.origin).href;
if (filename && !filename.startsWith(assetBaseUrl) && !filename.startsWith(window.location.origin)) return false;
return !stack || stack.includes(assetBaseUrl);
}
export function processWindowErrorEvent({error, reason, message, type, filename, lineno, colno}: ErrorEvent & PromiseRejectionEvent) {
const err = error ?? reason;
// `error` and `reason` are not guaranteed to be errors. If the value is falsy, it is likely a
// non-critical event from the browser. We log them but don't show them to users. Examples:
// - https://developer.mozilla.org/en-US/docs/Web/API/ResizeObserver#observation_errors
// - https://github.com/mozilla-mobile/firefox-ios/issues/10817
// - https://github.com/go-gitea/gitea/issues/20240
if (!err) {
if (message) console.error(new Error(message));
if (window.config.runModeIsProd) return;
}
// Filter out errors from browser extensions or other non-Gitea scripts.
if (!isGiteaError(filename ?? '', err?.stack ?? '')) return;
const renderedType = type === 'unhandledrejection' ? 'promise rejection' : type;
let msg = err?.message ?? message;
if (!err?.stack && lineno) msg += ` (${filename} @ ${lineno}:${colno})`;
const dot = msg.endsWith('.') ? '' : '.';
showGlobalErrorMessage(`JavaScript ${renderedType}: ${msg}${dot} Open browser console to see more details.`, 'error', err?.stack);
}