Skip to content

github: add ability to edit commit message from PR in Lando UI (bug 2003888)#1161

Open
Magnolia-Liu wants to merge 1 commit into
mainfrom
magnolia/bug-2003888-adding-edit-commit-msg
Open

github: add ability to edit commit message from PR in Lando UI (bug 2003888)#1161
Magnolia-Liu wants to merge 1 commit into
mainfrom
magnolia/bug-2003888-adding-edit-commit-msg

Conversation

@Magnolia-Liu

@Magnolia-Liu Magnolia-Liu commented May 14, 2026

Copy link
Copy Markdown
Contributor
  • Added a view callable by GitHub to update pull request content with data from Lando
  • Added editable commit body and title fields in the PR UI
    • Land button is disabled while fields are being edited to prevent landing stale content
  • Added an "Edit" and "Save" commit message button that refreshes the page on submit + cancel changes button
    • Text areas are disabled during save to prevent concurrent edits
  • Added error display for invalid input

Demo of UI:

Screen.Recording.2026-06-01.at.5.21.42.PM.mov

@Magnolia-Liu Magnolia-Liu requested review from cgsheeh, shtrom and zzzeid May 14, 2026 17:36
@github-actions

Copy link
Copy Markdown

View this pull request in Lando to land it once approved.

@zzzeid zzzeid left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just a few drive-by comments

Comment thread src/lando/utils/github.py
Comment thread src/lando/api/views.py
@Magnolia-Liu Magnolia-Liu marked this pull request as ready for review May 20, 2026 21:22
@Magnolia-Liu Magnolia-Liu requested a review from a team as a code owner May 20, 2026 21:22

@shtrom shtrom left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Mostly stylistic comments, but this is looking good, and the overall logic makes sense.

Comment thread src/lando/api/views.py
Comment thread src/lando/static_src/legacy/js/components/Stack.js Outdated
Comment thread src/lando/static_src/legacy/js/components/Stack.js Outdated
Comment thread src/lando/ui/jinja2/stack/pull_request.html Outdated
Comment thread src/lando/static_src/legacy/css/pages/StackPage.scss
Comment thread src/lando/static_src/legacy/js/components/Stack.js Outdated
Comment thread src/lando/static_src/legacy/js/components/Stack.js Outdated
Comment on lines -64 to +78
<td>{{ pull_request.title }}</td>
<td>
<textarea readonly id="commit-title" class="textarea">{{ pull_request.title }}</textarea>
<p class="help is-danger" id="commit-title-error"></p>
</td>
</tr>
<tr>
<th>Commit Body</th>
<td>{{ pull_request.body }}</td>
<td>
<textarea readonly id="commit-body" class="textarea">{{ pull_request.body }}</textarea>
<p class="help is-danger" id="commit-body-error"></p>
</td>
</tr>
</table>
<p>

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It may make sense to have title, body and button as a div-like form in a single table row.

Comment on lines +9 to +10
<button id="post-landing-job"
class="button is-large is-loading post-landing-job has-text-white"

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Having an id and a class named the same could be a bit of a footgun for our future selves.

Having an id is good, though. Perhaps we should just make sure that everything rely on it being an id, and remove the class altogether.

This would however force any page to only have a single landing button. I don't think we have it any differently at the moment, but maybe it's not something we want to commit to right here?

If anything, I'd look for ways to avoid needing to make this particular change, if possible.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It may be a good time to reduce clutter here. If .post-landing-job is used elsewhere we could change it to #post-landing-job.

Having said that, not sure if having them have the same name is an issue. I suspect you added this to be able to easily use document.getElementById?.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Having the same name is probably not a technical issue, but from a human differentiation perspective, it's probably best if they are different.

@shtrom shtrom Jun 9, 2026

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If .post-landing-job is used elsewhere we could change it to #post-landing-job.

@zzzeid I think you meant “if it ISN'T used elsewhere”? (otherwise the ids will collide).

Comment thread src/lando/utils/github.py
json={"body": comment},
)

def update_pull_request_content(

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
def update_pull_request_content(
def update_pull_request_description(

It may also make sense to make the title optional, so we can use it to only change the body.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this method is more generic than just updating the description. It can be used to update any attribute on the PR.

Comment thread src/lando/api/tests/test_views.py
Comment thread src/lando/api/tests/test_views.py Outdated
Comment thread src/lando/api/views.py
Comment thread src/lando/static_src/legacy/css/pages/StackPage.scss
});
});

