Skip to content

chore: Release release/2026-W34 - #7236

Open
github-actions[bot] wants to merge 537 commits into
masterfrom
release/2026-W34
Open

chore: Release release/2026-W34#7236
github-actions[bot] wants to merge 537 commits into
masterfrom
release/2026-W34

Conversation

@github-actions

Copy link
Copy Markdown

Weekly release PR

ssiyad and others added 30 commits July 28, 2026 14:50
The code is no longer kept on Account Request, so the test cannot look it
up there. It captures what was mailed instead, which is what the person
using the dialog has.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Checking the code and deleting it were still two steps, so a code replaced
in between was accepted anyway, and the delete then landed on the
replacement — leaving the caller holding a code that had just been thrown
away and being told it was wrong.

Redis does both in one step now. A small script deletes the key only if it
still holds the code being presented, which settles this and the two
callers racing for one code together: whoever the delete lands for wins,
and it lands for nobody if the code has moved on.

Comparing in Lua means storing the hash on its own rather than inside a
pickled record, so when a code was last sent moves to its own key that
expires after the resend wait. Frappe's cache namespaces keys and pickles
values on some methods and not others, so these use raw redis commands
throughout and namespace up front.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
fix(account): Keep one-time passwords out of Account Request
…rest

fix(tls): Encrypt TLS private keys at rest
The rule against a leading None in a type union became stable in ruff
0.16, and the lint job installs ruff unpinned, so this pre-existing
annotation started failing CI as soon as site.py was touched for anything
else.

Five more of these are sitting in api/marketplace.py, api/server.py and
app_source.py. They stay quiet until something changes those files.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Turning `private_key` into a Password field left the desk "Copy Private
Key" button copying the `*****` mask, since the client only ever gets the
masked value. Whitelist `get_private_key()` and have the button fetch the
decrypted key from the server before copying. Exposure is unchanged — the
button already copied the plaintext when the field was a Code field.
…rest

fix(tls): Decrypt private key in desk copy button
fix(role): Refresh before update
Matches the slug style of the existing frappe-cloud-server-alerts channel.
The incidents channel id was hard-coded and nobody could tell whether the
guessed slug matched the real channel. Made it a setting instead of
guessing; a wrong channel is now a one-field fix in the UI.
fix: Redirect 0 site user to dashboard post-login
…abled

feat(incident): Alert on Raven when phone call alerts are disabled
The file predates biome.json's `semicolons: "asNeeded"`, so the
pre-commit hook rewrites ~45 lines on the next touch. Doing it alone
keeps the follow-up fix readable in review.
The tab labels split on ownership (Public GitHub App vs Your GitHub App),
but the real split is access: whether Frappe Cloud has a GitHub
installation on the repo. A private repo fit neither label, so users
pasted the URL into the default tab and got a raw GitHub JSON dump.

Renamed the tabs to Public/Private Repository, replaced the 404 dump
with a plain message, and made the dialog offer a link to the private
tab instead. Matched on the message text rather than the status code
because the resource only surfaces the error, not the response.
fix(dashboard): Point users at the private repo tab on a 404
The old Change Region dialog warned when a site had custom domains on A
records. That warning was dropped when migrations moved to the Site
Action flow in #4890, and it was inverted anyway (it rendered only when
the site had no A records).

Return the flag plus the destination cluster's inbound IP so the dialog
can warn again and name the IP to point at. Resolved the destination
through the same Bench lookup change_region uses, not the cluster's
proxy list, so the IP shown is the one the site actually lands behind.
A custom domain on an A record points at the old cluster's proxy IP, so
it stops resolving once the site moves. Site Migration knows this and
silently demotes an A record primary domain back to the *.frappe.cloud
name, with no warning before and no notification after.

Shows the destination IP and the CNAME alternative once a region is
picked. Kept it in the region block instead of the shared
warningMessage map because it needs the selected region's IP.
RUF036 fires on `None | str` in CI. The annotation predates this branch
(b828afe), but CI lints the whole file, so the check fails on any PR
that touches site.py.
After a machine is downsized, MariaDB can fail to start with an InnoDB buffer
pool sized for the bigger machine. Adjusting the config then didn't help: the
play set the variable on the running server first, so it bailed out before
writing the config file and the smaller size was never persisted.

