chore: Release release/2026-W34 - #7236
Open
github-actions[bot] wants to merge 537 commits into
Open
Conversation
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>
feat: Add public IP for hetzner
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.
instead of quickstart
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>
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
github-actions
Bot
requested review from
Aradhya-Tripathi,
adityahase,
balamurali27,
prathameshkurunkar7,
shadrak98,
siduck and
tanmoysrt
as code owners
August 17, 2026 04:50
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. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Weekly release PR