Skip to content

Where people and agents ship software together. The open-source git platform for the whole job: issues, agents, checks and deploys to the edge.

g1t.sh

Commit

Merge commit '9232a85b'

syntaqxcommitted Parentsc6a4b0d9232a85Browse files
45 files+209−3729 files not counted0/45 viewed
+2−2
33983398
33993399 [[package]]
34003400 name = "rustls"
3401−version = "0.23.45"
3401+version = "0.23.46"
34023402 source = "registry+https://github.com/rust-lang/crates.io-index"
3403−checksum = "0d41d731c7d2f962d1ccc364cec258de3c0e93b38c2fb3ba97ac74513048d634"
3403+checksum = "48e13bd8c0e9365c43cfa5c9e8f9ad49d3c8444926c9aac819e0e4dc503c8fdf"
34043404 dependencies = [
34053405 "aws-lc-rs",
34063406 "log",
+1−0
275275 Op::Security(SecurityOp::GetDependencyGraph),
276276 Op::Security(SecurityOp::GetSbom),
277277 Op::Security(SecurityOp::CompareDependencies),
278+ Op::Security(SecurityOp::RerunDependencyReview),
278279 ],
279280 ),
280281 (
+4−3
808808 }
809809
810810 impl Op {
811− pub const ALL: [Op; 402] = [
811+ pub const ALL: [Op; 403] = [
812812 Op::Whoami,
813813 Op::GetWorkspace,
814814 Op::CreateWorkspace,
10411041 Op::Security(SecurityOp::GetDependencyGraph),
10421042 Op::Security(SecurityOp::GetSbom),
10431043 Op::Security(SecurityOp::CompareDependencies),
1044+ Op::Security(SecurityOp::RerunDependencyReview),
10441045 Op::Security(SecurityOp::GetSettings),
10451046 Op::Security(SecurityOp::UpdateSettings),
10461047 Op::Security(SecurityOp::GetWorkspaceSettings),
15861587 "Search all of g1t: repositories (name, description, topics, README), code on default branches (file names and contents), issues, pull requests, people and workspaces. Covers everything public, and private content in workspaces you belong to; signed out, public only. Write words, \"exact phrases\", -words to leave out, and qualifiers: repo:owner/name, org:workspace, language:rust, path:src/ (a glob with *), is:issue, is:pr, is:open, is:closed, is:merged, author:username, label:bug. type picks the kind of results (repositories, code, issues, pulls or people); without it, the qualifiers decide. Returns one page of results with the matches highlighted, code with line numbers, and how many there are of each kind."
15871588 }
15881589 Op::GetMergeQueue => {
1589− "A repository's merge queue: the pull requests waiting to land, in order, each with the state it is being tested in (the default branch with the pull requests ahead of it merged in) and how that went; then those that recently landed or left. With the queue on, merging a pull request adds it here."
1590+ "A repository's merge queue: the pull requests waiting to land, in order, each with the state it is being tested in (the default branch with the pull requests ahead of it landed in turn, each by its merge method) and how that went; then those that recently landed or left. With the queue on, merging a pull request adds it here."
15901591 }
15911592 Op::CreateRepo => {
15921593 "Create a repository in one of your workspaces, empty or as a copy of a public git repository elsewhere."
16941695 "What a pull request changes: the files it touches and their line-by-line diff against the commit it started from. Use it to review a pull request or to compare several made for the same issue. A large one lists every file (up to 300; truncated says when there were more) but has the lines of only the first, about 20,000 lines read: the files after that come with omitted true and no lines or counts. Ask again with paths (up to 50 at a time) to have those files' lines."
16951696 }
16961697 Op::MergePullRequest => {
1697− "Land a pull request on its base, the branch it merges into (the default branch unless it names another). merge_method says how: merge (a merge commit joins its branch to the base, its commits included), squash (one new commit holds everything it changed), rebase (each of its commits is made again on top of the base, in order) or fast_forward (the base moves to its head, exactly the commit that was checked; only when its branch contains the base's head). Left out, the repository's default_merge_method. A method the repository does not allow (allow_merge_commit, allow_squash_merge, allow_rebase_merge, allow_fast_forward on update_repo_settings), or that a rule for the base does not (allowed_merge_methods, and required linear history, which refuses merge), is refused. commit_title and commit_message are a merge or squash commit's message: its first line and the rest; left out, the repository's merge_commit_message or squash_commit_message decides. With sha, the merge is refused (409) if the pull request's head is no longer that commit. delete_branch deletes its branch once it has merged (left out, the repository's delete_branch_on_merge); restore_pull_request_head_branch brings it back. Merging needs the Write role or higher, and only once it is marked ready and it meets every rule that holds for its base (see rules and required_checks on get_pull_request: approvals, checks, deployments, merge windows and the rest, from the repository's and its workspace's rulesets); the refusal names the first rule not met. With ignore_checks, someone who may merge can bypass required checks where the rule allows it; with bypass_rules, someone a ruleset lists as a bypass actor merges past its rules, and it is recorded. Merging into the default branch closes the issues in its closes: the issue it was made for and those its title and description name after a closing keyword (Fixes #12), where the repository closes issues (auto_close_issues); the other pull requests still in progress for its issue close as superseded. Merging into another branch closes nothing. Where the repository has a merge queue, a pull request into the default branch joins the queue instead of landing at once. If its base has moved since the pull request was opened, it is brought up to date first and lands when that is done; a repository that requires pull requests into its default branch to be up to date refuses instead: update_pull_request_branch, then merge again. Check status in the result to see whether it has landed, and merge_method and merge_commit for how."
1698+ "Land a pull request on its base, the branch it merges into (the default branch unless it names another). merge_method says how: merge (a merge commit joins its branch to the base, its commits included), squash (one new commit holds everything it changed), rebase (each of its commits is made again on top of the base, in order) or fast_forward (the base moves to its head, exactly the commit that was checked; only when its branch contains the base's head). Left out, the repository's default_merge_method. A method the repository does not allow (allow_merge_commit, allow_squash_merge, allow_rebase_merge, allow_fast_forward on update_repo_settings), or that a rule for the base does not (allowed_merge_methods, and required linear history, which refuses merge), is refused. commit_title and commit_message are a merge or squash commit's message: its first line and the rest; left out, the repository's merge_commit_message or squash_commit_message decides. With sha, the merge is refused (409) if the pull request's head is no longer that commit. delete_branch deletes its branch once it has merged (left out, the repository's delete_branch_on_merge); restore_pull_request_head_branch brings it back. Merging needs the Write role or higher, and only once it is marked ready and it meets every rule that holds for its base (see rules and required_checks on get_pull_request: approvals, checks, deployments, merge windows and the rest, from the repository's and its workspace's rulesets); the refusal names the first rule not met. With ignore_checks, someone who may merge can bypass required checks where the rule allows it; with bypass_rules, someone a ruleset lists as a bypass actor merges past its rules, and it is recorded. Merging into the default branch closes the issues in its closes: the issue it was made for and those its title and description name after a closing keyword (Fixes #12), where the repository closes issues (auto_close_issues); the other pull requests still in progress for its issue close as superseded. Merging into another branch closes nothing. Where the repository has a merge queue, a pull request into the default branch joins the queue instead of landing at once, to be tested and landed by merge_method (the merge queue rule's when absent) with the commit message given. If its base has moved since the pull request was opened, it is brought up to date first and lands when that is done; a repository that requires pull requests into its default branch to be up to date refuses instead: update_pull_request_branch, then merge again. Check status in the result to see whether it has landed, and merge_method and merge_commit for how."
16981699 }
16991700 Op::GetPullRequestMergeOptions => {
17001701 "How a pull request may merge now, as the merge box offers it to you: the methods it may merge by (the repository's, as the rules for its base allow them) and the one offered first (default_method); each method's default commit title and message, and why one cannot be used now (unavailable); whether it is behind its base, can fast-forward as it is, should be offered an update (suggest_update) or must be up to date (require_up_to_date); whether it goes through the merge queue; whether you may turn on auto-merge; whether deleting its branch starts ticked and is possible; and whether commits made merging it are signed off."
+46−0
92869286 "deny_licenses": []
92879287 }
92889288 },
9289+ "rerun_dependency_review": {
9290+ "params": {
9291+ "owner": "flagon-io",
9292+ "name": "hello",
9293+ "number": 12
9294+ },
9295+ "response": {
9296+ "base": "4b1d7c0e9a2f6e3d8c5b0a7f4e1d2c3b4a5f6e7d",
9297+ "head": "9f2c4e1a7b3d5f60812a4c6e8b0d2f4a6c8e0b13",
9298+ "changes": [
9299+ {
9300+ "change_type": "added",
9301+ "manifest": "package-lock.json",
9302+ "ecosystem": "npm",
9303+ "name": "lodash",
9304+ "version": "4.17.21",
9305+ "relationship": "direct",
9306+ "development": false,
9307+ "license": "MIT",
9308+ "purl": "pkg:npm/lodash@4.17.21",
9309+ "vulnerabilities": [],
9310+ "denied_license": false,
9311+ "failing": false
9312+ },
9313+ {
9314+ "change_type": "removed",
9315+ "manifest": "package-lock.json",
9316+ "ecosystem": "npm",
9317+ "name": "lodash",
9318+ "version": "4.17.20",
9319+ "relationship": "direct",
9320+ "development": false,
9321+ "license": "MIT",
9322+ "purl": "pkg:npm/lodash@4.17.20",
9323+ "vulnerabilities": [],
9324+ "denied_license": false,
9325+ "failing": false
9326+ }
9327+ ],
9328+ "passed": true,
9329+ "headline": "2 dependency changes, none vulnerable",
9330+ "fail_on": "high",
9331+ "deny_licenses": []
9332+ },
9333+ "notes": "The pull request's one dependency review comment is changed in place; nothing new is posted when the review says the same."
9334+ },
92899335 "get_security_settings": {
92909336 "params": {
92919337 "owner": "flagon-io",
+1−0
332332 route("GET", "/repos/:owner/:name/dependency-graph", Op::Security(SecurityOp::GetDependencyGraph), &[]),
333333 route("GET", "/repos/:owner/:name/dependency-graph/sbom", Op::Security(SecurityOp::GetSbom), &[]),
334334 route("GET", "/repos/:owner/:name/dependency-graph/compare/:basehead", Op::Security(SecurityOp::CompareDependencies), &[]),
335+ route("POST", "/repos/:owner/:name/pulls/:number/dependency-review/rerun", Op::Security(SecurityOp::RerunDependencyReview), &[]),
335336 route("GET", "/repos/:owner/:name/security/settings", Op::Security(SecurityOp::GetSettings), &[]),
336337 route("PATCH", "/repos/:owner/:name/security/settings", Op::Security(SecurityOp::UpdateSettings), &[]),
337338 route("GET", "/workspaces/:workspace/security/settings", Op::Security(SecurityOp::GetWorkspaceSettings), &[]),
+18−1
5454 GetDependencyGraph,
5555 GetSbom,
5656 CompareDependencies,
57+ RerunDependencyReview,
5758 GetSettings,
5859 UpdateSettings,
5960 GetWorkspaceSettings,
7374 /// Every one: `Op::ALL` lists each as `Op::Security(…)`, which a test
7475 /// checks against this.
7576 #[cfg(test)]
76− pub const ALL: [SecurityOp; 38] = [
77+ pub const ALL: [SecurityOp; 39] = [
7778 SecurityOp::ListSecretAlerts,
7879 SecurityOp::GetSecretAlert,
7980 SecurityOp::UpdateSecretAlert,
99100 SecurityOp::GetDependencyGraph,
100101 SecurityOp::GetSbom,
101102 SecurityOp::CompareDependencies,
103+ SecurityOp::RerunDependencyReview,
102104 SecurityOp::GetSettings,
103105 SecurityOp::UpdateSettings,
104106 SecurityOp::GetWorkspaceSettings,
141143 SecurityOp::GetDependencyGraph => "get_dependency_graph",
142144 SecurityOp::GetSbom => "get_sbom",
143145 SecurityOp::CompareDependencies => "compare_dependencies",
146+ SecurityOp::RerunDependencyReview => "rerun_dependency_review",
144147 SecurityOp::GetSettings => "get_security_settings",
145148 SecurityOp::UpdateSettings => "update_security_settings",
146149 SecurityOp::GetWorkspaceSettings => "get_workspace_security_settings",
185188 SecurityOp::GetDependencyGraph => "Get the dependency graph",
186189 SecurityOp::GetSbom => "Export an SBOM",
187190 SecurityOp::CompareDependencies => "Compare dependencies",
191+ SecurityOp::RerunDependencyReview => "Re-run dependency review",
188192 SecurityOp::GetSettings => "Get a repository's security settings",
189193 SecurityOp::UpdateSettings => "Update a repository's security settings",
190194 SecurityOp::GetWorkspaceSettings => "Get a workspace's security settings",
228232 SecurityOp::GetDependencyGraph => "Get the dependency graph: every package the lockfiles on the default branch resolve, per lockfile, with whether it is direct or transitive (where the lockfile says), for development, its license when recorded, its package URL and its open vulnerability alerts.",
229233 SecurityOp::GetSbom => "Export the dependency graph as an SPDX 2.3 JSON document, in sbom. Every package is named by its package URL.",
230234 SecurityOp::CompareDependencies => "Compare the dependencies at two commits, branches or tags (basehead, as base...head): what was added and removed per lockfile, with the known vulnerabilities of what was added and whether it passes the repository's dependency review policy. Needs the g1t plan on a private repository.",
235+ SecurityOp::RerunDependencyReview => "Run the Dependency review check again on an open pull request's head, with the advisories known now: its status is set again and its one comment on the pull request is changed in place (or added, when it has dependency changes to show and none is there yet). Returns the review. g1t reviews a pull request by itself when it opens and when its head moves, carrying the result over when the head's lockfile changes are the ones reviewed before. Takes the Write role. Needs the g1t plan on a private repository.",
231236 SecurityOp::GetSettings => "Get a repository's security settings: when the Code scanning check fails, dependency review and its policy, whether secrets in the history open alerts, whether it takes private vulnerability reports, its workspace's settings, and whether the paid features are on for it.",
232237 SecurityOp::UpdateSettings => "Change a repository's security settings: code_scanning_gate (none, errors, critical, high, medium or any), dependency_review, review_fail_on (critical, high, medium, low or none), review_deny_licenses (SPDX ids), review_comment, history_alerts (whether secrets found in the history open alerts; push protection stays on) and private_vulnerability_reporting. Takes the Admin role, or a security manager of the workspace. Require the Code scanning and Dependency review checks in branch protection to gate merges on them.",
233238 SecurityOp::GetWorkspaceSettings => "Get a workspace's security settings (delegated bypass, validity checks) and whether it has Security and quality, which comes with the g1t plan.",
428433 &["repo", "id", "state"],
429434 ),
430435 SecurityOp::GetDependencyGraph | SecurityOp::GetSbom | SecurityOp::GetSettings => (json!({ "repo": repo() }), &["repo"]),
436+ SecurityOp::RerunDependencyReview => (
437+ json!({ "repo": repo(), "number": { "type": "integer", "description": "The pull request's number." } }),
438+ &["repo", "number"],
439+ ),
431440 SecurityOp::CompareDependencies => (
432441 json!({
433442 "repo": repo(),
10371046 };
10381047 pass(services, "dependency_review", &DependencyReviewArgs { viewer: viewer.clone(), repo, base, head }).await
10391048 }
1049+ SecurityOp::RerunDependencyReview => {
1050+ let Some(repo) = repo else { return failed(FailureCode::Invalid, &need_repo()) };
1051+ let Some(number) = whole(input, "number").filter(|number| *number > 0) else {
1052+ return failed(FailureCode::Invalid, "number is the pull request's number.");
1053+ };
1054+ pass(services, "rerun_dependency_review", &PullScanningArgs { viewer: viewer.clone(), repo, number }).await
1055+ }
10401056 SecurityOp::GetSettings => {
10411057 let Some(repo) = repo else { return failed(FailureCode::Invalid, &need_repo()) };
10421058 pass(services, "security_settings", &SecuritySettingsArgs { viewer: viewer.clone(), repo }).await
12411257 }
12421258 assert_eq!(scope_for("get_sbom"), Some(Scope::SecurityRead));
12431259 assert_eq!(scope_for("upload_sarif"), Some(Scope::SecurityWrite));
1260+ assert_eq!(scope_for("rerun_dependency_review"), Some(Scope::SecurityWrite));
12441261 // No run decides about security.
12451262 for name in ["bypass_push_protection", "review_bypass_request", "update_security_settings"] {
12461263 assert!(g1t_contracts::credentials::NEVER.contains(&name), "{name}");
+1−0
515515 a("dependency_graph", Op::Security(SecurityOp::GetDependencyGraph), "Every package the lockfiles resolve, direct or transitive"),
516516 a("sbom", Op::Security(SecurityOp::GetSbom), "The dependency graph as an SPDX 2.3 document"),
517517 a("compare_dependencies", Op::Security(SecurityOp::CompareDependencies), "What changes in dependencies between base...head"),
518+ a("rerun_dependency_review", Op::Security(SecurityOp::RerunDependencyReview), "Run a pull request's Dependency review check again"),
518519 a("settings", Op::Security(SecurityOp::GetSettings), "A repository's security settings"),
519520 a("update_settings", Op::Security(SecurityOp::UpdateSettings), "Change when checks fail and dependency review's policy"),
520521 a("workspace_settings", Op::Security(SecurityOp::GetWorkspaceSettings), "A workspace's delegated bypass and validity checks"),
+3−3
713713 checksum = "d045de693cb712d0b22c6a64be5b953f67b3ce00ab5ad3dd5d8b441886ab8e1a"
714714 dependencies = [
715715 "quote",
716− "syn 3.0.7",
716+ "syn 2.0.119",
717717 ]
718718
719719 [[package]]
34873487
34883488 [[package]]
34893489 name = "rustls"
3490−version = "0.23.45"
3490+version = "0.23.46"
34913491 source = "registry+https://github.com/rust-lang/crates.io-index"
3492−checksum = "0d41d731c7d2f962d1ccc364cec258de3c0e93b38c2fb3ba97ac74513048d634"
3492+checksum = "48e13bd8c0e9365c43cfa5c9e8f9ad49d3c8444926c9aac819e0e4dc503c8fdf"
34933493 dependencies = [
34943494 "once_cell",
34953495 "ring",
+6−3
156156 [The merge queue](/guides/merge-queue/#who-answers-for-it) has the table of
157157 outcomes from a person's side.
158158
159−<Aside title="What a merge queue needs">
160− Building candidates takes sandboxes, so the merge queue needs a paid or
161− trial workspace, or the open-source pool for a public repository.
159+<Aside title="How states are built">
160+ `work` builds each candidate in the repository itself, through repos'
161+ `build_queue_step`: the entry landed by its own merge method on the
162+ state ahead of it, with the commits `land` would make there, pushed to
163+ the attempt's `g1t-queue/` branch. Landing is then a fast-forward to
164+ exactly that commit, and no sandbox is involved.
162165 [The merge queue](/guides/merge-queue/) has the settings.
163166 </Aside>
164167
+48−17
99 on, a pull request is tested together with everything ahead of it before it
1010 lands, and `main` only ever moves to a state whose required checks passed.
1111
12−The merge queue runs in g1t's sandboxes, which need
13−[the g1t plan](/guides/usage-and-billing/#the-g1t-plan) or the trial after
14−a card check; a public repository can use the open-source pool instead.
15−Without one, an entry fails at once with a message saying so; turn the
16−queue off to merge directly.
12+g1t builds the queue's states in the repository itself, without a
13+sandbox. What checks them is the repository's `merge_group`
14+[workflows](/guides/actions/), which run and are billed like any other
15+workflow run.
1716
1817 ## Turn it on
1918
6059
6160 ## How entries are tested
6261
63−g1t takes up to four entries (the rule's `max_entries_to_build`) from the front of the queue and tests them all
64−at once, speculatively, each in its own sandbox. Each sandbox builds `main`
65−with that entry and every entry ahead of it merged in, in queue order:
62+g1t takes up to four entries (the rule's `max_entries_to_build`) from the
63+front of the queue and tests them all at once, speculatively. Each entry's
64+state is the one before it with that entry landed on top, in queue order:
6665
6766 | Entry | Tested as |
6867 | --- | --- |
7170 | 3rd | `main` + #41 + #44 + #46 |
7271 | 4th | `main` + #41 + #44 + #46 + #47 |
7372
73+Each entry is landed on the state ahead of it by its own
74+[merge method](/guides/pull-requests/#merge-methods), exactly as merging it
75+there would:
76+
77+- **Merge commit**: a merge commit, with the message for the repository's
78+ merge commits or the one written when it was queued.
79+- **Squash**: one commit, by the pull request's author, with the squash
80+ message and its `Co-authored-by:` trailers.
81+- **Rebase**: each of its commits made again on top, keeping their authors.
82+- **Fast-forward**: its own head, which must already contain everything
83+ ahead of it; otherwise it fails, saying to bring it up to date or merge
84+ it another way.
85+
86+The method is the one asked for when it was merged into the queue (the
87+merge box's choice, `merge_method` in the API), else the merge queue
88+rule's `merge_method` (merge commit unless set). Both must be methods the
89+repository and the branch's [rules](/guides/rules/) allow, or merging is
90+refused, saying which are; linear history rules out merge commits.
91+A commit message written then (`commit_title`, `commit_message`) is kept
92+with the entry; otherwise the repository's default message is used, worked
93+out when the entry is first built. Sign-off is added where the repository
94+requires it. The same limits apply as to merging directly: g1t makes at
95+most 1,000 changed files, 100 files merged line by line and 250 rebased
96+commits itself.
97+
7498 If every entry passes, the four can land one after another without being
7599 tested again. The next batch starts when nothing is being tested. A batch
76100 that takes longer than 45 minutes (`check_response_timeout_minutes`) is tested again.
110134 Each build has its own attempt token. A result from an old attempt cannot
111135 replace a retry or put a removed entry back in the queue. Workflow results
112136 apply only to the combined commit still being checked.
113−Retries use separate Git branches, so a late sandbox cannot overwrite the
137+Retries use separate Git branches, so a late build cannot overwrite the
114138 new attempt's branch. Workflow results wait until the whole group has been
115139 registered; a dispatch error does not count as a pass.
116140
117141 ## How entries land
118142
119143 Entries land in order. When an entry has passed and everything ahead of it
120−has landed, `main` moves to exactly the state that was tested. The issue
121−closes and the other pull requests for it are superseded, as with any
122−merge.
144+has landed, `main` moves to exactly the state that was tested: since each
145+state was built on the one ahead of it, that is a fast-forward to the
146+commits its method made, which are the commits its checks ran on. The pull
147+request is recorded as merged by its method, with the commit `main` moved
148+to as its merge commit. The issue closes and the other pull requests for
149+it are superseded, as with any merge.
123150
124151 Current reviews and branch rules are checked again before publication,
125−against the combined commit's checks. Once publication starts, removal,
152+against the combined commit's checks and the entry's merge method. Once publication starts, removal,
126153 closing or conversion to draft returns a conflict until it finishes. If the
127154 service stops after updating Git, the next queue poll resumes bookkeeping
128155 for that same commit instead of publishing a different branch tip.
145172 ## When an entry fails
146173
147174 An entry fails when its `merge_group` workflows or required checks fail
148−on the combined state, when it does not merge cleanly with what is ahead of it, or
149−when the state cannot be built.
175+on the combined state, when its change clashes with what is ahead of it, or
176+when the state cannot be built (a fast-forward that does not contain what
177+is ahead, or more than g1t makes itself). One that cannot be built leaves
178+the queue, and the entries behind it are built in the next batch without
179+it.
150180
151181 ### Who answers for it
152182
210240 changes together, or may not be deterministic. Diagnosis stops after three
211241 extra builds, retaining the last combination demonstrated to fail.
212242
213−These combinations are built in sandboxes as the queue's states are, on
214−`g1t-queue/<id>` branches that are deleted afterwards, and never land. They
243+These combinations are built as the queue's states are, each entry by
244+its own method and with the same commit messages, on `g1t-queue/<id>`
245+branches that are deleted afterwards, and never land. They
215246 do not hold up the queue: the entries behind are tested again at once. When
216247 a combination cannot be built or checked, or its checks are still running
217248 past the rule's timeout when the queue next moves, g1t stops and reports
+16−1
357357 those it refuses and nothing changes: squash or merge instead of rebasing,
358358 or merge the base in a clone.
359359
360+With the [merge queue](/guides/merge-queue/#how-entries-are-tested) on,
361+the method chosen (or the queue rule's, when none is) decides how the
362+pull request's state is built in the queue, and what is tested is what
363+lands.
364+
360365 ### Commit messages
361366
362367 A merge commit and a squash commit get a message. You can write it in the
522527
523528 A pull request that only has fallen behind its target, without conflicts,
524529 still merges: merging brings it up to date first, unless the repository
525−requires pull requests to be up to date.
530+requires pull requests to be up to date. Bringing it up to date makes a new
531+commit, so when the target branch requires checks, the merge box says
532+**Merging once checks pass** and the pull request lands when the required
533+checks pass on that commit, with nothing more to press. If one of them fails
534+there, it is not merged: the pull request says which check failed, and you
535+push a fix and merge again. With no required checks, it lands as soon as it
536+is up to date.
537+
538+If the repository does not answer in time while merging, the merge box says
539+g1t couldn't reach the repository. Merge again: if the first merge went
540+through meanwhile, merging again records it rather than merging twice.
526541
527542 ## Keeping it up to date
528543
+13−1
8080 `g1t.sh/<owner>/<project>/security/pulls/<number>`. Require **Dependency
8181 review** under **Settings → Branches** to block merges on it.
8282
83+A pull request has one review comment. When a later review says something
84+new, that comment is changed in place; when it says the same, the comment
85+is left alone. A push whose lockfile changes are the ones already reviewed,
86+such as catching the branch up with its base, is not reviewed again: the
87+check's result carries over to the new head.
88+
89+Advisories are published every day, so a review can be made again: **Re-run
90+dependency review** in the pull request's checks, or **Re-run** on its
91+Security checks page, takes the Write role. It updates the check and the
92+same comment.
93+
8394 In the repository's **Security settings**:
8495
8596 | Setting | Default | |
115126 | `GET /repos/{owner}/{name}/dependency-graph` | The graph, per lockfile. | `security:read` |
116127 | `GET /repos/{owner}/{name}/dependency-graph/sbom` | The SPDX document, in `sbom`. | `security:read` |
117128 | `GET /repos/{owner}/{name}/dependency-graph/compare/{basehead}` | What changed between two commits, and whether it passes review. | `security:read` |
129+| `POST /repos/{owner}/{name}/pulls/{number}/dependency-review/rerun` | Runs a pull request's Dependency review check again and returns the review. | `security:write` |
118130 | `GET /repos/{owner}/{name}/vulnerability-alerts` | Lists alerts; filter with `state`, `severity`, `ecosystem`, `package`. | `security:read` |
119131 | `GET /workspaces/{workspace}/vulnerability-alerts` | The same across a workspace. | `security:read` |
120132 | `GET /repos/{owner}/{name}/vulnerability-alerts/{id}` | One alert. | `security:read` |
121133 | `PATCH /repos/{owner}/{name}/vulnerability-alerts/{id}` | `state` `dismissed` with `reason` and `comment`, or `open`. | `security:write` |
122134
123135 Over MCP, the [`security` tool](/reference/mcp/#security) has
124−`dependency_graph`, `sbom`, `compare_dependencies`, `vulnerability_alerts`,
136+`dependency_graph`, `sbom`, `compare_dependencies`, `rerun_dependency_review`, `vulnerability_alerts`,
125137 `vulnerability_alert` and `update_vulnerability_alert`. Webhooks:
126138 `vulnerability_alert.created`, `.fixed`, `.dismissed` and `.reopened`.
+1−0
618618 | [`dependency_graph`](/reference/api/supply-chain/get-dependency-graph/) | Every package the lockfiles resolve, direct or transitive, with licenses. | `repo` | `security:read` |
619619 | [`sbom`](/reference/api/supply-chain/get-sbom/) | The dependency graph as an SPDX 2.3 document, in `sbom`. | `repo` | `security:read` |
620620 | [`compare_dependencies`](/reference/api/supply-chain/compare-dependencies/) | What changes between `basehead` (`base...head`), and whether it passes dependency review. | `repo`, `basehead` | `security:read` |
621+| [`rerun_dependency_review`](/reference/api/supply-chain/rerun-dependency-review/) | Runs a pull request's Dependency review check again; its one comment changes in place. Write role. | `repo`, `number` | `security:write` |
621622 | [`settings`](/reference/api/security-settings/get-security-settings/) | A repository's security settings, and whether the paid features are on. | `repo` | `security:read` |
622623 | [`update_settings`](/reference/api/security-settings/update-security-settings/) | Change `code_scanning_gate`, `dependency_review`, `review_fail_on`, `review_deny_licenses`, `review_comment`. Admin role, or a security manager. | `repo` | `security:write` |
623624 | [`workspace_settings`](/reference/api/security-settings/get-workspace-security-settings/) | A workspace's delegated bypass and validity checks. | `workspace` | `security:read` |
+0−0

Binary or large file; its contents are not shown.

+25−5
219219 );
220220 }
221221
222−/** Where one rule's review stands, in a few words. */
223−function ReviewStatus({ review }: { review: OwnerReview }) {
222+/**
223+ * Where one rule's review stands, in a few words. When the ruleset does not
224+ * require code owners' approval (`required` false), a rule nobody approved
225+ * yet is said plainly, not as something merging waits for.
226+ */
227+function ReviewStatus({ review, required }: { review: OwnerReview; required: boolean }) {
224228 const names = (list: string[]) => list.join(", ");
225229 if (review.changes_requested_by.length > 0) {
226230 return (
246250 </span>
247251 );
248252 }
253+ if (!required) {
254+ return (
255+ <span className="text-xs text-faint">
256+ {review.approved_by.length > 0 ? `Approved by ${names(review.approved_by)}` : "No approval yet"}
257+ </span>
258+ );
259+ }
249260 const more = Math.max(review.required - review.approved_by.length, 1);
250261 return (
251262 <span className="flex items-center gap-1 text-xs text-warn">
257268 }
258269
259270 /** One rule: its section, pattern and line, its owners, the files it covers, and where its review stands. */
260−function OwnerReviewRow({ review, fileHref }: { review: OwnerReview; fileHref: (line: number) => string }) {
271+function OwnerReviewRow({
272+ review,
273+ required,
274+ fileHref,
275+}: {
276+ review: OwnerReview;
277+ /** Whether the ruleset requires code owners' approval to merge. */
278+ required: boolean;
279+ fileHref: (line: number) => string;
280+}) {
261281 const many = review.files.length > 3;
262282 const files = (
263283 <ul className="mt-1 space-y-0.5">
277297 line {review.line}
278298 </Link>
279299 <span className="ml-auto">
280− <ReviewStatus review={review} />
300+ <ReviewStatus review={review} required={required} />
281301 </span>
282302 </div>
283303 <p className="mt-1 flex flex-wrap items-center gap-x-2 gap-y-0.5 text-xs text-muted">
343363 ) : (
344364 <ul className="divide-y divide-line">
345365 {owners.reviews.map((review) => (
346− <OwnerReviewRow key={`${review.section ?? ""}:${review.line}`} review={review} fileHref={fileHref} />
366+ <OwnerReviewRow key={`${review.section ?? ""}:${review.line}`} review={review} required={owners.required} fileHref={fileHref} />
347367 ))}
348368 </ul>
349369 )}
+24−1
2121 import { useMemo, useState } from "react";
2222 import { Form, Link } from "react-router";
2323
24−import type { CheckResult, CheckRun, CommitStatus, Job, Mergeable, Pull, RequiredCheck } from "@g1t/contracts";
24+import {
25+ type CheckResult,
26+ type CheckRun,
27+ type CommitStatus,
28+ DEPENDENCY_REVIEW_CHECK,
29+ type Job,
30+ type Mergeable,
31+ type Pull,
32+ type RequiredCheck,
33+} from "@g1t/contracts";
2534
2635 import { useAddresses } from "../lib/addresses";
2736 import { duration } from "./actions";
406415 pull.fork ? `/${pull.fork.namespace}/${pull.fork.name}/commit/${sha}` : `${base}/commit/${sha}`;
407416 const older = run != null && pull.headCommit != null && run.headCommit !== pull.headCommit;
408417 const failedRuns = statuses.filter((status) => statusStanding(status) === "failed" && runIdOf(status));
418+ // g1t's own Dependency review check, which anyone who may start runs can
419+ // have made again (after an advisory is published, say).
420+ const dependencyReview = statuses.some((status) => status.context === DEPENDENCY_REVIEW_CHECK && status.source === "security");
409421
410422 return (
411423 <div aria-busy={loading || undefined}>
458470 </Hint>
459471 </Form>
460472 ))}
473+ {canRerunWorkflows && dependencyReview && !settled && (
474+ <Form method="post">
475+ <input type="hidden" name="action" value="rerun-dependency-review" />
476+ <Hint label="Review its dependency changes again, with the advisories known now">
477+ <SubmitButton variant="outline" match={{ action: "rerun-dependency-review" }} pending="Re-running…">
478+ <RotateCw size={13} />
479+ Re-run dependency review
480+ </SubmitButton>
481+ </Hint>
482+ </Form>
483+ )}
461484 </div>
462485 </div>
463486 {error && (
Loading the diff…
Loading the diff…
Loading the diff…
Loading the diff…
Loading the diff…
Loading the diff…
Loading the diff…
Loading the diff…
Loading the diff…
Loading the diff…
Loading the diff…
Loading the diff…
Loading the diff…
Loading the diff…
Loading the diff…
Loading the diff…
Loading the diff…
Loading the diff…
Loading the diff…
Loading the diff…
Loading the diff…
Loading the diff…
Loading the diff…
Loading the diff…
Loading the diff…
Loading the diff…
Loading the diff…
Loading the diff…
Loading the diff…

Comments

Sign in to comment.