gitd 0.10.0__tar.gz → 0.12.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: gitd
3
- Version: 0.10.0
3
+ Version: 0.12.0
4
4
  Summary: Client for gitd: instant, secretless git checkouts for agent sandboxes
5
5
  Project-URL: Homepage, https://github.com/dooservice/gitd
6
6
  Project-URL: Source, https://github.com/dooservice/gitd/tree/main/sdk/python
@@ -46,12 +46,24 @@ No call takes a credential: gitd reads and publishes with the ones it keeps.
46
46
  | `update(path, *, branch, submodules, on_progress)` | To the tip of its branch, or of the branch given |
47
47
  | `checkout(path, commit, *, submodules, on_progress)` | To a commit, as a rollback does |
48
48
  | `describe(path)` | Its repository, commit, branch, uncommitted changes and submodules |
49
- | `publish(path, branch)` | Its commits pushed to a new branch |
49
+ | `publish(path, branch, *, requested_by, pull_request, provenance, sandbox, update)` | Its commits pushed to a new branch, or with `update` an earlier publish's branch moved forward; its pull request opened or updated |
50
50
  | `remove(path)` | Deleted; its pool stays |
51
51
  | `probe(url)` | Whether it can be read, its default branch and branches |
52
52
  | `info()` | Which gitd answers, and how it makes workspaces here and why |
53
53
  | `audit(*, since, url, limit)` | Every publish, done or refused, newest first |
54
54
 
55
+ ```python
56
+ from gitd import PullRequestOptions
57
+
58
+ published = gitd.publish(
59
+ workspace.path, "agents/fix-login", update=True,
60
+ pull_request=PullRequestOptions(open=True, submodules=True, title="Fix the login", body="…"),
61
+ )
62
+ print(published.pull_request.url, published.pull_request.updated)
63
+ for submodule in published.submodule_pull_requests: # merged first, with a merge commit
64
+ print(submodule.path, submodule.pull_request or submodule.refused)
65
+ ```
66
+
55
67
  A refusal raises `GitdError`, with `reason` (`AUTH_REQUIRED`, `NOT_FOUND`, `PATH_REFUSED`,
56
68
  `BRANCH_REFUSED`, `BUSY`, …) and `said`, what git said. Decide from the reason, never from
57
69
  the message.
@@ -29,12 +29,24 @@ No call takes a credential: gitd reads and publishes with the ones it keeps.
29
29
  | `update(path, *, branch, submodules, on_progress)` | To the tip of its branch, or of the branch given |
30
30
  | `checkout(path, commit, *, submodules, on_progress)` | To a commit, as a rollback does |
31
31
  | `describe(path)` | Its repository, commit, branch, uncommitted changes and submodules |
32
- | `publish(path, branch)` | Its commits pushed to a new branch |
32
+ | `publish(path, branch, *, requested_by, pull_request, provenance, sandbox, update)` | Its commits pushed to a new branch, or with `update` an earlier publish's branch moved forward; its pull request opened or updated |
33
33
  | `remove(path)` | Deleted; its pool stays |
34
34
  | `probe(url)` | Whether it can be read, its default branch and branches |
35
35
  | `info()` | Which gitd answers, and how it makes workspaces here and why |
36
36
  | `audit(*, since, url, limit)` | Every publish, done or refused, newest first |
37
37
 
38
+ ```python
39
+ from gitd import PullRequestOptions
40
+
41
+ published = gitd.publish(
42
+ workspace.path, "agents/fix-login", update=True,
43
+ pull_request=PullRequestOptions(open=True, submodules=True, title="Fix the login", body="…"),
44
+ )
45
+ print(published.pull_request.url, published.pull_request.updated)
46
+ for submodule in published.submodule_pull_requests: # merged first, with a merge commit
47
+ print(submodule.path, submodule.pull_request or submodule.refused)
48
+ ```
49
+
38
50
  A refusal raises `GitdError`, with `reason` (`AUTH_REQUIRED`, `NOT_FOUND`, `PATH_REFUSED`,
39
51
  `BRANCH_REFUSED`, `BUSY`, …) and `said`, what git said. Decide from the reason, never from