$("button.save-pr").on("click", function (e) {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I noticed in the UI demo that there is no feedback on the save button when it is clicked (unless I missed it?) This would be good for usability (e.g., disable the button temporarily, or change the text, etc...

.getElementById("cancel-edit-pr")
.classList.add("is-hidden");

window.location.reload();

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It would be good to file a bug under https://bugzilla.mozilla.org/show_bug.cgi?id=2000954 to update this to instead re-trigger the checks without a full refresh.

This comment was marked as resolved.

Comment on lines +298 to +311
document.getElementById("commit-title").setAttribute("readonly", true);
document.getElementById("commit-body").setAttribute("readonly", true);
document.getElementById("commit-title-error").textContent = "";
document.getElementById("commit-body-error").textContent = "";
document.getElementById("commit-title").classList.remove("is-danger");
document.getElementById("commit-body").classList.remove("is-danger");
document.getElementById("commit-title").value =
document.getElementById("commit-title").defaultValue;
document.getElementById("commit-body").value =
document.getElementById("commit-body").defaultValue;
document.getElementById("save-pr").dataset.mode = "edit";
document.getElementById("save-pr").textContent = "Edit Commit Message";
document.getElementById("cancel-edit-pr").classList.add("is-hidden");
document.getElementById("post-landing-job").disabled = false;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: you can save the elements in variables and re-use them, instead of doing document.getElementById multiple times for each element.

Comment on lines +9 to +10
<button id="post-landing-job"
class="button is-large is-loading post-landing-job has-text-white"

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It may be a good time to reduce clutter here. If .post-landing-job is used elsewhere we could change it to #post-landing-job.

Having said that, not sure if having them have the same name is an issue. I suspect you added this to be able to easily use document.getElementById?.

Comment on lines +66 to +67
<textarea readonly id="commit-title" class="textarea">{{ pull_request.title }}</textarea>
<p class="help is-danger" id="commit-title-error"></p>

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a bit out of scope for this PR, I filed a bug to remove the use of a table here altogether.

Comment thread src/lando/utils/github.py
json={"body": comment},
)

def update_pull_request_content(

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this method is more generic than just updating the description. It can be used to update any attribute on the PR.

Comment thread package-lock.json

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is probably erroneously showing up here because of the merge. I would recommend squashing this entire PR at some point, before attempting to merge it, to clean up the commit history.

Comment thread src/lando/static_src/legacy/js/components/Stack.js
@Magnolia-Liu Magnolia-Liu requested review from shtrom and zzzeid June 2, 2026 15:58
@Magnolia-Liu Magnolia-Liu changed the title pull_request: add ability to edit commit message from PR in Lando UI pull_request: add ability to edit commit message from PR in Lando UI (bug 2003888) Jun 2, 2026
Comment thread src/lando/api/views.py
Comment on lines +347 to +351
if not self.target_repo.user_can_push(request.user):
return JsonResponse(
{"errors": ["You are not allowed to push to this repository."]},
status=403,
)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wonder if we should make a little assertion util that would return a consistent error everywhere it's called.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I already have this functionality partially implemented in #1160.

<textarea readonly id="commit-title" class="textarea">{{ pull_request.title }}</textarea>
<p class="help is-danger" id="commit-title-error"></p>
<p id="commit-title">{{ pull_request.title }}</p>
<p id="commit-title-error" class="help is-danger"></p>

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wouldn't set the is-danger class on those, even if empty. It can be set as needed by the JS.

$("#save-edit-pr").on("click", function (e) {
var save_edit_pr_button = $(this);

if (save_edit_pr_button.attr("data-mode") === "saved") {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could we swap the logic of this method, so we do the case for saved by default, and the fetch only when we are sure we have data-mode===edit?

It may be worth splitting those two into separate methods, e.g.,

if (save_edit_pr_button.attr("data-mode") === "edit") {
  return save_pr_description();
} 
return edit_pr_description();

.getElementById("cancel-edit-pr")
.classList.add("is-hidden");

window.location.reload();

This comment was marked as resolved.

const pTitle = document.createElement("p");
const pBody = document.createElement("p");
const textareaTitle = $("#commit-title")[0];
const textareaBody = $("#commit-body")[0];

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why do we use array indexing here? This seems odd, and we don't do it before in tho code, e.g., https://github.com/mozilla-conduit/lando/pull/1161/changes/8726f39b11c08695895b0a506e34cad6c652edd4..e6cbe4c36dfa3a2b52f622538df1f06eaa3bbc86#diff-4d791453e88ede62fd62f9e15ecccd2a546f9d0e6fe016091adb198d09a6ca67R272.

If it's not needed (which I'm not sure, tbh), then we should probably be consistent and use the same access type throughout the code.

This comment was marked as resolved.

This comment was marked as resolved.

This comment was marked as resolved.

Comment on lines +297 to +303
$("#commit-title-error").text("");
$("#commit-body-error").text("");
$("#commit-title").removeClass("is-danger");
$("#commit-body").removeClass("is-danger");
$("#commit-title").prop("disabled", true);
$("#commit-body").prop("disabled", true);
$("#cancel-edit-pr").addClass("is-hidden");

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Perhaps we should have utility functions to set/reset the errors, e.g., something like

function set_error_for(selector, error_text, error_class) {
  $(selector + "-error").text(error_text);
  $(selector).removeClass("is-hidden");
  $(selector).removeClass("is-danger");
  $(selector).addClass(error_class);
  $(selector).prop("disabled", error_text === "");
}

@zzzeid zzzeid left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looking good, just a couple of questions/comments. Is it possible to see a new video with the latest UI implementation?

Comment thread src/lando/api/tests/test_views.py Outdated
Comment thread src/lando/api/tests/test_views.py
Comment thread src/lando/api/views.py
Comment on lines +347 to +351
if not self.target_repo.user_can_push(request.user):
return JsonResponse(
{"errors": ["You are not allowed to push to this repository."]},
status=403,
)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I already have this functionality partially implemented in #1160.

@zzzeid zzzeid left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looking good! Just a couple of small changes and I think this will be ready to go.

Comment thread src/lando/api/views.py
Comment thread src/lando/api/views.py Outdated
Comment thread src/lando/static_src/legacy/js/components/Stack.js Outdated
Comment thread src/lando/api/tests/test_views.py Outdated
Comment thread src/lando/api/tests/test_views.py Outdated

@shtrom shtrom left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A few nits, and one remaining thing regarding the handling of the status from the fetch to the API (return early on 200, and handle all 4xx).

This looks pretty good overall, though. Nice job!

Comment thread src/lando/api/tests/test_views.py
Comment thread src/lando/api/tests/test_views.py Outdated
Comment thread src/lando/api/views.py Outdated
Comment thread src/lando/api/views.py Outdated
Comment thread src/lando/static_src/legacy/css/pages/StackPage.scss
Comment thread src/lando/static_src/legacy/js/components/Stack.js Outdated
@Magnolia-Liu Magnolia-Liu requested review from shtrom and zzzeid June 17, 2026 19:16

@shtrom shtrom left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

:shipit:


@pytest.fixture
def repo_github_api_client(repo_mc):
repo_mc(SCMType.GIT, name="git-repo")

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: it may be safer to name the repo after the fixture it comes from, to avoid risks of collisions

@Magnolia-Liu Magnolia-Liu force-pushed the magnolia/bug-2003888-adding-edit-commit-msg branch from 124e4bb to 5d3e39f Compare June 22, 2026 18:54
@Magnolia-Liu Magnolia-Liu changed the title pull_request: add ability to edit commit message from PR in Lando UI (bug 2003888) github: add ability to edit commit message from PR in Lando UI (bug 2003888) Jun 22, 2026
@Magnolia-Liu Magnolia-Liu force-pushed the magnolia/bug-2003888-adding-edit-commit-msg branch from 5d3e39f to 2781bcf Compare June 22, 2026 19:09
@Magnolia-Liu Magnolia-Liu reopened this Jun 22, 2026
@Magnolia-Liu Magnolia-Liu force-pushed the magnolia/bug-2003888-adding-edit-commit-msg branch from 2781bcf to bce8475 Compare June 22, 2026 19:58
@Magnolia-Liu Magnolia-Liu reopened this Jun 22, 2026
@Magnolia-Liu Magnolia-Liu force-pushed the magnolia/bug-2003888-adding-edit-commit-msg branch from bce8475 to ee345d8 Compare June 22, 2026 20:28
@Magnolia-Liu Magnolia-Liu force-pushed the magnolia/bug-2003888-adding-edit-commit-msg branch from a4fd00b to 8af7584 Compare June 23, 2026 17:51
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.

3 participants