Write the config file first, and restart MariaDB when the runtime change fails.
Restarting is fine here because the value is already on disk.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
…ore-downgrade

fix(server): Persist MariaDB variable before applying it at runtime
The desk button enqueued `_update_agent_ansible` on the default queue
with no timeout, so RQ killed it at 300s. Ansible puts no timeout on a
task's command, and `agent update` runs `supervisorctl stop
agent:worker-N`, which waits out an rq warm shutdown — stopwaitsecs is
1500 in the agent's supervisor template. Anything past 5 minutes died
mid-play, leaving the Ansible Play and its tasks stuck on
Running/Pending forever with no failure recorded.

Long queue with an explicit 3600s, since the long queue's own 1500s
default is exactly one worker's stopwait and leaves nothing over.

Other callers already enqueue with timeout=18000 from press job steps.

https://github.com/frappe/agent/blob/master/agent/templates/agent/supervisor.conf.jinja2

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
siduck and others added 22 commits August 14, 2026 07:45
feat(site-backup): Add backup audit trail to the site backups tab
fix: Stop remote builds on stop deploy button click
Three costs, each fine alone and not together once a few hundred people
open a trail at once.

The build slept up to a minute waiting on the server's job. That holds a
long queue worker, and a thousand of those would starve the queue that
also carries backups and site work. It builds from what it has now, and
the job's callback drops the built trail when the answer lands so the
next build picks it up.

The page asked again every five seconds until the trail appeared. It
subscribes instead, and the build says when there is something to read.
Nothing is asked for on a timer.

Those asks went through run_doc_method, which returns the whole Site
document with every answer, so checking whether a trail was ready cost
about what loading the site page costs. It has its own endpoint now.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
An Agent Request Failure row means the server is unreachable, and
create_agent_job does not consult it, so every look created another job
that would sit undelivered. It asks should_skip_requests first and goes
straight to the buckets when nothing is getting through.

A job the agent never gave an id to is treated the same after a minute.
job_id stays 0 until the agent acknowledges it, so that catches a job
still queued for delivery and one whose delivery failed outright, where
the status alone would only catch the first.

Test benches leave failures against their own server, which made every
test look like it was talking to a dead agent, so setUp clears them.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The range gets trimmed to the days a site could have been backed up on,
and the completion event carried the trimmed dates while the page matched
them against the ones it had asked with. A site younger than the range,
or an end date past today, left the page waiting on an event it would
never accept. It returns the used range with the trail, and the page
matches on that.

Dates also arrived from a whitelisted endpoint without being read as
dates first, so a structured value reached getdate and surfaced as a
comparison against None several frames later. Anything that is not a date
is turned away where the range is resolved, which covers every caller
rather than the one endpoint.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The check named the rule and left the caller to guess the shape it
wanted. It reads like the date errors beside it now, and a test covers
the path since it turned out to be reachable: protected passes a
non-string through to the body rather than turning it away first.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The resource fetches on its own, and the resources mixin runs before the
component's created hook, so the first call went out with no start date
and the server turned it away. The default is set in data now, where it
exists before anything can read it.

It is set without clamping to the site's age, since that needed the site
document to have loaded and the server trims the range anyway. The
pickers then follow whatever range came back, so they show the days the
trail actually covers rather than the ones that were asked for.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The 100 GB check tells the user to contact support for a physical backup,
but `set_physical_backup_mode_if_eligible` only picks Physical when the
database server runs on AWS EC2. On OCI, Hetzner or Frappe Compute support
can't switch the backup type either, so the site can never update.

Skipped the check when the database server isn't AWS EC2, instead of
listing the blocked providers, because the reason is the same one that
gates physical backup itself.
perf(site-backup): Stop polling and stop holding a worker to wait
fix(site-update): Only block large-database updates on AWS servers
fix(ui): Show site list for benches site tab only for private benches
feat: Give user an option to reactivate suspended account  postlogin
@mergify

mergify Bot commented Aug 17, 2026

Copy link
Copy Markdown
Contributor

@github-actions[bot], thanks for the contribution, but we do not accept pull requests on a master. Please close this PR and raise PR on an develop branch.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.