40
52
  the message.
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "gitd"
7
- version = "0.10.0"
7
+ version = "0.12.0"
8
8
  description = "Client for gitd: instant, secretless git checkouts for agent sandboxes"
9
9
  readme = "README.md"
10
10
  license = "Apache-2.0"
@@ -23,6 +23,7 @@ from .models import (
23
23
  Refusal,
24
24
  Strategy,
25
25
  Submodule,
26
+ SubmodulePullRequest,
26
27
  Workspace,
27
28
  )
28
29
  from .publishing_settings import (
@@ -78,6 +79,7 @@ __all__ = [
78
79
  "Refusal",
79
80
  "Strategy",
80
81
  "Submodule",
82
+ "SubmodulePullRequest",
81
83
  "Workspace",
82
84
  "WarmLayer",
83
85
  "Endpoint",
@@ -137,13 +137,20 @@ class Gitd:
137
137
  pull_request: PullRequestOptions | None = None,
138
138
  provenance: Provenance | None = None,
139
139
  sandbox: str = "",
140
+ update: bool = False,
140
141
  ) -> Published:
141
142
  """Pushes what was committed in a workspace to a new branch, with the credential gitd
142
143
  keeps, and opens its pull request when the publishing settings or pull_request say
143
144
  so. requested_by is who asked for the work, as their account on the host. With
144
- sandbox, and path empty, publishes the branch a sandbox pushed through the endpoint."""
145
+ sandbox, and path empty, publishes the branch a sandbox pushed through the endpoint.
146
+
147
+ With update, the branch may exist from an earlier publish: it is moved forward, only
148
+ ever as a fast-forward (BRANCH_EXISTS otherwise), and the pull request open from it is
149
+ updated rather than another opened. An update bringing nothing beyond what gitd
150
+ published to the branch pushes nothing and still opens or updates the pull requests,
151
+ so a publish whose pull request failed is retried by publishing again."""
145
152
  request: Any = messages.PublishRequest(
146
- path=path, branch=branch, requested_by=requested_by, sandbox=sandbox
153
+ path=path, branch=branch, requested_by=requested_by, sandbox=sandbox, update=update
147
154
  )
148
155
  if pull_request is not None:
149
156
  request.pull_request.CopyFrom(pull_request.to_message())
@@ -287,6 +287,10 @@
287
287
  {
288
288
  "name": "REASON_LIMIT_REACHED",
289
289
  "number": 15
290
+ },
291
+ {
292
+ "name": "REASON_BRANCH_EXISTS",
293
+ "number": 16
290
294
  }
291
295
  ]
292
296
  }
@@ -989,6 +993,13 @@
989
993
  "label": "LABEL_OPTIONAL",
990
994
  "type": "TYPE_STRING",
991
995
  "jsonName": "sandbox"
996
+ },
997
+ {
998
+ "name": "update",
999
+ "number": 8,
1000
+ "label": "LABEL_OPTIONAL",
1001
+ "type": "TYPE_BOOL",
1002
+ "jsonName": "update"
992
1003
  }
993
1004
  ]
994
1005
  },
@@ -1064,6 +1075,13 @@
1064
1075
  "oneofIndex": 0,
1065
1076
  "jsonName": "draft",
1066
1077
  "proto3Optional": true
1078
+ },
1079
+ {
1080
+ "name": "submodules",
1081
+ "number": 6,
1082
+ "label": "LABEL_OPTIONAL",
1083
+ "type": "TYPE_BOOL",
1084
+ "jsonName": "submodules"
1067
1085
  }
1068
1086
  ],
1069
1087
  "oneofDecl": [
@@ -1088,6 +1106,48 @@
1088
1106
  "label": "LABEL_OPTIONAL",
1089
1107
  "type": "TYPE_INT64",
1090
1108
  "jsonName": "number"
1109
+ },
1110
+ {
1111
+ "name": "updated",
1112
+ "number": 3,
1113
+ "label": "LABEL_OPTIONAL",
1114
+ "type": "TYPE_BOOL",
1115
+ "jsonName": "updated"
1116
+ }
1117
+ ]
1118
+ },
1119
+ {
1120
+ "name": "SubmodulePullRequest",
1121
+ "field": [
1122
+ {
1123
+ "name": "path",
1124
+ "number": 1,
1125
+ "label": "LABEL_OPTIONAL",
1126
+ "type": "TYPE_STRING",
1127
+ "jsonName": "path"
1128
+ },
1129
+ {
1130
+ "name": "url",
1131
+ "number": 2,
1132
+ "label": "LABEL_OPTIONAL",
1133
+ "type": "TYPE_STRING",
1134
+ "jsonName": "url"
1135
+ },
1136
+ {
1137
+ "name": "pull_request",
1138
+ "number": 3,
1139
+ "label": "LABEL_OPTIONAL",
1140
+ "type": "TYPE_MESSAGE",
1141
+ "typeName": ".gitd.v1.OpenedPullRequest",
1142
+ "jsonName": "pullRequest"
1143
+ },
1144
+ {
1145
+ "name": "failure",
1146
+ "number": 4,
1147
+ "label": "LABEL_OPTIONAL",
1148
+ "type": "TYPE_MESSAGE",
1149
+ "typeName": ".gitd.v1.GitFailure",
1150
+ "jsonName": "failure"
1091
1151
  }
1092
1152
  ]
1093
1153
  },
@@ -1165,6 +1225,14 @@
1165
1225
  "type": "TYPE_MESSAGE",
1166
1226
  "typeName": ".gitd.v1.GitFailure",
1167
1227
  "jsonName": "pullRequestFailure"
1228
+ },
1229
+ {
1230
+ "name": "submodule_pull_requests",
1231
+ "number": 6,
1232
+ "label": "LABEL_REPEATED",
1233
+ "type": "TYPE_MESSAGE",
1234
+ "typeName": ".gitd.v1.SubmodulePullRequest",
1235
+ "jsonName": "submodulePullRequests"
1168
1236
  }
1169
1237
  ]
1170
1238
  },
@@ -1932,6 +2000,14 @@
1932
2000
  "label": "LABEL_OPTIONAL",
1933
2001
  "type": "TYPE_STRING",
1934
2002
  "jsonName": "sandbox"
2003
+ },
2004
+ {
2005
+ "name": "submodule_pull_requests",
2006
+ "number": 14,
2007
+ "label": "LABEL_REPEATED",
2008
+ "type": "TYPE_MESSAGE",
2009
+ "typeName": ".gitd.v1.SubmodulePullRequest",
2010
+ "jsonName": "submodulePullRequests"
1935
2011
  }
1936
2012
  ]
1937
2013
  },
@@ -200,15 +200,42 @@ class Refusal:
200
200
  return messages.REASON.name(failure.reason).removeprefix(REASON_PREFIX)
201
201
 
202
202
 
203
+ @dataclass(frozen=True)
204
+ class SubmodulePullRequest:
205
+ """The pull request of one submodule, at path in the workspace and of the repository at
206
+ url, or why it could not be opened."""
207
+
208
+ path: str
209
+ url: str
210
+ pull_request: OpenedPullRequest | None = None
211
+ refused: Refusal | None = None
212
+
213
+ @classmethod
214
+ def from_message(cls, submodule: Any) -> SubmodulePullRequest:
215
+ return cls(
216
+ path=submodule.path,
217
+ url=submodule.url,
218
+ pull_request=(
219
+ OpenedPullRequest.from_message(submodule.pull_request)
220
+ if submodule.HasField("pull_request")
221
+ else None
222
+ ),
223
+ refused=Refusal.from_message(submodule.failure) if submodule.HasField("failure") else None,
224
+ )
225
+
226
+
203
227
  @dataclass(frozen=True)
204
228
  class Published:
205
229
  """What a publish pushed: the workspace's repository first, then each submodule; the
206
- pull request it opened, or why it could not, the branch being published either way."""
230
+ pull request it opened or updated, or why it could not, the branch being published
231
+ either way; and each submodule's, when asked for. An update that brought nothing new
232
+ lists the workspace's repository with no subjects."""
207
233
 
208
234
  branch: str
209
235
  repositories: list[PublishedRepository]
210
236
  pull_request: OpenedPullRequest | None = None
211
237
  pull_request_refused: Refusal | None = None
238
+ submodule_pull_requests: list[SubmodulePullRequest] = field(default_factory=list)
212
239
 
213
240
  @classmethod
214
241
  def from_message(cls, response: Any) -> Published:
@@ -226,6 +253,9 @@ class Published:
226
253
  if response.HasField("pull_request_failure")
227
254
  else None
228
255
  ),
