detached 6d7ddba

refactor(ci): reserve the removed storage fields and type the cancel reason

The storage schema marks the field numbers it dropped as reserved, and the
cancel reason of a job is an enum with an explicit mapping instead of an index
into a slice. The comment of the event stream names the live log feed.
commit
6d7ddbac1cb5ce5a4753e1988ddbaf40b49342be
author
brice · · 2026-10-12 19:22 UTC
parent
916e849
signature
GPG VerifiedCD88F9E564E0102646FB6077A1A07C7C7C3E349D · arch-gpg Verified for the committer email
5 files · +174 -58
M gen/ermite/storage/ci.pb.go +110 -49
@@ -316,6 +316,59 @@ func (CIIsolation) EnumDescriptor() ([]byte, []int) {
316316 return file_ermite_storage_ci_proto_rawDescGZIP(), []int{4}
317317 }
318318
319+// CICancelReason says why a job is asked to stop.
320+type CICancelReason int32
321+
322+const (
323+ CICancelReason_CI_CANCEL_REASON_UNSPECIFIED CICancelReason = 0
324+ CICancelReason_CI_CANCEL_REASON_USER CICancelReason = 1
325+ CICancelReason_CI_CANCEL_REASON_FAIL_FAST CICancelReason = 2
326+ CICancelReason_CI_CANCEL_REASON_TIMEOUT CICancelReason = 3
327+)
328+
329+// Enum value maps for CICancelReason.
330+var (
331+ CICancelReason_name = map[int32]string{
332+ 0: "CI_CANCEL_REASON_UNSPECIFIED",
333+ 1: "CI_CANCEL_REASON_USER",
334+ 2: "CI_CANCEL_REASON_FAIL_FAST",
335+ 3: "CI_CANCEL_REASON_TIMEOUT",
336+ }
337+ CICancelReason_value = map[string]int32{
338+ "CI_CANCEL_REASON_UNSPECIFIED": 0,
339+ "CI_CANCEL_REASON_USER": 1,
340+ "CI_CANCEL_REASON_FAIL_FAST": 2,
341+ "CI_CANCEL_REASON_TIMEOUT": 3,
342+ }
343+)
344+
345+func (x CICancelReason) Enum() *CICancelReason {
346+ p := new(CICancelReason)
347+ *p = x
348+ return p
349+}
350+
351+func (x CICancelReason) String() string {
352+ return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x))
353+}
354+
355+func (CICancelReason) Descriptor() protoreflect.EnumDescriptor {
356+ return file_ermite_storage_ci_proto_enumTypes[5].Descriptor()
357+}
358+
359+func (CICancelReason) Type() protoreflect.EnumType {
360+ return &file_ermite_storage_ci_proto_enumTypes[5]
361+}
362+
363+func (x CICancelReason) Number() protoreflect.EnumNumber {
364+ return protoreflect.EnumNumber(x)
365+}
366+
367+// Deprecated: Use CICancelReason.Descriptor instead.
368+func (CICancelReason) EnumDescriptor() ([]byte, []int) {
369+ return file_ermite_storage_ci_proto_rawDescGZIP(), []int{5}
370+}
371+
319372 // CIRun is stored under "run/<repo>/<id:020d>".
320373 type CIRun struct {
321374 state protoimpl.MessageState `protogen:"open.v1"`
@@ -722,7 +775,7 @@ type CIJob struct {
722775 AckedAt *timestamppb.Timestamp `protobuf:"bytes,30,opt,name=acked_at,json=ackedAt,proto3" json:"acked_at,omitempty"`
723776 AssignCancels int32 `protobuf:"varint,31,opt,name=assign_cancels,json=assignCancels,proto3" json:"assign_cancels,omitempty"`
724777 TokenValidUntil *timestamppb.Timestamp `protobuf:"bytes,32,opt,name=token_valid_until,json=tokenValidUntil,proto3" json:"token_valid_until,omitempty"`
725- CancelReason int32 `protobuf:"varint,33,opt,name=cancel_reason,json=cancelReason,proto3" json:"cancel_reason,omitempty"`
778+ CancelReason CICancelReason `protobuf:"varint,33,opt,name=cancel_reason,json=cancelReason,proto3,enum=ermite.storage.CICancelReason" json:"cancel_reason,omitempty"`
726779 CancelMessage string `protobuf:"bytes,34,opt,name=cancel_message,json=cancelMessage,proto3" json:"cancel_message,omitempty"`
727780 CancelRequestedAt *timestamppb.Timestamp `protobuf:"bytes,35,opt,name=cancel_requested_at,json=cancelRequestedAt,proto3" json:"cancel_requested_at,omitempty"`
728781 // Set when the job is planned: runs-on, name and contexts are evaluated.
@@ -992,11 +1045,11 @@ func (x *CIJob) GetTokenValidUntil() *timestamppb.Timestamp {
9921045 return nil
9931046 }
9941047
995-func (x *CIJob) GetCancelReason() int32 {
1048+func (x *CIJob) GetCancelReason() CICancelReason {
9961049 if x != nil {
9971050 return x.CancelReason
9981051 }
999- return 0
1052+ return CICancelReason_CI_CANCEL_REASON_UNSPECIFIED
10001053 }
10011054
10021055 func (x *CIJob) GetCancelMessage() string {
@@ -1289,7 +1342,7 @@ var File_ermite_storage_ci_proto protoreflect.FileDescriptor
12891342
12901343 const file_ermite_storage_ci_proto_rawDesc = "" +
12911344 "\n" +
1292- "\x17ermite/storage/ci.proto\x12\x0eermite.storage\x1a\x1fgoogle/protobuf/timestamp.proto\"\xbf\x05\n" +
1345+ "\x17ermite/storage/ci.proto\x12\x0eermite.storage\x1a\x1fgoogle/protobuf/timestamp.proto\"\xcb\x05\n" +
12931346 "\x05CIRun\x12\x12\n" +
12941347 "\x04repo\x18\x01 \x01(\tR\x04repo\x12\x0e\n" +
12951348 "\x02id\x18\x02 \x01(\x03R\x02id\x12\x16\n" +
@@ -1314,13 +1367,13 @@ const file_ermite_storage_ci_proto_rawDesc = "" +
13141367 "started_at\x18\x10 \x01(\v2\x1a.google.protobuf.TimestampR\tstartedAt\x12=\n" +
13151368 "\fcompleted_at\x18\x11 \x01(\v2\x1a.google.protobuf.TimestampR\vcompletedAt\x12)\n" +
13161369 "\x10cancel_requested\x18\x14 \x01(\bR\x0fcancelRequested\x12J\n" +
1317- "\x13cancel_requested_at\x18\x15 \x01(\v2\x1a.google.protobuf.TimestampR\x11cancelRequestedAt\"~\n" +
1370+ "\x13cancel_requested_at\x18\x15 \x01(\v2\x1a.google.protobuf.TimestampR\x11cancelRequestedAtJ\x04\b\x12\x10\x13J\x04\b\x13\x10\x14\"~\n" +
13181371 "\vCIRunSource\x12\x15\n" +
13191372 "\x06run_id\x18\x04 \x01(\x03R\x05runId\x12#\n" +
13201373 "\rworkflow_yaml\x18\x01 \x01(\tR\fworkflowYaml\x12\x1f\n" +
13211374 "\vgithub_json\x18\x02 \x01(\tR\n" +
13221375 "githubJson\x12\x12\n" +
1323- "\x04repo\x18\x03 \x01(\tR\x04repo\"\xd9\x02\n" +
1376+ "\x04repo\x18\x03 \x01(\tR\x04repo\"\xe5\x02\n" +
13241377 "\x06CIStep\x12\x16\n" +
13251378 "\x06number\x18\x01 \x01(\x05R\x06number\x12\x12\n" +
13261379 "\x04name\x18\x02 \x01(\tR\x04name\x121\n" +
@@ -1332,7 +1385,8 @@ const file_ermite_storage_ci_proto_rawDesc = "" +
13321385 "started_at\x18\x05 \x01(\v2\x1a.google.protobuf.TimestampR\tstartedAt\x12=\n" +
13331386 "\fcompleted_at\x18\x06 \x01(\v2\x1a.google.protobuf.TimestampR\vcompletedAt\x12\x1b\n" +
13341387 "\tlog_start\x18\a \x01(\x03R\blogStart\x12\x1b\n" +
1335- "\thas_lines\x18\t \x01(\bR\bhasLines\"\x94\f\n" +
1388+ "\thas_lines\x18\t \x01(\bR\bhasLinesJ\x04\b\b\x10\tJ\x04\b\n" +
1389+ "\x10\v\"\xba\f\n" +
13361390 "\x05CIJob\x12\x0e\n" +
13371391 "\x02id\x18\x01 \x01(\tR\x02id\x12\x15\n" +
13381392 "\x06run_id\x18\x02 \x01(\x03R\x05runId\x12\x18\n" +
@@ -1375,8 +1429,8 @@ const file_ermite_storage_ci_proto_rawDesc = "" +
13751429 "assignedAt\x125\n" +
13761430 "\backed_at\x18\x1e \x01(\v2\x1a.google.protobuf.TimestampR\aackedAt\x12%\n" +
13771431 "\x0eassign_cancels\x18\x1f \x01(\x05R\rassignCancels\x12F\n" +
1378- "\x11token_valid_until\x18 \x01(\v2\x1a.google.protobuf.TimestampR\x0ftokenValidUntil\x12#\n" +
1379- "\rcancel_reason\x18! \x01(\x05R\fcancelReason\x12%\n" +
1432+ "\x11token_valid_until\x18 \x01(\v2\x1a.google.protobuf.TimestampR\x0ftokenValidUntil\x12C\n" +
1433+ "\rcancel_reason\x18! \x01(\x0e2\x1e.ermite.storage.CICancelReasonR\fcancelReason\x12%\n" +
13801434 "\x0ecancel_message\x18\" \x01(\tR\rcancelMessage\x12J\n" +
13811435 "\x13cancel_requested_at\x18# \x01(\v2\x1a.google.protobuf.TimestampR\x11cancelRequestedAt\x12\x18\n" +
13821436 "\aplanned\x18% \x01(\bR\aplanned\x12\x1f\n" +
@@ -1385,7 +1439,7 @@ const file_ermite_storage_ci_proto_rawDesc = "" +
13851439 "\rcontexts_json\x18' \x01(\tR\fcontextsJson\x1a:\n" +
13861440 "\fOutputsEntry\x12\x10\n" +
13871441 "\x03key\x18\x01 \x01(\tR\x03key\x12\x14\n" +
1388- "\x05value\x18\x02 \x01(\tR\x05value:\x028\x01\"\xe5\x03\n" +
1442+ "\x05value\x18\x02 \x01(\tR\x05value:\x028\x01J\x04\b$\x10%\"\xe5\x03\n" +
13891443 "\aCICheck\x12\x0e\n" +
13901444 "\x02id\x18\x01 \x01(\tR\x02id\x12\x12\n" +
13911445 "\x04repo\x18\x02 \x01(\tR\x04repo\x12\x10\n" +
@@ -1447,7 +1501,12 @@ const file_ermite_storage_ci_proto_rawDesc = "" +
14471501 "\x18CI_ISOLATION_UNSPECIFIED\x10\x00\x12\x13\n" +
14481502 "\x0fCI_ISOLATION_VM\x10\x01\x12!\n" +
14491503 "\x1dCI_ISOLATION_CONTAINER_SYSBOX\x10\x02\x12%\n" +
1450- "!CI_ISOLATION_CONTAINER_PRIVILEGED\x10\x03B/Z-bnema.dev/ermite/gen/ermite/storage;storagepbb\x06proto3"
1504+ "!CI_ISOLATION_CONTAINER_PRIVILEGED\x10\x03*\x8b\x01\n" +
1505+ "\x0eCICancelReason\x12 \n" +
1506+ "\x1cCI_CANCEL_REASON_UNSPECIFIED\x10\x00\x12\x19\n" +
1507+ "\x15CI_CANCEL_REASON_USER\x10\x01\x12\x1e\n" +
1508+ "\x1aCI_CANCEL_REASON_FAIL_FAST\x10\x02\x12\x1c\n" +
1509+ "\x18CI_CANCEL_REASON_TIMEOUT\x10\x03B/Z-bnema.dev/ermite/gen/ermite/storage;storagepbb\x06proto3"
14511510
14521511 var (
14531512 file_ermite_storage_ci_proto_rawDescOnce sync.Once
@@ -1461,7 +1520,7 @@ func file_ermite_storage_ci_proto_rawDescGZIP() []byte {
14611520 return file_ermite_storage_ci_proto_rawDescData
14621521 }
14631522
1464-var file_ermite_storage_ci_proto_enumTypes = make([]protoimpl.EnumInfo, 5)
1523+var file_ermite_storage_ci_proto_enumTypes = make([]protoimpl.EnumInfo, 6)
14651524 var file_ermite_storage_ci_proto_msgTypes = make([]protoimpl.MessageInfo, 7)
14661525 var file_ermite_storage_ci_proto_goTypes = []any{
14671526 (CIStatus)(0), // 0: ermite.storage.CIStatus
@@ -1469,51 +1528,53 @@ var file_ermite_storage_ci_proto_goTypes = []any{
14691528 (CIStepState)(0), // 2: ermite.storage.CIStepState
14701529 (CIJobPhase)(0), // 3: ermite.storage.CIJobPhase
14711530 (CIIsolation)(0), // 4: ermite.storage.CIIsolation
1472- (*CIRun)(nil), // 5: ermite.storage.CIRun
1473- (*CIRunSource)(nil), // 6: ermite.storage.CIRunSource
1474- (*CIStep)(nil), // 7: ermite.storage.CIStep
1475- (*CIJob)(nil), // 8: ermite.storage.CIJob
1476- (*CICheck)(nil), // 9: ermite.storage.CICheck
1477- (*CIRunner)(nil), // 10: ermite.storage.CIRunner
1478- nil, // 11: ermite.storage.CIJob.OutputsEntry
1479- (*timestamppb.Timestamp)(nil), // 12: google.protobuf.Timestamp
1531+ (CICancelReason)(0), // 5: ermite.storage.CICancelReason
1532+ (*CIRun)(nil), // 6: ermite.storage.CIRun
1533+ (*CIRunSource)(nil), // 7: ermite.storage.CIRunSource
1534+ (*CIStep)(nil), // 8: ermite.storage.CIStep
1535+ (*CIJob)(nil), // 9: ermite.storage.CIJob
1536+ (*CICheck)(nil), // 10: ermite.storage.CICheck
1537+ (*CIRunner)(nil), // 11: ermite.storage.CIRunner
1538+ nil, // 12: ermite.storage.CIJob.OutputsEntry
1539+ (*timestamppb.Timestamp)(nil), // 13: google.protobuf.Timestamp
14801540 }
14811541 var file_ermite_storage_ci_proto_depIdxs = []int32{
14821542 0, // 0: ermite.storage.CIRun.status:type_name -> ermite.storage.CIStatus
14831543 1, // 1: ermite.storage.CIRun.conclusion:type_name -> ermite.storage.CIConclusion
1484- 12, // 2: ermite.storage.CIRun.created_at:type_name -> google.protobuf.Timestamp
1485- 12, // 3: ermite.storage.CIRun.started_at:type_name -> google.protobuf.Timestamp
1486- 12, // 4: ermite.storage.CIRun.completed_at:type_name -> google.protobuf.Timestamp
1487- 12, // 5: ermite.storage.CIRun.cancel_requested_at:type_name -> google.protobuf.Timestamp
1544+ 13, // 2: ermite.storage.CIRun.created_at:type_name -> google.protobuf.Timestamp
1545+ 13, // 3: ermite.storage.CIRun.started_at:type_name -> google.protobuf.Timestamp
1546+ 13, // 4: ermite.storage.CIRun.completed_at:type_name -> google.protobuf.Timestamp
1547+ 13, // 5: ermite.storage.CIRun.cancel_requested_at:type_name -> google.protobuf.Timestamp
14881548 2, // 6: ermite.storage.CIStep.state:type_name -> ermite.storage.CIStepState
14891549 1, // 7: ermite.storage.CIStep.conclusion:type_name -> ermite.storage.CIConclusion
1490- 12, // 8: ermite.storage.CIStep.started_at:type_name -> google.protobuf.Timestamp
1491- 12, // 9: ermite.storage.CIStep.completed_at:type_name -> google.protobuf.Timestamp
1550+ 13, // 8: ermite.storage.CIStep.started_at:type_name -> google.protobuf.Timestamp
1551+ 13, // 9: ermite.storage.CIStep.completed_at:type_name -> google.protobuf.Timestamp
14921552 3, // 10: ermite.storage.CIJob.phase:type_name -> ermite.storage.CIJobPhase
14931553 1, // 11: ermite.storage.CIJob.conclusion:type_name -> ermite.storage.CIConclusion
14941554 4, // 12: ermite.storage.CIJob.isolation:type_name -> ermite.storage.CIIsolation
1495- 7, // 13: ermite.storage.CIJob.steps:type_name -> ermite.storage.CIStep
1496- 12, // 14: ermite.storage.CIJob.created_at:type_name -> google.protobuf.Timestamp
1497- 12, // 15: ermite.storage.CIJob.started_at:type_name -> google.protobuf.Timestamp
1498- 12, // 16: ermite.storage.CIJob.completed_at:type_name -> google.protobuf.Timestamp
1499- 11, // 17: ermite.storage.CIJob.outputs:type_name -> ermite.storage.CIJob.OutputsEntry
1500- 12, // 18: ermite.storage.CIJob.ready_at:type_name -> google.protobuf.Timestamp
1501- 12, // 19: ermite.storage.CIJob.assigned_at:type_name -> google.protobuf.Timestamp
1502- 12, // 20: ermite.storage.CIJob.acked_at:type_name -> google.protobuf.Timestamp
1503- 12, // 21: ermite.storage.CIJob.token_valid_until:type_name -> google.protobuf.Timestamp
1504- 12, // 22: ermite.storage.CIJob.cancel_requested_at:type_name -> google.protobuf.Timestamp
1505- 0, // 23: ermite.storage.CICheck.status:type_name -> ermite.storage.CIStatus
1506- 1, // 24: ermite.storage.CICheck.conclusion:type_name -> ermite.storage.CIConclusion
1507- 12, // 25: ermite.storage.CICheck.created_at:type_name -> google.protobuf.Timestamp
1508- 12, // 26: ermite.storage.CICheck.started_at:type_name -> google.protobuf.Timestamp
1509- 12, // 27: ermite.storage.CICheck.completed_at:type_name -> google.protobuf.Timestamp
1510- 4, // 28: ermite.storage.CIRunner.isolation:type_name -> ermite.storage.CIIsolation
1511- 12, // 29: ermite.storage.CIRunner.registered_at:type_name -> google.protobuf.Timestamp
1512- 30, // [30:30] is the sub-list for method output_type
1513- 30, // [30:30] is the sub-list for method input_type
1514- 30, // [30:30] is the sub-list for extension type_name
1515- 30, // [30:30] is the sub-list for extension extendee
1516- 0, // [0:30] is the sub-list for field type_name
1555+ 8, // 13: ermite.storage.CIJob.steps:type_name -> ermite.storage.CIStep
1556+ 13, // 14: ermite.storage.CIJob.created_at:type_name -> google.protobuf.Timestamp
1557+ 13, // 15: ermite.storage.CIJob.started_at:type_name -> google.protobuf.Timestamp
1558+ 13, // 16: ermite.storage.CIJob.completed_at:type_name -> google.protobuf.Timestamp
1559+ 12, // 17: ermite.storage.CIJob.outputs:type_name -> ermite.storage.CIJob.OutputsEntry
1560+ 13, // 18: ermite.storage.CIJob.ready_at:type_name -> google.protobuf.Timestamp
1561+ 13, // 19: ermite.storage.CIJob.assigned_at:type_name -> google.protobuf.Timestamp
1562+ 13, // 20: ermite.storage.CIJob.acked_at:type_name -> google.protobuf.Timestamp
1563+ 13, // 21: ermite.storage.CIJob.token_valid_until:type_name -> google.protobuf.Timestamp
1564+ 5, // 22: ermite.storage.CIJob.cancel_reason:type_name -> ermite.storage.CICancelReason
1565+ 13, // 23: ermite.storage.CIJob.cancel_requested_at:type_name -> google.protobuf.Timestamp
1566+ 0, // 24: ermite.storage.CICheck.status:type_name -> ermite.storage.CIStatus
1567+ 1, // 25: ermite.storage.CICheck.conclusion:type_name -> ermite.storage.CIConclusion
1568+ 13, // 26: ermite.storage.CICheck.created_at:type_name -> google.protobuf.Timestamp
1569+ 13, // 27: ermite.storage.CICheck.started_at:type_name -> google.protobuf.Timestamp
1570+ 13, // 28: ermite.storage.CICheck.completed_at:type_name -> google.protobuf.Timestamp
1571+ 4, // 29: ermite.storage.CIRunner.isolation:type_name -> ermite.storage.CIIsolation
1572+ 13, // 30: ermite.storage.CIRunner.registered_at:type_name -> google.protobuf.Timestamp
1573+ 31, // [31:31] is the sub-list for method output_type
1574+ 31, // [31:31] is the sub-list for method input_type
1575+ 31, // [31:31] is the sub-list for extension type_name
1576+ 31, // [31:31] is the sub-list for extension extendee
1577+ 0, // [0:31] is the sub-list for field type_name
15171578 }
15181579
15191580 func init() { file_ermite_storage_ci_proto_init() }
@@ -1526,7 +1587,7 @@ func file_ermite_storage_ci_proto_init() {
15261587 File: protoimpl.DescBuilder{
15271588 GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
15281589 RawDescriptor: unsafe.Slice(unsafe.StringData(file_ermite_storage_ci_proto_rawDesc), len(file_ermite_storage_ci_proto_rawDesc)),
1529- NumEnums: 5,
1590+ NumEnums: 6,
15301591 NumMessages: 7,
15311592 NumExtensions: 0,
15321593 NumServices: 0,
@@ -316,6 +316,59 @@ func (CIIsolation) EnumDescriptor() ([]byte, []int) {
316 return file_ermite_storage_ci_proto_rawDescGZIP(), []int{4}316 return file_ermite_storage_ci_proto_rawDescGZIP(), []int{4}
317 }317 }
318 318
319+// CICancelReason says why a job is asked to stop.
320+type CICancelReason int32
321+
322+const (
323+ CICancelReason_CI_CANCEL_REASON_UNSPECIFIED CICancelReason = 0
324+ CICancelReason_CI_CANCEL_REASON_USER CICancelReason = 1
325+ CICancelReason_CI_CANCEL_REASON_FAIL_FAST CICancelReason = 2
326+ CICancelReason_CI_CANCEL_REASON_TIMEOUT CICancelReason = 3
327+)
328+
329+// Enum value maps for CICancelReason.
330+var (
331+ CICancelReason_name = map[int32]string{
332+ 0: "CI_CANCEL_REASON_UNSPECIFIED",
333+ 1: "CI_CANCEL_REASON_USER",
334+ 2: "CI_CANCEL_REASON_FAIL_FAST",
335+ 3: "CI_CANCEL_REASON_TIMEOUT",
336+ }
337+ CICancelReason_value = map[string]int32{
338+ "CI_CANCEL_REASON_UNSPECIFIED": 0,
339+ "CI_CANCEL_REASON_USER": 1,
340+ "CI_CANCEL_REASON_FAIL_FAST": 2,
341+ "CI_CANCEL_REASON_TIMEOUT": 3,
342+ }
343+)
344+
345+func (x CICancelReason) Enum() *CICancelReason {
346+ p := new(CICancelReason)
347+ *p = x
348+ return p
349+}
350+
351+func (x CICancelReason) String() string {
352+ return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x))
353+}
354+
355+func (CICancelReason) Descriptor() protoreflect.EnumDescriptor {
356+ return file_ermite_storage_ci_proto_enumTypes[5].Descriptor()
357+}
358+
359+func (CICancelReason) Type() protoreflect.EnumType {
360+ return &file_ermite_storage_ci_proto_enumTypes[5]
361+}
362+
363+func (x CICancelReason) Number() protoreflect.EnumNumber {
364+ return protoreflect.EnumNumber(x)
365+}
366+
367+// Deprecated: Use CICancelReason.Descriptor instead.
368+func (CICancelReason) EnumDescriptor() ([]byte, []int) {
369+ return file_ermite_storage_ci_proto_rawDescGZIP(), []int{5}
370+}
371+
319 // CIRun is stored under "run/<repo>/<id:020d>".372 // CIRun is stored under "run/<repo>/<id:020d>".
320 type CIRun struct {373 type CIRun struct {
321 state protoimpl.MessageState `protogen:"open.v1"`374 state protoimpl.MessageState `protogen:"open.v1"`
@@ -722,7 +775,7 @@ type CIJob struct {
722 AckedAt *timestamppb.Timestamp `protobuf:"bytes,30,opt,name=acked_at,json=ackedAt,proto3" json:"acked_at,omitempty"`775 AckedAt *timestamppb.Timestamp `protobuf:"bytes,30,opt,name=acked_at,json=ackedAt,proto3" json:"acked_at,omitempty"`
723 AssignCancels int32 `protobuf:"varint,31,opt,name=assign_cancels,json=assignCancels,proto3" json:"assign_cancels,omitempty"`776 AssignCancels int32 `protobuf:"varint,31,opt,name=assign_cancels,json=assignCancels,proto3" json:"assign_cancels,omitempty"`
724 TokenValidUntil *timestamppb.Timestamp `protobuf:"bytes,32,opt,name=token_valid_until,json=tokenValidUntil,proto3" json:"token_valid_until,omitempty"`777 TokenValidUntil *timestamppb.Timestamp `protobuf:"bytes,32,opt,name=token_valid_until,json=tokenValidUntil,proto3" json:"token_valid_until,omitempty"`
725- CancelReason int32 `protobuf:"varint,33,opt,name=cancel_reason,json=cancelReason,proto3" json:"cancel_reason,omitempty"`778+ CancelReason CICancelReason `protobuf:"varint,33,opt,name=cancel_reason,json=cancelReason,proto3,enum=ermite.storage.CICancelReason" json:"cancel_reason,omitempty"`
726 CancelMessage string `protobuf:"bytes,34,opt,name=cancel_message,json=cancelMessage,proto3" json:"cancel_message,omitempty"`779 CancelMessage string `protobuf:"bytes,34,opt,name=cancel_message,json=cancelMessage,proto3" json:"cancel_message,omitempty"`
727 CancelRequestedAt *timestamppb.Timestamp `protobuf:"bytes,35,opt,name=cancel_requested_at,json=cancelRequestedAt,proto3" json:"cancel_requested_at,omitempty"`780 CancelRequestedAt *timestamppb.Timestamp `protobuf:"bytes,35,opt,name=cancel_requested_at,json=cancelRequestedAt,proto3" json:"cancel_requested_at,omitempty"`
728 // Set when the job is planned: runs-on, name and contexts are evaluated.781 // Set when the job is planned: runs-on, name and contexts are evaluated.
@@ -992,11 +1045,11 @@ func (x *CIJob) GetTokenValidUntil() *timestamppb.Timestamp {
992 return nil1045 return nil
993 }1046 }
994 1047
995-func (x *CIJob) GetCancelReason() int32 {1048+func (x *CIJob) GetCancelReason() CICancelReason {
996 if x != nil {1049 if x != nil {
997 return x.CancelReason1050 return x.CancelReason
998 }1051 }
999- return 01052+ return CICancelReason_CI_CANCEL_REASON_UNSPECIFIED
1000 }1053 }
1001 1054
1002 func (x *CIJob) GetCancelMessage() string {1055 func (x *CIJob) GetCancelMessage() string {
@@ -1289,7 +1342,7 @@ var File_ermite_storage_ci_proto protoreflect.FileDescriptor
1289 1342
1290 const file_ermite_storage_ci_proto_rawDesc = "" +1343 const file_ermite_storage_ci_proto_rawDesc = "" +
1291 "\n" +1344 "\n" +
1292- "\x17ermite/storage/ci.proto\x12\x0eermite.storage\x1a\x1fgoogle/protobuf/timestamp.proto\"\xbf\x05\n" +1345+ "\x17ermite/storage/ci.proto\x12\x0eermite.storage\x1a\x1fgoogle/protobuf/timestamp.proto\"\xcb\x05\n" +
1293 "\x05CIRun\x12\x12\n" +1346 "\x05CIRun\x12\x12\n" +
1294 "\x04repo\x18\x01 \x01(\tR\x04repo\x12\x0e\n" +1347 "\x04repo\x18\x01 \x01(\tR\x04repo\x12\x0e\n" +
1295 "\x02id\x18\x02 \x01(\x03R\x02id\x12\x16\n" +1348 "\x02id\x18\x02 \x01(\x03R\x02id\x12\x16\n" +
@@ -1314,13 +1367,13 @@ const file_ermite_storage_ci_proto_rawDesc = "" +
1314 "started_at\x18\x10 \x01(\v2\x1a.google.protobuf.TimestampR\tstartedAt\x12=\n" +1367 "started_at\x18\x10 \x01(\v2\x1a.google.protobuf.TimestampR\tstartedAt\x12=\n" +
1315 "\fcompleted_at\x18\x11 \x01(\v2\x1a.google.protobuf.TimestampR\vcompletedAt\x12)\n" +1368 "\fcompleted_at\x18\x11 \x01(\v2\x1a.google.protobuf.TimestampR\vcompletedAt\x12)\n" +
1316 "\x10cancel_requested\x18\x14 \x01(\bR\x0fcancelRequested\x12J\n" +1369 "\x10cancel_requested\x18\x14 \x01(\bR\x0fcancelRequested\x12J\n" +
1317- "\x13cancel_requested_at\x18\x15 \x01(\v2\x1a.google.protobuf.TimestampR\x11cancelRequestedAt\"~\n" +1370+ "\x13cancel_requested_at\x18\x15 \x01(\v2\x1a.google.protobuf.TimestampR\x11cancelRequestedAtJ\x04\b\x12\x10\x13J\x04\b\x13\x10\x14\"~\n" +
1318 "\vCIRunSource\x12\x15\n" +1371 "\vCIRunSource\x12\x15\n" +
1319 "\x06run_id\x18\x04 \x01(\x03R\x05runId\x12#\n" +1372 "\x06run_id\x18\x04 \x01(\x03R\x05runId\x12#\n" +
1320 "\rworkflow_yaml\x18\x01 \x01(\tR\fworkflowYaml\x12\x1f\n" +1373 "\rworkflow_yaml\x18\x01 \x01(\tR\fworkflowYaml\x12\x1f\n" +
1321 "\vgithub_json\x18\x02 \x01(\tR\n" +1374 "\vgithub_json\x18\x02 \x01(\tR\n" +
1322 "githubJson\x12\x12\n" +1375 "githubJson\x12\x12\n" +
1323- "\x04repo\x18\x03 \x01(\tR\x04repo\"\xd9\x02\n" +1376+ "\x04repo\x18\x03 \x01(\tR\x04repo\"\xe5\x02\n" +
1324 "\x06CIStep\x12\x16\n" +1377 "\x06CIStep\x12\x16\n" +
1325 "\x06number\x18\x01 \x01(\x05R\x06number\x12\x12\n" +1378 "\x06number\x18\x01 \x01(\x05R\x06number\x12\x12\n" +
1326 "\x04name\x18\x02 \x01(\tR\x04name\x121\n" +1379 "\x04name\x18\x02 \x01(\tR\x04name\x121\n" +
@@ -1332,7 +1385,8 @@ const file_ermite_storage_ci_proto_rawDesc = "" +
1332 "started_at\x18\x05 \x01(\v2\x1a.google.protobuf.TimestampR\tstartedAt\x12=\n" +1385 "started_at\x18\x05 \x01(\v2\x1a.google.protobuf.TimestampR\tstartedAt\x12=\n" +
1333 "\fcompleted_at\x18\x06 \x01(\v2\x1a.google.protobuf.TimestampR\vcompletedAt\x12\x1b\n" +1386 "\fcompleted_at\x18\x06 \x01(\v2\x1a.google.protobuf.TimestampR\vcompletedAt\x12\x1b\n" +
1334 "\tlog_start\x18\a \x01(\x03R\blogStart\x12\x1b\n" +1387 "\tlog_start\x18\a \x01(\x03R\blogStart\x12\x1b\n" +
1335- "\thas_lines\x18\t \x01(\bR\bhasLines\"\x94\f\n" +1388+ "\thas_lines\x18\t \x01(\bR\bhasLinesJ\x04\b\b\x10\tJ\x04\b\n" +
1389+ "\x10\v\"\xba\f\n" +
1336 "\x05CIJob\x12\x0e\n" +1390 "\x05CIJob\x12\x0e\n" +
1337 "\x02id\x18\x01 \x01(\tR\x02id\x12\x15\n" +1391 "\x02id\x18\x01 \x01(\tR\x02id\x12\x15\n" +
1338 "\x06run_id\x18\x02 \x01(\x03R\x05runId\x12\x18\n" +1392 "\x06run_id\x18\x02 \x01(\x03R\x05runId\x12\x18\n" +
@@ -1375,8 +1429,8 @@ const file_ermite_storage_ci_proto_rawDesc = "" +
1375 "assignedAt\x125\n" +1429 "assignedAt\x125\n" +
1376 "\backed_at\x18\x1e \x01(\v2\x1a.google.protobuf.TimestampR\aackedAt\x12%\n" +1430 "\backed_at\x18\x1e \x01(\v2\x1a.google.protobuf.TimestampR\aackedAt\x12%\n" +
1377 "\x0eassign_cancels\x18\x1f \x01(\x05R\rassignCancels\x12F\n" +1431 "\x0eassign_cancels\x18\x1f \x01(\x05R\rassignCancels\x12F\n" +
1378- "\x11token_valid_until\x18 \x01(\v2\x1a.google.protobuf.TimestampR\x0ftokenValidUntil\x12#\n" +1432+ "\x11token_valid_until\x18 \x01(\v2\x1a.google.protobuf.TimestampR\x0ftokenValidUntil\x12C\n" +
1379- "\rcancel_reason\x18! \x01(\x05R\fcancelReason\x12%\n" +1433+ "\rcancel_reason\x18! \x01(\x0e2\x1e.ermite.storage.CICancelReasonR\fcancelReason\x12%\n" +
1380 "\x0ecancel_message\x18\" \x01(\tR\rcancelMessage\x12J\n" +1434 "\x0ecancel_message\x18\" \x01(\tR\rcancelMessage\x12J\n" +
1381 "\x13cancel_requested_at\x18# \x01(\v2\x1a.google.protobuf.TimestampR\x11cancelRequestedAt\x12\x18\n" +1435 "\x13cancel_requested_at\x18# \x01(\v2\x1a.google.protobuf.TimestampR\x11cancelRequestedAt\x12\x18\n" +
1382 "\aplanned\x18% \x01(\bR\aplanned\x12\x1f\n" +1436 "\aplanned\x18% \x01(\bR\aplanned\x12\x1f\n" +
@@ -1385,7 +1439,7 @@ const file_ermite_storage_ci_proto_rawDesc = "" +
1385 "\rcontexts_json\x18' \x01(\tR\fcontextsJson\x1a:\n" +1439 "\rcontexts_json\x18' \x01(\tR\fcontextsJson\x1a:\n" +
1386 "\fOutputsEntry\x12\x10\n" +1440 "\fOutputsEntry\x12\x10\n" +
1387 "\x03key\x18\x01 \x01(\tR\x03key\x12\x14\n" +1441 "\x03key\x18\x01 \x01(\tR\x03key\x12\x14\n" +
1388- "\x05value\x18\x02 \x01(\tR\x05value:\x028\x01\"\xe5\x03\n" +1442+ "\x05value\x18\x02 \x01(\tR\x05value:\x028\x01J\x04\b$\x10%\"\xe5\x03\n" +
1389 "\aCICheck\x12\x0e\n" +1443 "\aCICheck\x12\x0e\n" +
1390 "\x02id\x18\x01 \x01(\tR\x02id\x12\x12\n" +1444 "\x02id\x18\x01 \x01(\tR\x02id\x12\x12\n" +
1391 "\x04repo\x18\x02 \x01(\tR\x04repo\x12\x10\n" +1445 "\x04repo\x18\x02 \x01(\tR\x04repo\x12\x10\n" +
@@ -1447,7 +1501,12 @@ const file_ermite_storage_ci_proto_rawDesc = "" +
1447 "\x18CI_ISOLATION_UNSPECIFIED\x10\x00\x12\x13\n" +1501 "\x18CI_ISOLATION_UNSPECIFIED\x10\x00\x12\x13\n" +
1448 "\x0fCI_ISOLATION_VM\x10\x01\x12!\n" +1502 "\x0fCI_ISOLATION_VM\x10\x01\x12!\n" +
1449 "\x1dCI_ISOLATION_CONTAINER_SYSBOX\x10\x02\x12%\n" +1503 "\x1dCI_ISOLATION_CONTAINER_SYSBOX\x10\x02\x12%\n" +
1450- "!CI_ISOLATION_CONTAINER_PRIVILEGED\x10\x03B/Z-bnema.dev/ermite/gen/ermite/storage;storagepbb\x06proto3"1504+ "!CI_ISOLATION_CONTAINER_PRIVILEGED\x10\x03*\x8b\x01\n" +
1505+ "\x0eCICancelReason\x12 \n" +
1506+ "\x1cCI_CANCEL_REASON_UNSPECIFIED\x10\x00\x12\x19\n" +
1507+ "\x15CI_CANCEL_REASON_USER\x10\x01\x12\x1e\n" +
1508+ "\x1aCI_CANCEL_REASON_FAIL_FAST\x10\x02\x12\x1c\n" +
1509+ "\x18CI_CANCEL_REASON_TIMEOUT\x10\x03B/Z-bnema.dev/ermite/gen/ermite/storage;storagepbb\x06proto3"
1451 1510
1452 var (1511 var (
1453 file_ermite_storage_ci_proto_rawDescOnce sync.Once1512 file_ermite_storage_ci_proto_rawDescOnce sync.Once
@@ -1461,7 +1520,7 @@ func file_ermite_storage_ci_proto_rawDescGZIP() []byte {
1461 return file_ermite_storage_ci_proto_rawDescData1520 return file_ermite_storage_ci_proto_rawDescData
1462 }1521 }
1463 1522
1464-var file_ermite_storage_ci_proto_enumTypes = make([]protoimpl.EnumInfo, 5)1523+var file_ermite_storage_ci_proto_enumTypes = make([]protoimpl.EnumInfo, 6)
1465 var file_ermite_storage_ci_proto_msgTypes = make([]protoimpl.MessageInfo, 7)1524 var file_ermite_storage_ci_proto_msgTypes = make([]protoimpl.MessageInfo, 7)
1466 var file_ermite_storage_ci_proto_goTypes = []any{1525 var file_ermite_storage_ci_proto_goTypes = []any{
1467 (CIStatus)(0), // 0: ermite.storage.CIStatus1526 (CIStatus)(0), // 0: ermite.storage.CIStatus
@@ -1469,51 +1528,53 @@ var file_ermite_storage_ci_proto_goTypes = []any{
1469 (CIStepState)(0), // 2: ermite.storage.CIStepState1528 (CIStepState)(0), // 2: ermite.storage.CIStepState
1470 (CIJobPhase)(0), // 3: ermite.storage.CIJobPhase1529 (CIJobPhase)(0), // 3: ermite.storage.CIJobPhase
1471 (CIIsolation)(0), // 4: ermite.storage.CIIsolation1530 (CIIsolation)(0), // 4: ermite.storage.CIIsolation
1472- (*CIRun)(nil), // 5: ermite.storage.CIRun1531+ (CICancelReason)(0), // 5: ermite.storage.CICancelReason
1473- (*CIRunSource)(nil), // 6: ermite.storage.CIRunSource1532+ (*CIRun)(nil), // 6: ermite.storage.CIRun
1474- (*CIStep)(nil), // 7: ermite.storage.CIStep1533+ (*CIRunSource)(nil), // 7: ermite.storage.CIRunSource
1475- (*CIJob)(nil), // 8: ermite.storage.CIJob1534+ (*CIStep)(nil), // 8: ermite.storage.CIStep
1476- (*CICheck)(nil), // 9: ermite.storage.CICheck1535+ (*CIJob)(nil), // 9: ermite.storage.CIJob
1477- (*CIRunner)(nil), // 10: ermite.storage.CIRunner1536+ (*CICheck)(nil), // 10: ermite.storage.CICheck
1478- nil, // 11: ermite.storage.CIJob.OutputsEntry1537+ (*CIRunner)(nil), // 11: ermite.storage.CIRunner
1479- (*timestamppb.Timestamp)(nil), // 12: google.protobuf.Timestamp1538+ nil, // 12: ermite.storage.CIJob.OutputsEntry
1539+ (*timestamppb.Timestamp)(nil), // 13: google.protobuf.Timestamp
1480 }1540 }
1481 var file_ermite_storage_ci_proto_depIdxs = []int32{1541 var file_ermite_storage_ci_proto_depIdxs = []int32{
1482 0, // 0: ermite.storage.CIRun.status:type_name -> ermite.storage.CIStatus1542 0, // 0: ermite.storage.CIRun.status:type_name -> ermite.storage.CIStatus
1483 1, // 1: ermite.storage.CIRun.conclusion:type_name -> ermite.storage.CIConclusion1543 1, // 1: ermite.storage.CIRun.conclusion:type_name -> ermite.storage.CIConclusion
1484- 12, // 2: ermite.storage.CIRun.created_at:type_name -> google.protobuf.Timestamp1544+ 13, // 2: ermite.storage.CIRun.created_at:type_name -> google.protobuf.Timestamp
1485- 12, // 3: ermite.storage.CIRun.started_at:type_name -> google.protobuf.Timestamp1545+ 13, // 3: ermite.storage.CIRun.started_at:type_name -> google.protobuf.Timestamp
1486- 12, // 4: ermite.storage.CIRun.completed_at:type_name -> google.protobuf.Timestamp1546+ 13, // 4: ermite.storage.CIRun.completed_at:type_name -> google.protobuf.Timestamp
1487- 12, // 5: ermite.storage.CIRun.cancel_requested_at:type_name -> google.protobuf.Timestamp1547+ 13, // 5: ermite.storage.CIRun.cancel_requested_at:type_name -> google.protobuf.Timestamp
1488 2, // 6: ermite.storage.CIStep.state:type_name -> ermite.storage.CIStepState1548 2, // 6: ermite.storage.CIStep.state:type_name -> ermite.storage.CIStepState
1489 1, // 7: ermite.storage.CIStep.conclusion:type_name -> ermite.storage.CIConclusion1549 1, // 7: ermite.storage.CIStep.conclusion:type_name -> ermite.storage.CIConclusion
1490- 12, // 8: ermite.storage.CIStep.started_at:type_name -> google.protobuf.Timestamp1550+ 13, // 8: ermite.storage.CIStep.started_at:type_name -> google.protobuf.Timestamp
1491- 12, // 9: ermite.storage.CIStep.completed_at:type_name -> google.protobuf.Timestamp1551+ 13, // 9: ermite.storage.CIStep.completed_at:type_name -> google.protobuf.Timestamp
1492 3, // 10: ermite.storage.CIJob.phase:type_name -> ermite.storage.CIJobPhase1552 3, // 10: ermite.storage.CIJob.phase:type_name -> ermite.storage.CIJobPhase
1493 1, // 11: ermite.storage.CIJob.conclusion:type_name -> ermite.storage.CIConclusion1553 1, // 11: ermite.storage.CIJob.conclusion:type_name -> ermite.storage.CIConclusion
1494 4, // 12: ermite.storage.CIJob.isolation:type_name -> ermite.storage.CIIsolation1554 4, // 12: ermite.storage.CIJob.isolation:type_name -> ermite.storage.CIIsolation
1495- 7, // 13: ermite.storage.CIJob.steps:type_name -> ermite.storage.CIStep1555+ 8, // 13: ermite.storage.CIJob.steps:type_name -> ermite.storage.CIStep
1496- 12, // 14: ermite.storage.CIJob.created_at:type_name -> google.protobuf.Timestamp1556+ 13, // 14: ermite.storage.CIJob.created_at:type_name -> google.protobuf.Timestamp
1497- 12, // 15: ermite.storage.CIJob.started_at:type_name -> google.protobuf.Timestamp1557+ 13, // 15: ermite.storage.CIJob.started_at:type_name -> google.protobuf.Timestamp
1498- 12, // 16: ermite.storage.CIJob.completed_at:type_name -> google.protobuf.Timestamp1558+ 13, // 16: ermite.storage.CIJob.completed_at:type_name -> google.protobuf.Timestamp
1499- 11, // 17: ermite.storage.CIJob.outputs:type_name -> ermite.storage.CIJob.OutputsEntry1559+ 12, // 17: ermite.storage.CIJob.outputs:type_name -> ermite.storage.CIJob.OutputsEntry
1500- 12, // 18: ermite.storage.CIJob.ready_at:type_name -> google.protobuf.Timestamp1560+ 13, // 18: ermite.storage.CIJob.ready_at:type_name -> google.protobuf.Timestamp
1501- 12, // 19: ermite.storage.CIJob.assigned_at:type_name -> google.protobuf.Timestamp1561+ 13, // 19: ermite.storage.CIJob.assigned_at:type_name -> google.protobuf.Timestamp
1502- 12, // 20: ermite.storage.CIJob.acked_at:type_name -> google.protobuf.Timestamp1562+ 13, // 20: ermite.storage.CIJob.acked_at:type_name -> google.protobuf.Timestamp
1503- 12, // 21: ermite.storage.CIJob.token_valid_until:type_name -> google.protobuf.Timestamp1563+ 13, // 21: ermite.storage.CIJob.token_valid_until:type_name -> google.protobuf.Timestamp
1504- 12, // 22: ermite.storage.CIJob.cancel_requested_at:type_name -> google.protobuf.Timestamp1564+ 5, // 22: ermite.storage.CIJob.cancel_reason:type_name -> ermite.storage.CICancelReason
1505- 0, // 23: ermite.storage.CICheck.status:type_name -> ermite.storage.CIStatus1565+ 13, // 23: ermite.storage.CIJob.cancel_requested_at:type_name -> google.protobuf.Timestamp
1506- 1, // 24: ermite.storage.CICheck.conclusion:type_name -> ermite.storage.CIConclusion1566+ 0, // 24: ermite.storage.CICheck.status:type_name -> ermite.storage.CIStatus
1507- 12, // 25: ermite.storage.CICheck.created_at:type_name -> google.protobuf.Timestamp1567+ 1, // 25: ermite.storage.CICheck.conclusion:type_name -> ermite.storage.CIConclusion
1508- 12, // 26: ermite.storage.CICheck.started_at:type_name -> google.protobuf.Timestamp1568+ 13, // 26: ermite.storage.CICheck.created_at:type_name -> google.protobuf.Timestamp
1509- 12, // 27: ermite.storage.CICheck.completed_at:type_name -> google.protobuf.Timestamp1569+ 13, // 27: ermite.storage.CICheck.started_at:type_name -> google.protobuf.Timestamp
1510- 4, // 28: ermite.storage.CIRunner.isolation:type_name -> ermite.storage.CIIsolation1570+ 13, // 28: ermite.storage.CICheck.completed_at:type_name -> google.protobuf.Timestamp
1511- 12, // 29: ermite.storage.CIRunner.registered_at:type_name -> google.protobuf.Timestamp1571+ 4, // 29: ermite.storage.CIRunner.isolation:type_name -> ermite.storage.CIIsolation
1512- 30, // [30:30] is the sub-list for method output_type1572+ 13, // 30: ermite.storage.CIRunner.registered_at:type_name -> google.protobuf.Timestamp
1513- 30, // [30:30] is the sub-list for method input_type1573+ 31, // [31:31] is the sub-list for method output_type
1514- 30, // [30:30] is the sub-list for extension type_name1574+ 31, // [31:31] is the sub-list for method input_type
1515- 30, // [30:30] is the sub-list for extension extendee1575+ 31, // [31:31] is the sub-list for extension type_name
1516- 0, // [0:30] is the sub-list for field type_name1576+ 31, // [31:31] is the sub-list for extension extendee
1577+ 0, // [0:31] is the sub-list for field type_name
1517 }1578 }
1518 1579
1519 func init() { file_ermite_storage_ci_proto_init() }1580 func init() { file_ermite_storage_ci_proto_init() }
@@ -1526,7 +1587,7 @@ func file_ermite_storage_ci_proto_init() {
1526 File: protoimpl.DescBuilder{1587 File: protoimpl.DescBuilder{
1527 GoPackagePath: reflect.TypeOf(x{}).PkgPath(),1588 GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
1528 RawDescriptor: unsafe.Slice(unsafe.StringData(file_ermite_storage_ci_proto_rawDesc), len(file_ermite_storage_ci_proto_rawDesc)),1589 RawDescriptor: unsafe.Slice(unsafe.StringData(file_ermite_storage_ci_proto_rawDesc), len(file_ermite_storage_ci_proto_rawDesc)),
1529- NumEnums: 5,1590+ NumEnums: 6,
1530 NumMessages: 7,1591 NumMessages: 7,
1531 NumExtensions: 0,1592 NumExtensions: 0,
1532 NumServices: 0,1593 NumServices: 0,
M internal/adapters/kvstore/ci.go +28 -6
@@ -235,7 +235,32 @@ func decodeStepState(s storagepb.CIStepState) domain.CIStepState {
235235 return domain.CIStepPending
236236 }
237237
238-var cancelReasons = []domain.CICancelReason{domain.CICancelNone, domain.CICancelUser, domain.CICancelFailFast, domain.CICancelTimeout}
238+var cancelReasons = []struct {
239+ d domain.CICancelReason
240+ p storagepb.CICancelReason
241+}{
242+ {domain.CICancelUser, storagepb.CICancelReason_CI_CANCEL_REASON_USER},
243+ {domain.CICancelFailFast, storagepb.CICancelReason_CI_CANCEL_REASON_FAIL_FAST},
244+ {domain.CICancelTimeout, storagepb.CICancelReason_CI_CANCEL_REASON_TIMEOUT},
245+}
246+
247+func encodeCancelReason(r domain.CICancelReason) storagepb.CICancelReason {
248+ for _, e := range cancelReasons {
249+ if e.d == r {
250+ return e.p
251+ }
252+ }
253+ return storagepb.CICancelReason_CI_CANCEL_REASON_UNSPECIFIED
254+}
255+
256+func decodeCancelReason(r storagepb.CICancelReason) domain.CICancelReason {
257+ for _, e := range cancelReasons {
258+ if e.p == r {
259+ return e.d
260+ }
261+ }
262+ return domain.CICancelNone
263+}
239264
240265 func encodeRun(r domain.CIRun) ([]byte, error) {
241266 if r.Repo.IsZero() {
@@ -287,7 +312,6 @@ func encodeJob(j domain.CIJob) ([]byte, error) {
287312 LogStart: s.LogStart, HasLines: s.HasLines,
288313 })
289314 }
290- reason := int32(slices.Index(cancelReasons, j.CancelReason))
291315 pb := &storagepb.CIJob{
292316 Id: j.ID, RunId: j.RunID, Attempt: j.Attempt, RunAttempt: j.RunAttempt, Repo: j.Repo.String(),
293317 Key: j.Key, Name: j.Name, Phase: phase, Conclusion: encodeConclusion(j.Conclusion), Error: j.Error,
@@ -298,7 +322,7 @@ func encodeJob(j domain.CIJob) ([]byte, error) {
298322 TimeoutMinutes: j.TimeoutMinutes, FailFast: j.FailFast, MaxParallel: int32(j.MaxParallel), //nolint:gosec // validated at planning
299323 Outputs: j.Outputs, ReadyAt: encodeTime(j.ReadyAt), AssignedAt: encodeTime(j.AssignedAt),
300324 AckedAt: encodeTime(j.AckedAt), AssignCancels: int32(j.AssignCancels), //nolint:gosec // at most 3
301- TokenValidUntil: encodeTime(j.TokenValidUntil), CancelReason: max(reason, 0), CancelMessage: j.CancelMessage,
325+ TokenValidUntil: encodeTime(j.TokenValidUntil), CancelReason: encodeCancelReason(j.CancelReason), CancelMessage: j.CancelMessage,
302326 CancelRequestedAt: encodeTime(j.CancelRequestedAt), Planned: j.Planned,
303327 }
304328 if j.HasToken() {
@@ -331,9 +355,7 @@ func decodeJob(item kv.Item) (domain.CIJob, error) {
331355 CancelMessage: pb.GetCancelMessage(), CancelRequestedAt: decodeTime(pb.GetCancelRequestedAt()),
332356 Version: item.Version,
333357 }
334- if r := int(pb.GetCancelReason()); r >= 0 && r < len(cancelReasons) {
335- j.CancelReason = cancelReasons[r]
336- }
358+ j.CancelReason = decodeCancelReason(pb.GetCancelReason())
337359 copy(j.TokenHash[:], pb.GetTokenHash())
338360 for _, s := range pb.GetSteps() {
339361 j.Steps = append(j.Steps, domain.CIStep{
@@ -235,7 +235,32 @@ func decodeStepState(s storagepb.CIStepState) domain.CIStepState {
235 return domain.CIStepPending235 return domain.CIStepPending
236 }236 }
237 237
238-var cancelReasons = []domain.CICancelReason{domain.CICancelNone, domain.CICancelUser, domain.CICancelFailFast, domain.CICancelTimeout}238+var cancelReasons = []struct {
239+ d domain.CICancelReason
240+ p storagepb.CICancelReason
241+}{
242+ {domain.CICancelUser, storagepb.CICancelReason_CI_CANCEL_REASON_USER},
243+ {domain.CICancelFailFast, storagepb.CICancelReason_CI_CANCEL_REASON_FAIL_FAST},
244+ {domain.CICancelTimeout, storagepb.CICancelReason_CI_CANCEL_REASON_TIMEOUT},
245+}
246+
247+func encodeCancelReason(r domain.CICancelReason) storagepb.CICancelReason {
248+ for _, e := range cancelReasons {
249+ if e.d == r {
250+ return e.p
251+ }
252+ }
253+ return storagepb.CICancelReason_CI_CANCEL_REASON_UNSPECIFIED
254+}
255+
256+func decodeCancelReason(r storagepb.CICancelReason) domain.CICancelReason {
257+ for _, e := range cancelReasons {
258+ if e.p == r {
259+ return e.d
260+ }
261+ }
262+ return domain.CICancelNone
263+}
239 264
240 func encodeRun(r domain.CIRun) ([]byte, error) {265 func encodeRun(r domain.CIRun) ([]byte, error) {
241 if r.Repo.IsZero() {266 if r.Repo.IsZero() {
@@ -287,7 +312,6 @@ func encodeJob(j domain.CIJob) ([]byte, error) {
287 LogStart: s.LogStart, HasLines: s.HasLines,312 LogStart: s.LogStart, HasLines: s.HasLines,
288 })313 })
289 }314 }
290- reason := int32(slices.Index(cancelReasons, j.CancelReason))
291 pb := &storagepb.CIJob{315 pb := &storagepb.CIJob{
292 Id: j.ID, RunId: j.RunID, Attempt: j.Attempt, RunAttempt: j.RunAttempt, Repo: j.Repo.String(),316 Id: j.ID, RunId: j.RunID, Attempt: j.Attempt, RunAttempt: j.RunAttempt, Repo: j.Repo.String(),
293 Key: j.Key, Name: j.Name, Phase: phase, Conclusion: encodeConclusion(j.Conclusion), Error: j.Error,317 Key: j.Key, Name: j.Name, Phase: phase, Conclusion: encodeConclusion(j.Conclusion), Error: j.Error,
@@ -298,7 +322,7 @@ func encodeJob(j domain.CIJob) ([]byte, error) {
298 TimeoutMinutes: j.TimeoutMinutes, FailFast: j.FailFast, MaxParallel: int32(j.MaxParallel), //nolint:gosec // validated at planning322 TimeoutMinutes: j.TimeoutMinutes, FailFast: j.FailFast, MaxParallel: int32(j.MaxParallel), //nolint:gosec // validated at planning
299 Outputs: j.Outputs, ReadyAt: encodeTime(j.ReadyAt), AssignedAt: encodeTime(j.AssignedAt),323 Outputs: j.Outputs, ReadyAt: encodeTime(j.ReadyAt), AssignedAt: encodeTime(j.AssignedAt),
300 AckedAt: encodeTime(j.AckedAt), AssignCancels: int32(j.AssignCancels), //nolint:gosec // at most 3324 AckedAt: encodeTime(j.AckedAt), AssignCancels: int32(j.AssignCancels), //nolint:gosec // at most 3
301- TokenValidUntil: encodeTime(j.TokenValidUntil), CancelReason: max(reason, 0), CancelMessage: j.CancelMessage,325+ TokenValidUntil: encodeTime(j.TokenValidUntil), CancelReason: encodeCancelReason(j.CancelReason), CancelMessage: j.CancelMessage,
302 CancelRequestedAt: encodeTime(j.CancelRequestedAt), Planned: j.Planned,326 CancelRequestedAt: encodeTime(j.CancelRequestedAt), Planned: j.Planned,
303 }327 }
304 if j.HasToken() {328 if j.HasToken() {
@@ -331,9 +355,7 @@ func decodeJob(item kv.Item) (domain.CIJob, error) {
331 CancelMessage: pb.GetCancelMessage(), CancelRequestedAt: decodeTime(pb.GetCancelRequestedAt()),355 CancelMessage: pb.GetCancelMessage(), CancelRequestedAt: decodeTime(pb.GetCancelRequestedAt()),
332 Version: item.Version,356 Version: item.Version,
333 }357 }
334- if r := int(pb.GetCancelReason()); r >= 0 && r < len(cancelReasons) {358+ j.CancelReason = decodeCancelReason(pb.GetCancelReason())
335- j.CancelReason = cancelReasons[r]
336- }
337 copy(j.TokenHash[:], pb.GetTokenHash())359 copy(j.TokenHash[:], pb.GetTokenHash())
338 for _, s := range pb.GetSteps() {360 for _, s := range pb.GetSteps() {
339 j.Steps = append(j.Steps, domain.CIStep{361 j.Steps = append(j.Steps, domain.CIStep{
M internal/adapters/kvstore/ci_test.go +17 -0
@@ -356,3 +356,20 @@ func TestCIStateSurvivesARestart(t *testing.T) {
356356 active, _ := ci2.ListActiveJobs(ctx)
357357 assert.Len(t, active, 1)
358358 }
359+
360+func TestCICancelReasonsRoundTrip(t *testing.T) {
361+ ctx := context.Background()
362+ _, ci, n := ciRepo(t)
363+ d, err := ci.CreateRun(ctx, n, "w.yml", draftOf(n, "w.yml", 1))
364+ require.NoError(t, err)
365+ for _, reason := range []domain.CICancelReason{domain.CICancelUser, domain.CICancelFailFast, domain.CICancelTimeout, domain.CICancelNone} {
366+ j, err := ci.GetJob(ctx, d.Run.ID, 1, d.Jobs[0].ID)
367+ require.NoError(t, err)
368+ j.CancelReason, j.CancelMessage, j.CancelRequestedAt = reason, "why", created
369+ _, err = ci.Apply(ctx, ports.CIWrite{Jobs: []domain.CIJob{j}})
370+ require.NoError(t, err)
371+ got, err := ci.GetJob(ctx, d.Run.ID, 1, d.Jobs[0].ID)
372+ require.NoError(t, err)
373+ assert.Equal(t, reason, got.CancelReason)
374+ }
375+}
@@ -356,3 +356,20 @@ func TestCIStateSurvivesARestart(t *testing.T) {
356 active, _ := ci2.ListActiveJobs(ctx)356 active, _ := ci2.ListActiveJobs(ctx)
357 assert.Len(t, active, 1)357 assert.Len(t, active, 1)
358 }358 }
359+
360+func TestCICancelReasonsRoundTrip(t *testing.T) {
361+ ctx := context.Background()
362+ _, ci, n := ciRepo(t)
363+ d, err := ci.CreateRun(ctx, n, "w.yml", draftOf(n, "w.yml", 1))
364+ require.NoError(t, err)
365+ for _, reason := range []domain.CICancelReason{domain.CICancelUser, domain.CICancelFailFast, domain.CICancelTimeout, domain.CICancelNone} {
366+ j, err := ci.GetJob(ctx, d.Run.ID, 1, d.Jobs[0].ID)
367+ require.NoError(t, err)
368+ j.CancelReason, j.CancelMessage, j.CancelRequestedAt = reason, "why", created
369+ _, err = ci.Apply(ctx, ports.CIWrite{Jobs: []domain.CIJob{j}})
370+ require.NoError(t, err)
371+ got, err := ci.GetJob(ctx, d.Run.ID, 1, d.Jobs[0].ID)
372+ require.NoError(t, err)
373+ assert.Equal(t, reason, got.CancelReason)
374+ }
375+}
M internal/adapters/web/events.go +2 -2
@@ -56,8 +56,8 @@ import (
5656 // ci-run data: <tr id="run-<id>">…</tr> (the list of runs) or
5757 // <div id="run-body">…</div> (one run)
5858 // ci-job data: <h2 id="job-head">…</h2> and <ol id="job-steps">…</ol>; the log
59-// itself is never sent in the stream, the page reads the lines after
60-// the last it holds from /raw?from=
59+// itself is never sent in this stream: the page follows it on its own
60+// feed, /<repo>/actions/runs/<id>/job/<job>/stream?from=<line>
6161 // gap data: gap; events were lost, or what the page shows is gone or
6262 // changed: the page fetches itself again (ermiteLive in ermite.js)
6363 //
@@ -56,8 +56,8 @@ import (
56 // ci-run data: <tr id="run-<id>">…</tr> (the list of runs) or56 // ci-run data: <tr id="run-<id>">…</tr> (the list of runs) or
57 // <div id="run-body">…</div> (one run)57 // <div id="run-body">…</div> (one run)
58 // ci-job data: <h2 id="job-head">…</h2> and <ol id="job-steps">…</ol>; the log58 // ci-job data: <h2 id="job-head">…</h2> and <ol id="job-steps">…</ol>; the log
59-// itself is never sent in the stream, the page reads the lines after59+// itself is never sent in this stream: the page follows it on its own
60-// the last it holds from /raw?from=60+// feed, /<repo>/actions/runs/<id>/job/<job>/stream?from=<line>
61 // gap data: gap; events were lost, or what the page shows is gone or61 // gap data: gap; events were lost, or what the page shows is gone or
62 // changed: the page fetches itself again (ermiteLive in ermite.js)62 // changed: the page fetches itself again (ermiteLive in ermite.js)
63 //63 //
M proto/ermite/storage/ci.proto +17 -1
@@ -63,8 +63,19 @@ enum CIIsolation {
6363 CI_ISOLATION_CONTAINER_PRIVILEGED = 3;
6464 }
6565
66+// CICancelReason says why a job is asked to stop.
67+enum CICancelReason {
68+ CI_CANCEL_REASON_UNSPECIFIED = 0;
69+ CI_CANCEL_REASON_USER = 1;
70+ CI_CANCEL_REASON_FAIL_FAST = 2;
71+ CI_CANCEL_REASON_TIMEOUT = 3;
72+}
73+
6674 // CIRun is stored under "run/<repo>/<id:020d>".
6775 message CIRun {
76+ // 18 and 19 were the workflow file and the github context, which moved to
77+ // CIRunSource.
78+ reserved 18, 19;
6879 string repo = 1;
6980 int64 id = 2;
7081 int64 number = 3;
@@ -101,6 +112,9 @@ message CIRunSource {
101112
102113 // CIStep is a step of a job.
103114 message CIStep {
115+ // 8 and 10 were the end of the step, which is derived from the next step's
116+ // start and the line count.
117+ reserved 8, 10;
104118 int32 number = 1;
105119 string name = 2;
106120 CIStepState state = 3;
@@ -116,6 +130,8 @@ message CIStep {
116130
117131 // CIJob is stored under "job/<run_id:020d>/<run_attempt:010d>/<job id>".
118132 message CIJob {
133+ // 36 was the line count of the log, which the log file holds.
134+ reserved 36;
119135 string id = 1;
120136 int64 run_id = 2;
121137 // Attempt in which the job executed (the one of its log).
@@ -152,7 +168,7 @@ message CIJob {
152168 google.protobuf.Timestamp acked_at = 30;
153169 int32 assign_cancels = 31;
154170 google.protobuf.Timestamp token_valid_until = 32;
155- int32 cancel_reason = 33;
171+ CICancelReason cancel_reason = 33;
156172 string cancel_message = 34;
157173 google.protobuf.Timestamp cancel_requested_at = 35;
158174 // Set when the job is planned: runs-on, name and contexts are evaluated.
@@ -63,8 +63,19 @@ enum CIIsolation {
63 CI_ISOLATION_CONTAINER_PRIVILEGED = 3;63 CI_ISOLATION_CONTAINER_PRIVILEGED = 3;
64 }64 }
65 65
66+// CICancelReason says why a job is asked to stop.
67+enum CICancelReason {
68+ CI_CANCEL_REASON_UNSPECIFIED = 0;
69+ CI_CANCEL_REASON_USER = 1;
70+ CI_CANCEL_REASON_FAIL_FAST = 2;
71+ CI_CANCEL_REASON_TIMEOUT = 3;
72+}
73+
66 // CIRun is stored under "run/<repo>/<id:020d>".74 // CIRun is stored under "run/<repo>/<id:020d>".
67 message CIRun {75 message CIRun {
76+ // 18 and 19 were the workflow file and the github context, which moved to
77+ // CIRunSource.
78+ reserved 18, 19;
68 string repo = 1;79 string repo = 1;
69 int64 id = 2;80 int64 id = 2;
70 int64 number = 3;81 int64 number = 3;
@@ -101,6 +112,9 @@ message CIRunSource {
101 112
102 // CIStep is a step of a job.113 // CIStep is a step of a job.
103 message CIStep {114 message CIStep {
115+ // 8 and 10 were the end of the step, which is derived from the next step's
116+ // start and the line count.
117+ reserved 8, 10;
104 int32 number = 1;118 int32 number = 1;
105 string name = 2;119 string name = 2;
106 CIStepState state = 3;120 CIStepState state = 3;
@@ -116,6 +130,8 @@ message CIStep {
116 130
117 // CIJob is stored under "job/<run_id:020d>/<run_attempt:010d>/<job id>".131 // CIJob is stored under "job/<run_id:020d>/<run_attempt:010d>/<job id>".
118 message CIJob {132 message CIJob {
133+ // 36 was the line count of the log, which the log file holds.
134+ reserved 36;
119 string id = 1;135 string id = 1;
120 int64 run_id = 2;136 int64 run_id = 2;
121 // Attempt in which the job executed (the one of its log).137 // Attempt in which the job executed (the one of its log).
@@ -152,7 +168,7 @@ message CIJob {
152 google.protobuf.Timestamp acked_at = 30;168 google.protobuf.Timestamp acked_at = 30;
153 int32 assign_cancels = 31;169 int32 assign_cancels = 31;
154 google.protobuf.Timestamp token_valid_until = 32;170 google.protobuf.Timestamp token_valid_until = 32;
155- int32 cancel_reason = 33;171+ CICancelReason cancel_reason = 33;
156 string cancel_message = 34;172 string cancel_message = 34;
157 google.protobuf.Timestamp cancel_requested_at = 35;173 google.protobuf.Timestamp cancel_requested_at = 35;
158 // Set when the job is planned: runs-on, name and contexts are evaluated.174 // Set when the job is planned: runs-on, name and contexts are evaluated.

Keyboard shortcuts

Single-key shortcuts are on. ctrl k and esc work whatever this says.

ctrl k :
go to a section, branch, tag, file or repository
?
this list
j k
move the row cursor down / up
enter
open the row under the cursor; on Files, a directory opens or closes in place
↑ ↓ ← → home end
in the file tree (focus on a row): previous / next row, close / open a directory or go to its parent / first entry, first / last row. They never open a file
l h
on Files: open a directory or a file / close a directory or go up to its parent, then to the parent page. Elsewhere: into the side panel (on a merge request, its files) / back to the content; there j k move between its controls
g g G
first / last row
/
filter the list; on Files, find a file anywhere in the repository (esc clears, enter opens the best match)
b
switch branch or tag
g s g f g c g b g m g i g r g a
tabs: summary, files, commits, branches & tags, merge requests, issues, releases, actions (when available)
g h
home
w
wide mode: use the whole width of the screen, or not (remembered)
y
copy a permalink pinned to the commit
d u x
diff: split / unified / collapse or expand all
e E
diff: the whole file in view / every file, with the lines the hunks hide
n
merge request: next note in the diff
esc
close a dialog, leave a field

Branches 3

Tags 45

↑↓ moveenter openesc close