chore: Release release/2026-W36 - #7347
Open
github-actions[bot] wants to merge 727 commits into
Open
Conversation
Two transitions driving MariaDB at once would race, so each job takes the row before it starts. All three take it, since a lock only one of them takes excludes nothing. The lock releases at the first commit, so it covers the plays rather than the whole job. The reload before each save is what keeps a concurrent writer from failing the save.
fix(database-server): Fix the audit transition jobs racing the row
The price sits inside a sentence rather than a pricing table, where a bare symbol is easy to skim past, so it spells out the currency code instead.
fix(dashboard): Name the currency in the audit log price
fix: Ensure trusted apps are added implicitly
The Ansible constructor can raise before the play is recorded (SSH lookup, playbook parse, Ansible Play insert), and play.run() can raise after. Either way the server row stayed Running with no play to poll, so the update never terminated and halt_agent_jobs stayed on. Catch it and mark the row Failure so it rolls back, or Fatal if the rollback play is the one that failed. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Some servers must not get a new agent right now. The Agent Update tool skips them, both when picking servers and again before it starts a server's play, since the flag is usually set after the plan exists. Manual updates throw instead of skipping quietly, so whoever clicked the button knows why nothing happened. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
feat(agent-update): Handle play failures and let servers opt out
fix: Allow updates if other app versions changed
Getting into a server means reading the IP, the SSH user and the port off the form, then remembering whether the server needs a jump host. `get_ssh_command` builds the same command Ansible connects with, and the desk form and the dashboard copy it to the clipboard. Only system users can call it. Team members have write access to their own servers, so the UI condition is not enough.
…oard The Console Access button showed the command in a dialog, which you then had to select by hand. It now also copies it, and keeps the dialog so you can still read it.
The command connected straight to the server IP, which nobody can do from their laptop. Servers are reachable only from the press server, and only through the proxy server of their cluster. Same shape as break_glass, plus the outer hop: `ssh frappe@frappe.cloud -t 'ssh -J root@n2-mumbai root@f74-mumbai'`
Picking any active proxy in the cluster gave the wrong one when a cluster has more than one - `get_value` orders by `modified desc`, so a newer proxy won over the one the server is attached to. Fall back to the cluster lookup only for database servers, which have no `proxy_server` field.
`check_dashboard_actions` only lets through methods registered by `dashboard_whitelist`, so the dashboard button got "Not permitted". The decorator applies `frappe.whitelist` too, so the desk button keeps working.
feat(server): Add a button to copy the SSH command
SiteBackup.get_list_query hides successful backups once retention removes their files, so a team cannot show an auditor that a backup ran on an old date. The audit trail lists every day in a range with what is held for it, and exports the list to CSV. Days are answered from Site Backup records, which survive retention for live sites, and the cluster's bucket is listed only for days no record covers. The agent's jobs.sqlite3 carries the same data but has no endpoint to filter jobs by site or date. Filter controls marked local drive the page rather than the query, which is what lets the one tab hold both lists. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Remote File already sends reads to the replication target when a Backup Bucket has one, because the primary can expire an object the replica still holds. The audit trail listed the primary regardless, so a site on a replicated bucket reported old backups as Not Available. Resolution lives on Backup Bucket rather than beside the listing code, since Remote File carries three copies of the same swap and can adopt it later. Writes are untouched and still go to the primary. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Five gaps found while walking through how an audit actually goes. A site whose plan has no offsite backups showed a wall of Not Available, which reads as missing backups rather than a plan that never uploaded any, so the list now carries a banner saying so. Dates before the site existed and dates in the future are trimmed off both ends, since neither can hold a backup and the picker has no min or max to stop them. Buckets are per cluster, so a site moved to another cluster lost sight of its older objects. Every bucket the site's Remote Files point at is now walked, its current cluster first. A year of daily backups also put a few thousand names in one IN clause, now batched. Finished ranges are cached for an hour, because an audit means opening the same range repeatedly. Ranges reaching today stay uncached, since today can still gain a backup. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Records and buckets can only show a backup that still exists. The agent keeps its own job history, so it can tell a day whose files are long gone from a day no backup was ever attempted, and it knows which runs failed. The server is asked last and only for days the other two could not answer, so a site with its objects intact never triggers the call. A day that failed and was retried reports the run that got furthest, and a stored object always outranks what the server remembers. An unreachable server fails the request rather than leaving those days as Not Available. A day nobody could check is not a day without a backup, and an audit trail that quietly says otherwise is worse than one that errors. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Most servers run an agent predating the endpoint and will for a while, and Agent.request answers a missing route by swallowing the error, writing an Error Log and returning None. So the audit trail threw on those servers, and logged once per page view while doing it. Failing the page is the wrong trade when only the days nothing is stored for are affected. Those now stay Not Available and the response carries an unconfirmed flag, which the list turns into a banner, so nobody reads them as a backup that never ran. A server that could not answer is left alone for an hour rather than retried on every view, and an unconfirmed range is not cached so an upgraded agent is picked up. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The endpoint now says when it hit its row limit, which means it dropped the oldest days in the range. Those days would otherwise read as days no backup ran, so the trail marks them unconfirmed the same way it does for a server it could not reach. Also silences a server that answers with nothing. Agent.request turns a missing route into None rather than an exception, so that path skipped the retry guard and asked again on every page view. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The filter bar normalises a control's value with `value == ''`, and that is true for `false`, so unchecking a checkbox reports undefined rather than false. The mode switch tested the value, saw undefined and did nothing, leaving the trail on screen with the box unticked. It tests for the key instead, which is always present for the control that changed. The banners asked for a gray alert, which is not one of the types AlertBanner defines, so it threw reading a colour off undefined and took the page with it. They ask for general now, and AlertBanner falls back to it rather than throwing. The upsell banner asked for the same missing type and would have done the same. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Both banners described the data model rather than what the reader is looking at. They now name the words on screen, so the sentence lands against the rows underneath it. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The checks in restore_tables are judgement calls: no fatal update on the site, a newer update after it, or a database server that does not report itself up. An operator on the desk can see more than the checks can, so the button now opens a dialog with a Force option that skips them. Force never skips the concurrent-restore check, and only a System User can use it. The dashboard button stays unforced. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
fix(site): Skip rate limit on all dedicated server plans
fix: Add press_otp and press_otp_sent cache to persistent cache keys
fix(site-update): Replace the automatic table restore with a button
refactor(invoice): Invoice finalisation flow
The merge of develop into this branch kept the import, but 1bb82d2 had already removed its only use — get_plan_config now checks dedicated_server_plan instead. UNLIMITED_PLANS no longer exists in site_plan.py, so this was an ImportError, not only a ruff F401. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
fix(site-config): Require JSON config values to be an object or array
This fixes an issue where the user is not able to enable/disable fiewalls. The root cause is a missing editable field declaration.
fix(firewall): Permission error on toggle
fix(nat): Clamp MSS
fix(virtual-machine): Fix TypeError in OCI attach_to_firewall
Every other destructive action in the dashboard uses the word drop: drop site, drop server, drop bench group. The bench action menu was the only place that said archive, so the same operation had two names. Only the labels change. The backend method stays `archive`.
fix(dashboard): Say drop bench, not archive bench
github-actions
Bot
requested review from
Aradhya-Tripathi,
adityahase,
balamurali27,
prathameshkurunkar7,
shadrak98,
siduck and
tanmoysrt
as code owners
August 31, 2026 10:48
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