256
+ submodule_pull_requests=[
257
+ SubmodulePullRequest.from_message(submodule) for submodule in response.submodule_pull_requests
258
+ ],
229
259
  )
230
260
 
231
261
 
@@ -310,6 +340,7 @@ class AuditEntry:
310
340
  pull_request_refused: Refusal | None = None
311
341
  change: ConfigurationChange | None = None
312
342
  provenance: Provenance | None = None
343
+ submodule_pull_requests: list[SubmodulePullRequest] = field(default_factory=list)
313
344
 
314
345
  @classmethod
315
346
  def from_message(cls, entry: Any) -> AuditEntry:
@@ -332,4 +363,7 @@ class AuditEntry:
332
363
  ),
333
364
  change=ConfigurationChange.from_message(entry.change) if entry.HasField("change") else None,
334
365
  provenance=Provenance.from_message(entry.provenance) if entry.HasField("provenance") else None,
366
+ submodule_pull_requests=[
367
+ SubmodulePullRequest.from_message(submodule) for submodule in entry.submodule_pull_requests
368
+ ],
335
369
  )
@@ -156,17 +156,20 @@ class Preset:
156
156
  class PullRequestOptions:
157
157
  """A publish's own say on its pull request: open one even when the settings open them
158
158
  only when asked, its title (the newest commit's subject when empty), the text before
159
- what gitd checked, the branch it merges into, and whether it is a draft."""
159
+ what gitd checked, the branch it merges into, and whether it is a draft. submodules
160
+ opens one too in each submodule's repository, with the same title, into the branch
161
+ .gitmodules names for it or its default branch: to be merged first, with a merge commit."""
160
162
 
161
163
  open: bool = False
162
164
  title: str = ""
163
165
  body: str = ""
164
166
  base: str = ""
165
167
  draft: bool | None = None
168
+ submodules: bool = False
166
169
 
167
170
  def to_message(self) -> Any:
168
171
  message: Any = messages.PullRequestOptions(
169
- open=self.open, title=self.title, body=self.body, base=self.base
172
+ open=self.open, title=self.title, body=self.body, base=self.base, submodules=self.submodules
170
173
  )
171
174
  if self.draft is not None:
172
175
  message.draft = self.draft
@@ -201,11 +204,13 @@ class Provenance:
201
204
 
202
205
  @dataclass(frozen=True)
203
206
  class OpenedPullRequest:
204
- """A pull request gitd opened."""
207
+ """A pull request gitd opened; updated says it was already open from the branch, and
208
+ gitd updated its title and body."""
205
209
 
206
210
  url: str
207
211
  number: int
212
+ updated: bool = False
208
213
 
209
214
  @classmethod
210
215
  def from_message(cls, opened: Any) -> OpenedPullRequest:
211
- return cls(url=opened.url, number=opened.number)
216
+ return cls(url=opened.url, number=opened.number, updated=opened.updated)
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes