gitea.cli.utils.issue
issue
Helpers for addressing issues from the project CLI commands.
Gitea identifies an issue in two ways: the number shown in the web UI, which is local to a repository, and the global ID, which the project endpoints expect. The helpers here let the project commands take the number whenever the repository holding the issue is known, and turn the endpoints' rejections into errors that say what to do next.
The repository holding the issue is not the same thing as the repository holding the project: a repository project takes its issues from its own repository, while an organization project takes them from any repository of the organization, which is why the commands let that one be named separately.
One endpoint's rejection has to be manufactured here, because it does not
reject: moving an issue that is not on a project moves the row relating the two,
of which there is none, and Gitea answers that with a success and an empty body.
run_project_issue_move therefore finds the card before moving it, and reports
its absence itself - a success that moved nothing is the one failure a caller
cannot see.
The same walk answers a different question for run_project_issue_remove. The
removal endpoint takes the column the card is in, which is not a column the
caller is choosing but one the board already knows, so --column-id is optional
there and the walk supplies it - and an issue with no card is reported as having
none rather than removed from a column picked for it. This is what makes the
option mean two things across the commands: a destination for add and move,
the card's present whereabouts for remove.
Looking before the move is what makes the failure legible; reading the card back afterwards is what makes the success true. The status code says only that the request was accepted, so the move is followed by a listing of the target column, and the command exits zero having seen the card there rather than having assumed it. A removal whose column the walk supplied is read back as well, and against the whole board rather than that column: the column named holds no card whether the removal took it off or the card had already moved elsewhere, so only a walk finding none anywhere tells the two apart. What that walk establishes is the card's absence rather than the request's fate - an instance may refuse a removal naming a column that does not hold the card, and one tried by hand answers it with a 404, but a status code is an answer about the call and never about the card. Neither half makes either pair atomic - Gitea has no conditional move and no conditional delete, so a card taken off the board, or put back on it, between the two reads is still a card the command has reported on - and the messages say which of "no card", "not where it was sent", "still on the board" and "could not be confirmed" happened rather than collapsing them into one.
Classes
Functions:
gitea.cli.utils.issue.resolve_issue_id
Resolve a repository issue number to the global issue ID.
When the repository holding the issue is known, issue_number is the number
shown in the web UI and is looked up against that repository. When it is
not, there is nothing to look the number up in, so the value is taken to be
the global ID already and returned unchanged.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
client
|
Gitea
|
The Gitea client used for the lookup. |
required |
owner
|
str
|
The owner of the repository. |
required |
repository
|
str | None
|
The name of the repository holding the issue, or None when it is not known. |
required |
issue_number
|
int
|
The issue number of the repository, or the global issue ID
when |
required |
Returns:
| Type | Description |
|---|---|
int
|
The global issue ID that the project endpoints expect. |
Raises:
| Type | Description |
|---|---|
CommandError
|
If the repository has no issue with that number, the lookup was refused, the instance could not be reached, or the request failed without reaching a response. |
Source code in src/gitea/cli/utils/issue.py
gitea.cli.utils.issue.run_project_issue_call
run_project_issue_call(
*,
client: Gitea,
call: Callable[
[int], tuple[dict[str, Any], dict[str, Any]]
],
action: str,
owner: str,
project_id: int,
issue_number: int,
issue_repository: str | None,
) -> tuple[dict[str, Any], dict[str, Any]]
Run a project issue call against the issue the user named.
The issue is resolved first, so --issue-id can be the number shown in the
web UI, and a rejection by the project endpoint is reported as an error
naming both the issue and what to check, rather than as a bare HTTP status.
On success the resolved global ID is recorded in the metadata, so the caller
can see which issue was acted on.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
client
|
Gitea
|
The Gitea client to call. |
required |
call
|
Callable[[int], tuple[dict[str, Any], dict[str, Any]]]
|
The API call, taking the resolved global issue ID. |
required |
action
|
str
|
The verb describing the call, used in the error message. |
required |
owner
|
str
|
The owner of the repository. |
required |
project_id
|
int
|
The ID of the project. |
required |
issue_number
|
int
|
The value the user passed as --issue-id. |
required |
issue_repository
|
str | None
|
The name of the repository holding the issue, or None
when it is not known and |
required |
Returns:
| Type | Description |
|---|---|
dict[str, Any]
|
A tuple containing the payload and the metadata, the latter carrying the |
dict[str, Any]
|
resolved global issue ID whenever the number was resolved. |
Raises:
| Type | Description |
|---|---|
CommandError
|
If the issue could not be resolved, the call was refused, the instance could not be reached, or the request failed without reaching a response. |
Source code in src/gitea/cli/utils/issue.py
gitea.cli.utils.issue.run_project_issue_move
run_project_issue_move(
*,
client: Gitea,
owner: str,
repository: str | None,
project_id: int,
issue_number: int,
column_id: int,
sorting: int | None,
issue_repository: str | None,
add_if_missing: bool,
) -> tuple[dict[str, Any], dict[str, Any]]
Move an issue's card to a column of a project, and confirm it arrived.
Gitea's move endpoint moves the row relating an issue to a project, and an
issue that is not on the project has no such row: the endpoint answers the
call with a success and an empty body, and moves nothing. A caller reading
that as a move made is left believing a card is on a board that has none,
which is what the board is walked here to prevent. The card is looked for
first, and the move is made only once it has been found; when it has not,
the command either says so or, with add_if_missing, puts the issue in the
target column instead - which is what project issue add does, and the only
way to get a card there in one call.
Whichever call was made, the target column is then read back, because the
success it answered with is the thing this endpoint has already been shown
not to mean. Returning normally therefore says the card was seen in
column_id, not that Gitea accepted a request to put it there. It does not
say the card is still there: the two reads are separate requests, and no
conditional move exists to make them one.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
client
|
Gitea
|
The Gitea client to call. |
required |
owner
|
str
|
The owner of the repository or organization holding the project. |
required |
repository
|
str | None
|
The name of the repository holding the project, or None for an organization project. |
required |
project_id
|
int
|
The ID of the project. |
required |
issue_number
|
int
|
The value the user passed as --issue-id. |
required |
column_id
|
int
|
The target column ID. |
required |
sorting
|
int | None
|
The position within the column, ascending. |
required |
issue_repository
|
str | None
|
The name of the repository holding the issue, or None
when it is not known and |
required |
add_if_missing
|
bool
|
Whether to add the issue to the target column when no column of the project holds a card for it. |
required |
Returns:
| Type | Description |
|---|---|
dict[str, Any]
|
A tuple containing the payload and the metadata, the latter carrying the |
dict[str, Any]
|
resolved global issue ID whenever the number was resolved. |
Raises:
| Type | Description |
|---|---|
CommandError
|
If the issue could not be resolved, the board could not be
read, the issue has no card on the project and |
Source code in src/gitea/cli/utils/issue.py
1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 | |
gitea.cli.utils.issue.run_project_issue_remove
run_project_issue_remove(
*,
client: Gitea,
owner: str,
repository: str | None,
project_id: int,
issue_number: int,
column_id: int | None,
issue_repository: str | None,
) -> tuple[dict[str, Any], dict[str, Any]]
Take an issue's card off a project, from the column it is in.
Gitea's removal endpoint takes the column the card is in, not a column the
caller is choosing: unlike the --column-id of add and move, which says
where the card is to end up, this one says where it already is. That is
something the board can be asked, so column_id may be None, and the column
holding the card is then found by walking the project's columns - the same
walk the move makes before moving a card. An issue with no card on the
project is reported as having none, rather than removed from a column chosen
for it.
A column this command found is one it also checks: the board is walked again after the removal, and the command exits zero having seen no column of the project holding a card for the issue. The two calls are separate requests against a board anything may edit, so a card moved between the walk and the removal leaves the removal addressed to the column the card has left, which is a removal with nothing to do. Whether the instance refuses that call or answers it with a success is the instance's business: what a caller is told here is that no column of the project holds the card, which is the claim the exit status makes and the one only a read can support. It is a narrower window and not a closed one - Gitea has no conditional delete, so a card put back on the board after the confirming walk is a card this command has already reported on.
A column_id that was given is passed on as it stands. Nothing is looked up
for it, before or after: this is a removal the caller addressed, so the
column it was told to use is the column it uses, whether or not the card is
there, and reading the board back would be checking a claim the command never
made. What the instance makes of such a call - a refusal, or a success that
removed nothing - is reported as it came.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
client
|
Gitea
|
The Gitea client to call. |
required |
owner
|
str
|
The owner of the repository or organization holding the project. |
required |
repository
|
str | None
|
The name of the repository holding the project, or None for an organization project. |
required |
project_id
|
int
|
The ID of the project. |
required |
issue_number
|
int
|
The value the user passed as --issue-id. |
required |
column_id
|
int | None
|
The column holding the card, or None to find it on the board. |
required |
issue_repository
|
str | None
|
The name of the repository holding the issue, or None
when it is not known and |
required |
Returns:
| Type | Description |
|---|---|
dict[str, Any]
|
A tuple containing the payload and the metadata, the latter carrying the |
dict[str, Any]
|
resolved global issue ID whenever the number was resolved, and the column |
tuple[dict[str, Any], dict[str, Any]]
|
the card was removed from whenever that was looked up. |
Raises:
| Type | Description |
|---|---|
CommandError
|
If the issue could not be resolved, the board could not be read, the issue has no card on the project, the call was refused, a column of the project still holds the card afterwards or that could not be confirmed, the instance could not be reached, or the request failed without reaching a response. |
Source code in src/gitea/cli/utils/issue.py
1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259 1260 1261 1262 1263 1264 1265 1266 1267 1268 1269 1270 1271 1272 1273 1274 1275 1276 | |