docs(ci): tighten the annotation, summary and action resolution contracts
Add GetStepSummariesResponse.truncated and the 20 summaries cap, document annotation replacement, per-field annotation limits, ListAnnotations attempts, resolved_sha and token scope, and the UploadSummary request size.
- commit
- b94fede8b9d3b7c980ac641364d295dc864a9430
- author
- brice · · 2026-10-13 09:17 UTC
- parent
- 1541ed7
- signature
- GPG Verified
CD88F9E564E0102646FB6077A1A07C7C7C3E349D· arch-gpg Verified for the committer email
7 files · +139 -64
M gen/ermite/ermiteconnect/run.connect.go +12 -4
| @@ -78,7 +78,9 @@ type RunServiceClient interface { | |||
| 78 | 78 | GetJob(context.Context, *connect.Request[ermite.GetJobRequest]) (*connect.Response[ermite.GetJobResponse], error) | |
| 79 | 79 | // ListAnnotations lists the annotations of a run attempt, optionally of one | |
| 80 | 80 | // job, ordered by job (as in GetRun), step number, then the order in which | |
| 81 | - | // the step produced them. Needs the same access as GetRun. Returns at most | |
| 81 | + | // the step produced them. For each job it gives the annotations of the | |
| 82 | + | // attempt in which that job executed (RunJob.attempt), which is lower than | |
| 83 | + | // the attempt of the run for a job kept by a re-run of failed jobs only. Needs the same access as GetRun. Returns at most | |
| 82 | 84 | // 1,000 annotations (truncated tells). A run without annotations gives an | |
| 83 | 85 | // empty list. Only servers with the feature "ci.annotations" implement it | |
| 84 | 86 | // (unimplemented otherwise). Fails with not_found if the run, the attempt or | |
| @@ -86,7 +88,9 @@ type RunServiceClient interface { | |||
| 86 | 88 | ListAnnotations(context.Context, *connect.Request[ermite.ListAnnotationsRequest]) (*connect.Response[ermite.ListAnnotationsResponse], error) | |
| 87 | 89 | // GetStepSummaries returns the job summaries (the Markdown written to | |
| 88 | 90 | // GITHUB_STEP_SUMMARY) of the steps of a job that have one, ordered by step | |
| 89 | - | // number. Needs the same access as GetJob. Only servers with the feature | |
| 91 | + | // number. Like GitHub, it returns at most 20 summaries per job: the first 20 | |
| 92 | + | // steps that have one, in step order; truncated says there are more. Needs | |
| 93 | + | // the same access as GetJob. Only servers with the feature | |
| 90 | 94 | // "ci.summaries" implement it (unimplemented otherwise). A job without | |
| 91 | 95 | // summaries gives an empty list. Fails with not_found if the job or the | |
| 92 | 96 | // attempt does not exist. | |
| @@ -307,7 +311,9 @@ type RunServiceHandler interface { | |||
| 307 | 311 | GetJob(context.Context, *connect.Request[ermite.GetJobRequest]) (*connect.Response[ermite.GetJobResponse], error) | |
| 308 | 312 | // ListAnnotations lists the annotations of a run attempt, optionally of one | |
| 309 | 313 | // job, ordered by job (as in GetRun), step number, then the order in which | |
| 310 | - | // the step produced them. Needs the same access as GetRun. Returns at most | |
| 314 | + | // the step produced them. For each job it gives the annotations of the | |
| 315 | + | // attempt in which that job executed (RunJob.attempt), which is lower than | |
| 316 | + | // the attempt of the run for a job kept by a re-run of failed jobs only. Needs the same access as GetRun. Returns at most | |
| 311 | 317 | // 1,000 annotations (truncated tells). A run without annotations gives an | |
| 312 | 318 | // empty list. Only servers with the feature "ci.annotations" implement it | |
| 313 | 319 | // (unimplemented otherwise). Fails with not_found if the run, the attempt or | |
| @@ -315,7 +321,9 @@ type RunServiceHandler interface { | |||
| 315 | 321 | ListAnnotations(context.Context, *connect.Request[ermite.ListAnnotationsRequest]) (*connect.Response[ermite.ListAnnotationsResponse], error) | |
| 316 | 322 | // GetStepSummaries returns the job summaries (the Markdown written to | |
| 317 | 323 | // GITHUB_STEP_SUMMARY) of the steps of a job that have one, ordered by step | |
| 318 | - | // number. Needs the same access as GetJob. Only servers with the feature | |
| 324 | + | // number. Like GitHub, it returns at most 20 summaries per job: the first 20 | |
| 325 | + | // steps that have one, in step order; truncated says there are more. Needs | |
| 326 | + | // the same access as GetJob. Only servers with the feature | |
| 319 | 327 | // "ci.summaries" implement it (unimplemented otherwise). A job without | |
| 320 | 328 | // summaries gives an empty list. Fails with not_found if the job or the | |
| 321 | 329 | // attempt does not exist. | |
| @@ -78,7 +78,9 @@ type RunServiceClient interface { | |||||
| 78 | GetJob(context.Context, *connect.Request[ermite.GetJobRequest]) (*connect.Response[ermite.GetJobResponse], error) | 78 | GetJob(context.Context, *connect.Request[ermite.GetJobRequest]) (*connect.Response[ermite.GetJobResponse], error) | ||
| 79 | // ListAnnotations lists the annotations of a run attempt, optionally of one | 79 | // ListAnnotations lists the annotations of a run attempt, optionally of one | ||
| 80 | // job, ordered by job (as in GetRun), step number, then the order in which | 80 | // job, ordered by job (as in GetRun), step number, then the order in which | ||
| 81 | - | // the step produced them. Needs the same access as GetRun. Returns at most | 81 | + | // the step produced them. For each job it gives the annotations of the |
| 82 | + | // attempt in which that job executed (RunJob.attempt), which is lower than | |||
| 83 | + | // the attempt of the run for a job kept by a re-run of failed jobs only. Needs the same access as GetRun. Returns at most | |||
| 82 | // 1,000 annotations (truncated tells). A run without annotations gives an | 84 | // 1,000 annotations (truncated tells). A run without annotations gives an | ||
| 83 | // empty list. Only servers with the feature "ci.annotations" implement it | 85 | // empty list. Only servers with the feature "ci.annotations" implement it | ||
| 84 | // (unimplemented otherwise). Fails with not_found if the run, the attempt or | 86 | // (unimplemented otherwise). Fails with not_found if the run, the attempt or | ||
| @@ -86,7 +88,9 @@ type RunServiceClient interface { | |||||
| 86 | ListAnnotations(context.Context, *connect.Request[ermite.ListAnnotationsRequest]) (*connect.Response[ermite.ListAnnotationsResponse], error) | 88 | ListAnnotations(context.Context, *connect.Request[ermite.ListAnnotationsRequest]) (*connect.Response[ermite.ListAnnotationsResponse], error) | ||
| 87 | // GetStepSummaries returns the job summaries (the Markdown written to | 89 | // GetStepSummaries returns the job summaries (the Markdown written to | ||
| 88 | // GITHUB_STEP_SUMMARY) of the steps of a job that have one, ordered by step | 90 | // GITHUB_STEP_SUMMARY) of the steps of a job that have one, ordered by step | ||
| 89 | - | // number. Needs the same access as GetJob. Only servers with the feature | 91 | + | // number. Like GitHub, it returns at most 20 summaries per job: the first 20 |
| 92 | + | // steps that have one, in step order; truncated says there are more. Needs | |||
| 93 | + | // the same access as GetJob. Only servers with the feature | |||
| 90 | // "ci.summaries" implement it (unimplemented otherwise). A job without | 94 | // "ci.summaries" implement it (unimplemented otherwise). A job without | ||
| 91 | // summaries gives an empty list. Fails with not_found if the job or the | 95 | // summaries gives an empty list. Fails with not_found if the job or the | ||
| 92 | // attempt does not exist. | 96 | // attempt does not exist. | ||
| @@ -307,7 +311,9 @@ type RunServiceHandler interface { | |||||
| 307 | GetJob(context.Context, *connect.Request[ermite.GetJobRequest]) (*connect.Response[ermite.GetJobResponse], error) | 311 | GetJob(context.Context, *connect.Request[ermite.GetJobRequest]) (*connect.Response[ermite.GetJobResponse], error) | ||
| 308 | // ListAnnotations lists the annotations of a run attempt, optionally of one | 312 | // ListAnnotations lists the annotations of a run attempt, optionally of one | ||
| 309 | // job, ordered by job (as in GetRun), step number, then the order in which | 313 | // job, ordered by job (as in GetRun), step number, then the order in which | ||
| 310 | - | // the step produced them. Needs the same access as GetRun. Returns at most | 314 | + | // the step produced them. For each job it gives the annotations of the |
| 315 | + | // attempt in which that job executed (RunJob.attempt), which is lower than | |||
| 316 | + | // the attempt of the run for a job kept by a re-run of failed jobs only. Needs the same access as GetRun. Returns at most | |||
| 311 | // 1,000 annotations (truncated tells). A run without annotations gives an | 317 | // 1,000 annotations (truncated tells). A run without annotations gives an | ||
| 312 | // empty list. Only servers with the feature "ci.annotations" implement it | 318 | // empty list. Only servers with the feature "ci.annotations" implement it | ||
| 313 | // (unimplemented otherwise). Fails with not_found if the run, the attempt or | 319 | // (unimplemented otherwise). Fails with not_found if the run, the attempt or | ||
| @@ -315,7 +321,9 @@ type RunServiceHandler interface { | |||||
| 315 | ListAnnotations(context.Context, *connect.Request[ermite.ListAnnotationsRequest]) (*connect.Response[ermite.ListAnnotationsResponse], error) | 321 | ListAnnotations(context.Context, *connect.Request[ermite.ListAnnotationsRequest]) (*connect.Response[ermite.ListAnnotationsResponse], error) | ||
| 316 | // GetStepSummaries returns the job summaries (the Markdown written to | 322 | // GetStepSummaries returns the job summaries (the Markdown written to | ||
| 317 | // GITHUB_STEP_SUMMARY) of the steps of a job that have one, ordered by step | 323 | // GITHUB_STEP_SUMMARY) of the steps of a job that have one, ordered by step | ||
| 318 | - | // number. Needs the same access as GetJob. Only servers with the feature | 324 | + | // number. Like GitHub, it returns at most 20 summaries per job: the first 20 |
| 325 | + | // steps that have one, in step order; truncated says there are more. Needs | |||
| 326 | + | // the same access as GetJob. Only servers with the feature | |||
| 319 | // "ci.summaries" implement it (unimplemented otherwise). A job without | 327 | // "ci.summaries" implement it (unimplemented otherwise). A job without | ||
| 320 | // summaries gives an empty list. Fails with not_found if the job or the | 328 | // summaries gives an empty list. Fails with not_found if the job or the | ||
| 321 | // attempt does not exist. | 329 | // attempt does not exist. | ||
M gen/ermite/ermiteconnect/runner.connect.go +32 -14
| @@ -115,7 +115,12 @@ type RunnerServiceClient interface { | |||
| 115 | 115 | // step_number present in annotations, the annotations of that step stored | |
| 116 | 116 | // so far are replaced by the ones of the request, so a retry never | |
| 117 | 117 | // duplicates them. A step number absent from the request keeps its | |
| 118 | - | // annotations. | |
| 118 | + | // annotations. The step of an annotation need not be in the steps of the | |
| 119 | + | // same call, and may already be COMPLETED: its annotations can still be | |
| 120 | + | // replaced (the rule that a COMPLETED step cannot change applies to | |
| 121 | + | // StepUpdate, not to annotations), until the job ends. A runner sends one | |
| 122 | + | // UpdateJob (or CompleteJob) at a time for a job, never concurrent calls, | |
| 123 | + | // so replacements apply in the order of the calls. | |
| 119 | 124 | // | |
| 120 | 125 | // Fails with invalid_argument if a rule is broken (including the annotation | |
| 121 | 126 | // limits), with failed_precondition if a step goes back (a COMPLETED step | |
| @@ -225,7 +230,8 @@ type RunnerServiceClient interface { | |||
| 225 | 230 | // ends are completed by the server as CI_CONCLUSION_CANCELLED (or SKIPPED when | |
| 226 | 231 | // they never started and the job did not end by cancellation). | |
| 227 | 232 | // | |
| 228 | - | // Annotations are applied as in UpdateJob, together with the conclusion. | |
| 233 | + | // Annotations are applied as in UpdateJob (replacement per step number, also | |
| 234 | + | // for COMPLETED steps and steps not in steps), together with the conclusion. | |
| 229 | 235 | // Summaries are not part of this call: a runner sends them with | |
| 230 | 236 | // UploadSummary before it. | |
| 231 | 237 | // | |
| @@ -249,9 +255,10 @@ type RunnerServiceClient interface { | |||
| 249 | 255 | // as is. Only a failure of the call itself (credential, ended job, bad | |
| 250 | 256 | // request, server error) is an RPC error; the runner then fails the job. | |
| 251 | 257 | // | |
| 252 | - | // Resolution is stable for a run: the same ref resolves to the same sha for | |
| 253 | - | // every job and every call of one attempt of the run. A re-run attempt | |
| 254 | - | // resolves again. | |
| 258 | + | // Resolution is stable for a run attempt: the same ref resolves to the same | |
| 259 | + | // sha (ResolvedAction.resolved_sha) for every job and every call of that | |
| 260 | + | // attempt. A re-run attempt resolves again. Tokens are not shared: each | |
| 261 | + | // job gets its own (ResolvedAction.token). | |
| 255 | 262 | // | |
| 256 | 263 | // Fails with unauthenticated or permission_denied as the other job RPCs, | |
| 257 | 264 | // with failed_precondition and a JobEnded detail if the job has ended, and | |
| @@ -266,8 +273,10 @@ type RunnerServiceClient interface { | |||
| 266 | 273 | // | |
| 267 | 274 | // It is idempotent: the summary of a step is replaced by each call, so a | |
| 268 | 275 | // retry changes nothing, and an empty markdown removes the summary of the | |
| 269 | - | // step. The Markdown is at most 1 MiB (1,048,576 bytes) and valid UTF-8; | |
| 270 | - | // clients set a message size limit above it. | |
| 276 | + | // step. The Markdown is at most 1 MiB (1,048,576 bytes) and valid UTF-8. The | |
| 277 | + | // server reads requests of up to 1 MiB plus the envelope (job id, step | |
| 278 | + | // number, framing), so a summary of exactly 1 MiB is accepted; clients set | |
| 279 | + | // their own message size limit above that. | |
| 271 | 280 | // | |
| 272 | 281 | // Fails with invalid_argument if a rule is broken (size, UTF-8, step number) | |
| 273 | 282 | // and with failed_precondition and a JobEnded detail if the job has ended. | |
| @@ -456,7 +465,12 @@ type RunnerServiceHandler interface { | |||
| 456 | 465 | // step_number present in annotations, the annotations of that step stored | |
| 457 | 466 | // so far are replaced by the ones of the request, so a retry never | |
| 458 | 467 | // duplicates them. A step number absent from the request keeps its | |
| 459 | - | // annotations. | |
| 468 | + | // annotations. The step of an annotation need not be in the steps of the | |
| 469 | + | // same call, and may already be COMPLETED: its annotations can still be | |
| 470 | + | // replaced (the rule that a COMPLETED step cannot change applies to | |
| 471 | + | // StepUpdate, not to annotations), until the job ends. A runner sends one | |
| 472 | + | // UpdateJob (or CompleteJob) at a time for a job, never concurrent calls, | |
| 473 | + | // so replacements apply in the order of the calls. | |
| 460 | 474 | // | |
| 461 | 475 | // Fails with invalid_argument if a rule is broken (including the annotation | |
| 462 | 476 | // limits), with failed_precondition if a step goes back (a COMPLETED step | |
| @@ -566,7 +580,8 @@ type RunnerServiceHandler interface { | |||
| 566 | 580 | // ends are completed by the server as CI_CONCLUSION_CANCELLED (or SKIPPED when | |
| 567 | 581 | // they never started and the job did not end by cancellation). | |
| 568 | 582 | // | |
| 569 | - | // Annotations are applied as in UpdateJob, together with the conclusion. | |
| 583 | + | // Annotations are applied as in UpdateJob (replacement per step number, also | |
| 584 | + | // for COMPLETED steps and steps not in steps), together with the conclusion. | |
| 570 | 585 | // Summaries are not part of this call: a runner sends them with | |
| 571 | 586 | // UploadSummary before it. | |
| 572 | 587 | // | |
| @@ -590,9 +605,10 @@ type RunnerServiceHandler interface { | |||
| 590 | 605 | // as is. Only a failure of the call itself (credential, ended job, bad | |
| 591 | 606 | // request, server error) is an RPC error; the runner then fails the job. | |
| 592 | 607 | // | |
| 593 | - | // Resolution is stable for a run: the same ref resolves to the same sha for | |
| 594 | - | // every job and every call of one attempt of the run. A re-run attempt | |
| 595 | - | // resolves again. | |
| 608 | + | // Resolution is stable for a run attempt: the same ref resolves to the same | |
| 609 | + | // sha (ResolvedAction.resolved_sha) for every job and every call of that | |
| 610 | + | // attempt. A re-run attempt resolves again. Tokens are not shared: each | |
| 611 | + | // job gets its own (ResolvedAction.token). | |
| 596 | 612 | // | |
| 597 | 613 | // Fails with unauthenticated or permission_denied as the other job RPCs, | |
| 598 | 614 | // with failed_precondition and a JobEnded detail if the job has ended, and | |
| @@ -607,8 +623,10 @@ type RunnerServiceHandler interface { | |||
| 607 | 623 | // | |
| 608 | 624 | // It is idempotent: the summary of a step is replaced by each call, so a | |
| 609 | 625 | // retry changes nothing, and an empty markdown removes the summary of the | |
| 610 | - | // step. The Markdown is at most 1 MiB (1,048,576 bytes) and valid UTF-8; | |
| 611 | - | // clients set a message size limit above it. | |
| 626 | + | // step. The Markdown is at most 1 MiB (1,048,576 bytes) and valid UTF-8. The | |
| 627 | + | // server reads requests of up to 1 MiB plus the envelope (job id, step | |
| 628 | + | // number, framing), so a summary of exactly 1 MiB is accepted; clients set | |
| 629 | + | // their own message size limit above that. | |
| 612 | 630 | // | |
| 613 | 631 | // Fails with invalid_argument if a rule is broken (size, UTF-8, step number) | |
| 614 | 632 | // and with failed_precondition and a JobEnded detail if the job has ended. | |
| @@ -115,7 +115,12 @@ type RunnerServiceClient interface { | |||||
| 115 | // step_number present in annotations, the annotations of that step stored | 115 | // step_number present in annotations, the annotations of that step stored | ||
| 116 | // so far are replaced by the ones of the request, so a retry never | 116 | // so far are replaced by the ones of the request, so a retry never | ||
| 117 | // duplicates them. A step number absent from the request keeps its | 117 | // duplicates them. A step number absent from the request keeps its | ||
| 118 | - | // annotations. | 118 | + | // annotations. The step of an annotation need not be in the steps of the |
| 119 | + | // same call, and may already be COMPLETED: its annotations can still be | |||
| 120 | + | // replaced (the rule that a COMPLETED step cannot change applies to | |||
| 121 | + | // StepUpdate, not to annotations), until the job ends. A runner sends one | |||
| 122 | + | // UpdateJob (or CompleteJob) at a time for a job, never concurrent calls, | |||
| 123 | + | // so replacements apply in the order of the calls. | |||
| 119 | // | 124 | // | ||
| 120 | // Fails with invalid_argument if a rule is broken (including the annotation | 125 | // Fails with invalid_argument if a rule is broken (including the annotation | ||
| 121 | // limits), with failed_precondition if a step goes back (a COMPLETED step | 126 | // limits), with failed_precondition if a step goes back (a COMPLETED step | ||
| @@ -225,7 +230,8 @@ type RunnerServiceClient interface { | |||||
| 225 | // ends are completed by the server as CI_CONCLUSION_CANCELLED (or SKIPPED when | 230 | // ends are completed by the server as CI_CONCLUSION_CANCELLED (or SKIPPED when | ||
| 226 | // they never started and the job did not end by cancellation). | 231 | // they never started and the job did not end by cancellation). | ||
| 227 | // | 232 | // | ||
| 228 | - | // Annotations are applied as in UpdateJob, together with the conclusion. | 233 | + | // Annotations are applied as in UpdateJob (replacement per step number, also |
| 234 | + | // for COMPLETED steps and steps not in steps), together with the conclusion. | |||
| 229 | // Summaries are not part of this call: a runner sends them with | 235 | // Summaries are not part of this call: a runner sends them with | ||
| 230 | // UploadSummary before it. | 236 | // UploadSummary before it. | ||
| 231 | // | 237 | // | ||
| @@ -249,9 +255,10 @@ type RunnerServiceClient interface { | |||||
| 249 | // as is. Only a failure of the call itself (credential, ended job, bad | 255 | // as is. Only a failure of the call itself (credential, ended job, bad | ||
| 250 | // request, server error) is an RPC error; the runner then fails the job. | 256 | // request, server error) is an RPC error; the runner then fails the job. | ||
| 251 | // | 257 | // | ||
| 252 | - | // Resolution is stable for a run: the same ref resolves to the same sha for | 258 | + | // Resolution is stable for a run attempt: the same ref resolves to the same |
| 253 | - | // every job and every call of one attempt of the run. A re-run attempt | 259 | + | // sha (ResolvedAction.resolved_sha) for every job and every call of that |
| 254 | - | // resolves again. | 260 | + | // attempt. A re-run attempt resolves again. Tokens are not shared: each |
| 261 | + | // job gets its own (ResolvedAction.token). | |||
| 255 | // | 262 | // | ||
| 256 | // Fails with unauthenticated or permission_denied as the other job RPCs, | 263 | // Fails with unauthenticated or permission_denied as the other job RPCs, | ||
| 257 | // with failed_precondition and a JobEnded detail if the job has ended, and | 264 | // with failed_precondition and a JobEnded detail if the job has ended, and | ||
| @@ -266,8 +273,10 @@ type RunnerServiceClient interface { | |||||
| 266 | // | 273 | // | ||
| 267 | // It is idempotent: the summary of a step is replaced by each call, so a | 274 | // It is idempotent: the summary of a step is replaced by each call, so a | ||
| 268 | // retry changes nothing, and an empty markdown removes the summary of the | 275 | // retry changes nothing, and an empty markdown removes the summary of the | ||
| 269 | - | // step. The Markdown is at most 1 MiB (1,048,576 bytes) and valid UTF-8; | 276 | + | // step. The Markdown is at most 1 MiB (1,048,576 bytes) and valid UTF-8. The |
| 270 | - | // clients set a message size limit above it. | 277 | + | // server reads requests of up to 1 MiB plus the envelope (job id, step |
| 278 | + | // number, framing), so a summary of exactly 1 MiB is accepted; clients set | |||
| 279 | + | // their own message size limit above that. | |||
| 271 | // | 280 | // | ||
| 272 | // Fails with invalid_argument if a rule is broken (size, UTF-8, step number) | 281 | // Fails with invalid_argument if a rule is broken (size, UTF-8, step number) | ||
| 273 | // and with failed_precondition and a JobEnded detail if the job has ended. | 282 | // and with failed_precondition and a JobEnded detail if the job has ended. | ||
| @@ -456,7 +465,12 @@ type RunnerServiceHandler interface { | |||||
| 456 | // step_number present in annotations, the annotations of that step stored | 465 | // step_number present in annotations, the annotations of that step stored | ||
| 457 | // so far are replaced by the ones of the request, so a retry never | 466 | // so far are replaced by the ones of the request, so a retry never | ||
| 458 | // duplicates them. A step number absent from the request keeps its | 467 | // duplicates them. A step number absent from the request keeps its | ||
| 459 | - | // annotations. | 468 | + | // annotations. The step of an annotation need not be in the steps of the |
| 469 | + | // same call, and may already be COMPLETED: its annotations can still be | |||
| 470 | + | // replaced (the rule that a COMPLETED step cannot change applies to | |||
| 471 | + | // StepUpdate, not to annotations), until the job ends. A runner sends one | |||
| 472 | + | // UpdateJob (or CompleteJob) at a time for a job, never concurrent calls, | |||
| 473 | + | // so replacements apply in the order of the calls. | |||
| 460 | // | 474 | // | ||
| 461 | // Fails with invalid_argument if a rule is broken (including the annotation | 475 | // Fails with invalid_argument if a rule is broken (including the annotation | ||
| 462 | // limits), with failed_precondition if a step goes back (a COMPLETED step | 476 | // limits), with failed_precondition if a step goes back (a COMPLETED step | ||
| @@ -566,7 +580,8 @@ type RunnerServiceHandler interface { | |||||
| 566 | // ends are completed by the server as CI_CONCLUSION_CANCELLED (or SKIPPED when | 580 | // ends are completed by the server as CI_CONCLUSION_CANCELLED (or SKIPPED when | ||
| 567 | // they never started and the job did not end by cancellation). | 581 | // they never started and the job did not end by cancellation). | ||
| 568 | // | 582 | // | ||
| 569 | - | // Annotations are applied as in UpdateJob, together with the conclusion. | 583 | + | // Annotations are applied as in UpdateJob (replacement per step number, also |
| 584 | + | // for COMPLETED steps and steps not in steps), together with the conclusion. | |||
| 570 | // Summaries are not part of this call: a runner sends them with | 585 | // Summaries are not part of this call: a runner sends them with | ||
| 571 | // UploadSummary before it. | 586 | // UploadSummary before it. | ||
| 572 | // | 587 | // | ||
| @@ -590,9 +605,10 @@ type RunnerServiceHandler interface { | |||||
| 590 | // as is. Only a failure of the call itself (credential, ended job, bad | 605 | // as is. Only a failure of the call itself (credential, ended job, bad | ||
| 591 | // request, server error) is an RPC error; the runner then fails the job. | 606 | // request, server error) is an RPC error; the runner then fails the job. | ||
| 592 | // | 607 | // | ||
| 593 | - | // Resolution is stable for a run: the same ref resolves to the same sha for | 608 | + | // Resolution is stable for a run attempt: the same ref resolves to the same |
| 594 | - | // every job and every call of one attempt of the run. A re-run attempt | 609 | + | // sha (ResolvedAction.resolved_sha) for every job and every call of that |
| 595 | - | // resolves again. | 610 | + | // attempt. A re-run attempt resolves again. Tokens are not shared: each |
| 611 | + | // job gets its own (ResolvedAction.token). | |||
| 596 | // | 612 | // | ||
| 597 | // Fails with unauthenticated or permission_denied as the other job RPCs, | 613 | // Fails with unauthenticated or permission_denied as the other job RPCs, | ||
| 598 | // with failed_precondition and a JobEnded detail if the job has ended, and | 614 | // with failed_precondition and a JobEnded detail if the job has ended, and | ||
| @@ -607,8 +623,10 @@ type RunnerServiceHandler interface { | |||||
| 607 | // | 623 | // | ||
| 608 | // It is idempotent: the summary of a step is replaced by each call, so a | 624 | // It is idempotent: the summary of a step is replaced by each call, so a | ||
| 609 | // retry changes nothing, and an empty markdown removes the summary of the | 625 | // retry changes nothing, and an empty markdown removes the summary of the | ||
| 610 | - | // step. The Markdown is at most 1 MiB (1,048,576 bytes) and valid UTF-8; | 626 | + | // step. The Markdown is at most 1 MiB (1,048,576 bytes) and valid UTF-8. The |
| 611 | - | // clients set a message size limit above it. | 627 | + | // server reads requests of up to 1 MiB plus the envelope (job id, step |
| 628 | + | // number, framing), so a summary of exactly 1 MiB is accepted; clients set | |||
| 629 | + | // their own message size limit above that. | |||
| 612 | // | 630 | // | ||
| 613 | // Fails with invalid_argument if a rule is broken (size, UTF-8, step number) | 631 | // Fails with invalid_argument if a rule is broken (size, UTF-8, step number) | ||
| 614 | // and with failed_precondition and a JobEnded detail if the job has ended. | 632 | // and with failed_precondition and a JobEnded detail if the job has ended. | ||
M gen/ermite/run.pb.go +18 -5 generated file: collapsed
M gen/ermite/runner.pb.go +23 -14 generated file: collapsed
M gen_test.go +2 -2
| @@ -389,7 +389,7 @@ func TestCI2FieldNumbers(t *testing.T) { | |||
| 389 | 389 | {&ermite.ListAnnotationsResponse{}, map[string]int{"annotations": 1, "truncated": 2}}, | |
| 390 | 390 | {&ermite.JobAnnotation{}, map[string]int{"job_id": 1, "annotation": 2}}, | |
| 391 | 391 | {&ermite.GetStepSummariesRequest{}, map[string]int{"repo": 1, "job_id": 2, "attempt": 3}}, | |
| 392 | - | {&ermite.GetStepSummariesResponse{}, map[string]int{"summaries": 1}}, | |
| 392 | + | {&ermite.GetStepSummariesResponse{}, map[string]int{"summaries": 1, "truncated": 2}}, | |
| 393 | 393 | {&ermite.StepSummary{}, map[string]int{"step_number": 1, "markdown": 2}}, | |
| 394 | 394 | } | |
| 395 | 395 | for _, tt := range tests { | |
| @@ -433,7 +433,7 @@ func TestCI2RoundTrip(t *testing.T) { | |||
| 433 | 433 | }}, | |
| 434 | 434 | &ermite.UploadSummaryRequest{JobId: "j1", StepNumber: 2, Markdown: "# hi"}, | |
| 435 | 435 | &ermite.ListAnnotationsResponse{Annotations: []*ermite.JobAnnotation{{JobId: "j1", Annotation: &ermite.Annotation{Message: "m"}}}, Truncated: true}, | |
| 436 | - | &ermite.GetStepSummariesResponse{Summaries: []*ermite.StepSummary{{StepNumber: 2, Markdown: "# hi"}}}, | |
| 436 | + | &ermite.GetStepSummariesResponse{Summaries: []*ermite.StepSummary{{StepNumber: 2, Markdown: "# hi"}}, Truncated: true}, | |
| 437 | 437 | &ermite.RunJob{Id: "j1", Steps: []*ermite.Step{{Number: 2, Outcome: ermite.CiConclusion_CI_CONCLUSION_FAILURE}}}, | |
| 438 | 438 | } | |
| 439 | 439 | for _, in := range msgs { | |
| @@ -389,7 +389,7 @@ func TestCI2FieldNumbers(t *testing.T) { | |||||
| 389 | {&ermite.ListAnnotationsResponse{}, map[string]int{"annotations": 1, "truncated": 2}}, | 389 | {&ermite.ListAnnotationsResponse{}, map[string]int{"annotations": 1, "truncated": 2}}, | ||
| 390 | {&ermite.JobAnnotation{}, map[string]int{"job_id": 1, "annotation": 2}}, | 390 | {&ermite.JobAnnotation{}, map[string]int{"job_id": 1, "annotation": 2}}, | ||
| 391 | {&ermite.GetStepSummariesRequest{}, map[string]int{"repo": 1, "job_id": 2, "attempt": 3}}, | 391 | {&ermite.GetStepSummariesRequest{}, map[string]int{"repo": 1, "job_id": 2, "attempt": 3}}, | ||
| 392 | - | {&ermite.GetStepSummariesResponse{}, map[string]int{"summaries": 1}}, | 392 | + | {&ermite.GetStepSummariesResponse{}, map[string]int{"summaries": 1, "truncated": 2}}, |
| 393 | {&ermite.StepSummary{}, map[string]int{"step_number": 1, "markdown": 2}}, | 393 | {&ermite.StepSummary{}, map[string]int{"step_number": 1, "markdown": 2}}, | ||
| 394 | } | 394 | } | ||
| 395 | for _, tt := range tests { | 395 | for _, tt := range tests { | ||
| @@ -433,7 +433,7 @@ func TestCI2RoundTrip(t *testing.T) { | |||||
| 433 | }}, | 433 | }}, | ||
| 434 | &ermite.UploadSummaryRequest{JobId: "j1", StepNumber: 2, Markdown: "# hi"}, | 434 | &ermite.UploadSummaryRequest{JobId: "j1", StepNumber: 2, Markdown: "# hi"}, | ||
| 435 | &ermite.ListAnnotationsResponse{Annotations: []*ermite.JobAnnotation{{JobId: "j1", Annotation: &ermite.Annotation{Message: "m"}}}, Truncated: true}, | 435 | &ermite.ListAnnotationsResponse{Annotations: []*ermite.JobAnnotation{{JobId: "j1", Annotation: &ermite.Annotation{Message: "m"}}}, Truncated: true}, | ||
| 436 | - | &ermite.GetStepSummariesResponse{Summaries: []*ermite.StepSummary{{StepNumber: 2, Markdown: "# hi"}}}, | 436 | + | &ermite.GetStepSummariesResponse{Summaries: []*ermite.StepSummary{{StepNumber: 2, Markdown: "# hi"}}, Truncated: true}, |
| 437 | &ermite.RunJob{Id: "j1", Steps: []*ermite.Step{{Number: 2, Outcome: ermite.CiConclusion_CI_CONCLUSION_FAILURE}}}, | 437 | &ermite.RunJob{Id: "j1", Steps: []*ermite.Step{{Number: 2, Outcome: ermite.CiConclusion_CI_CONCLUSION_FAILURE}}}, | ||
| 438 | } | 438 | } | ||
| 439 | for _, in := range msgs { | 439 | for _, in := range msgs { | ||
M proto/ermite/run.proto +13 -4
| @@ -283,7 +283,9 @@ service RunService { | |||
| 283 | 283 | rpc GetJob(GetJobRequest) returns (GetJobResponse); | |
| 284 | 284 | // ListAnnotations lists the annotations of a run attempt, optionally of one | |
| 285 | 285 | // job, ordered by job (as in GetRun), step number, then the order in which | |
| 286 | - | // the step produced them. Needs the same access as GetRun. Returns at most | |
| 286 | + | // the step produced them. For each job it gives the annotations of the | |
| 287 | + | // attempt in which that job executed (RunJob.attempt), which is lower than | |
| 288 | + | // the attempt of the run for a job kept by a re-run of failed jobs only. Needs the same access as GetRun. Returns at most | |
| 287 | 289 | // 1,000 annotations (truncated tells). A run without annotations gives an | |
| 288 | 290 | // empty list. Only servers with the feature "ci.annotations" implement it | |
| 289 | 291 | // (unimplemented otherwise). Fails with not_found if the run, the attempt or | |
| @@ -291,7 +293,9 @@ service RunService { | |||
| 291 | 293 | rpc ListAnnotations(ListAnnotationsRequest) returns (ListAnnotationsResponse); | |
| 292 | 294 | // GetStepSummaries returns the job summaries (the Markdown written to | |
| 293 | 295 | // GITHUB_STEP_SUMMARY) of the steps of a job that have one, ordered by step | |
| 294 | - | // number. Needs the same access as GetJob. Only servers with the feature | |
| 296 | + | // number. Like GitHub, it returns at most 20 summaries per job: the first 20 | |
| 297 | + | // steps that have one, in step order; truncated says there are more. Needs | |
| 298 | + | // the same access as GetJob. Only servers with the feature | |
| 295 | 299 | // "ci.summaries" implement it (unimplemented otherwise). A job without | |
| 296 | 300 | // summaries gives an empty list. Fails with not_found if the job or the | |
| 297 | 301 | // attempt does not exist. | |
| @@ -422,7 +426,9 @@ message ListAnnotationsRequest { | |||
| 422 | 426 | string repo = 1; | |
| 423 | 427 | // RunId is the Run.id. | |
| 424 | 428 | int64 run_id = 2; | |
| 425 | - | // Attempt is the attempt to read. 0 means the latest. | |
| 429 | + | // Attempt is the attempt to read. 0 means the latest, and then each job | |
| 430 | + | // contributes the annotations of its own RunJob.attempt (not necessarily the | |
| 431 | + | // latest attempt of the run, see ListAnnotations). | |
| 426 | 432 | int32 attempt = 3; | |
| 427 | 433 | // JobId restricts the result to one job (RunJob.id). Empty means every job | |
| 428 | 434 | // of the run. | |
| @@ -459,8 +465,11 @@ message GetStepSummariesRequest { | |||
| 459 | 465 | // GetStepSummariesResponse holds the summaries of a job. | |
| 460 | 466 | message GetStepSummariesResponse { | |
| 461 | 467 | // Summaries are the summaries of the steps that have one, ordered by step | |
| 462 | - | // number. | |
| 468 | + | // number: at most 20, the first 20 steps having one. | |
| 463 | 469 | repeated StepSummary summaries = 1; | |
| 470 | + | // Truncated is true when the job has more than 20 steps with a summary and | |
| 471 | + | // summaries holds only the first 20. | |
| 472 | + | bool truncated = 2; | |
| 464 | 473 | } | |
| 465 | 474 | ||
| 466 | 475 | // StepSummary is the job summary of one step. | |
| @@ -283,7 +283,9 @@ service RunService { | |||||
| 283 | rpc GetJob(GetJobRequest) returns (GetJobResponse); | 283 | rpc GetJob(GetJobRequest) returns (GetJobResponse); | ||
| 284 | // ListAnnotations lists the annotations of a run attempt, optionally of one | 284 | // ListAnnotations lists the annotations of a run attempt, optionally of one | ||
| 285 | // job, ordered by job (as in GetRun), step number, then the order in which | 285 | // job, ordered by job (as in GetRun), step number, then the order in which | ||
| 286 | - | // the step produced them. Needs the same access as GetRun. Returns at most | 286 | + | // the step produced them. For each job it gives the annotations of the |
| 287 | + | // attempt in which that job executed (RunJob.attempt), which is lower than | |||
| 288 | + | // the attempt of the run for a job kept by a re-run of failed jobs only. Needs the same access as GetRun. Returns at most | |||
| 287 | // 1,000 annotations (truncated tells). A run without annotations gives an | 289 | // 1,000 annotations (truncated tells). A run without annotations gives an | ||
| 288 | // empty list. Only servers with the feature "ci.annotations" implement it | 290 | // empty list. Only servers with the feature "ci.annotations" implement it | ||
| 289 | // (unimplemented otherwise). Fails with not_found if the run, the attempt or | 291 | // (unimplemented otherwise). Fails with not_found if the run, the attempt or | ||
| @@ -291,7 +293,9 @@ service RunService { | |||||
| 291 | rpc ListAnnotations(ListAnnotationsRequest) returns (ListAnnotationsResponse); | 293 | rpc ListAnnotations(ListAnnotationsRequest) returns (ListAnnotationsResponse); | ||
| 292 | // GetStepSummaries returns the job summaries (the Markdown written to | 294 | // GetStepSummaries returns the job summaries (the Markdown written to | ||
| 293 | // GITHUB_STEP_SUMMARY) of the steps of a job that have one, ordered by step | 295 | // GITHUB_STEP_SUMMARY) of the steps of a job that have one, ordered by step | ||
| 294 | - | // number. Needs the same access as GetJob. Only servers with the feature | 296 | + | // number. Like GitHub, it returns at most 20 summaries per job: the first 20 |
| 297 | + | // steps that have one, in step order; truncated says there are more. Needs | |||
| 298 | + | // the same access as GetJob. Only servers with the feature | |||
| 295 | // "ci.summaries" implement it (unimplemented otherwise). A job without | 299 | // "ci.summaries" implement it (unimplemented otherwise). A job without | ||
| 296 | // summaries gives an empty list. Fails with not_found if the job or the | 300 | // summaries gives an empty list. Fails with not_found if the job or the | ||
| 297 | // attempt does not exist. | 301 | // attempt does not exist. | ||
| @@ -422,7 +426,9 @@ message ListAnnotationsRequest { | |||||
| 422 | string repo = 1; | 426 | string repo = 1; | ||
| 423 | // RunId is the Run.id. | 427 | // RunId is the Run.id. | ||
| 424 | int64 run_id = 2; | 428 | int64 run_id = 2; | ||
| 425 | - | // Attempt is the attempt to read. 0 means the latest. | 429 | + | // Attempt is the attempt to read. 0 means the latest, and then each job |
| 430 | + | // contributes the annotations of its own RunJob.attempt (not necessarily the | |||
| 431 | + | // latest attempt of the run, see ListAnnotations). | |||
| 426 | int32 attempt = 3; | 432 | int32 attempt = 3; | ||
| 427 | // JobId restricts the result to one job (RunJob.id). Empty means every job | 433 | // JobId restricts the result to one job (RunJob.id). Empty means every job | ||
| 428 | // of the run. | 434 | // of the run. | ||
| @@ -459,8 +465,11 @@ message GetStepSummariesRequest { | |||||
| 459 | // GetStepSummariesResponse holds the summaries of a job. | 465 | // GetStepSummariesResponse holds the summaries of a job. | ||
| 460 | message GetStepSummariesResponse { | 466 | message GetStepSummariesResponse { | ||
| 461 | // Summaries are the summaries of the steps that have one, ordered by step | 467 | // Summaries are the summaries of the steps that have one, ordered by step | ||
| 462 | - | // number. | 468 | + | // number: at most 20, the first 20 steps having one. |
| 463 | repeated StepSummary summaries = 1; | 469 | repeated StepSummary summaries = 1; | ||
| 470 | + | // Truncated is true when the job has more than 20 steps with a summary and | |||
| 471 | + | // summaries holds only the first 20. | |||
| 472 | + | bool truncated = 2; | |||
| 464 | } | 473 | } | ||
| 465 | 474 | ||||
| 466 | // StepSummary is the job summary of one step. | 475 | // StepSummary is the job summary of one step. | ||
M proto/ermite/runner.proto +39 -21
| @@ -229,7 +229,12 @@ service RunnerService { | |||
| 229 | 229 | // step_number present in annotations, the annotations of that step stored | |
| 230 | 230 | // so far are replaced by the ones of the request, so a retry never | |
| 231 | 231 | // duplicates them. A step number absent from the request keeps its | |
| 232 | - | // annotations. | |
| 232 | + | // annotations. The step of an annotation need not be in the steps of the | |
| 233 | + | // same call, and may already be COMPLETED: its annotations can still be | |
| 234 | + | // replaced (the rule that a COMPLETED step cannot change applies to | |
| 235 | + | // StepUpdate, not to annotations), until the job ends. A runner sends one | |
| 236 | + | // UpdateJob (or CompleteJob) at a time for a job, never concurrent calls, | |
| 237 | + | // so replacements apply in the order of the calls. | |
| 233 | 238 | // | |
| 234 | 239 | // Fails with invalid_argument if a rule is broken (including the annotation | |
| 235 | 240 | // limits), with failed_precondition if a step goes back (a COMPLETED step | |
| @@ -339,7 +344,8 @@ service RunnerService { | |||
| 339 | 344 | // ends are completed by the server as CI_CONCLUSION_CANCELLED (or SKIPPED when | |
| 340 | 345 | // they never started and the job did not end by cancellation). | |
| 341 | 346 | // | |
| 342 | - | // Annotations are applied as in UpdateJob, together with the conclusion. | |
| 347 | + | // Annotations are applied as in UpdateJob (replacement per step number, also | |
| 348 | + | // for COMPLETED steps and steps not in steps), together with the conclusion. | |
| 343 | 349 | // Summaries are not part of this call: a runner sends them with | |
| 344 | 350 | // UploadSummary before it. | |
| 345 | 351 | // | |
| @@ -363,9 +369,10 @@ service RunnerService { | |||
| 363 | 369 | // as is. Only a failure of the call itself (credential, ended job, bad | |
| 364 | 370 | // request, server error) is an RPC error; the runner then fails the job. | |
| 365 | 371 | // | |
| 366 | - | // Resolution is stable for a run: the same ref resolves to the same sha for | |
| 367 | - | // every job and every call of one attempt of the run. A re-run attempt | |
| 368 | - | // resolves again. | |
| 372 | + | // Resolution is stable for a run attempt: the same ref resolves to the same | |
| 373 | + | // sha (ResolvedAction.resolved_sha) for every job and every call of that | |
| 374 | + | // attempt. A re-run attempt resolves again. Tokens are not shared: each | |
| 375 | + | // job gets its own (ResolvedAction.token). | |
| 369 | 376 | // | |
| 370 | 377 | // Fails with unauthenticated or permission_denied as the other job RPCs, | |
| 371 | 378 | // with failed_precondition and a JobEnded detail if the job has ended, and | |
| @@ -380,8 +387,10 @@ service RunnerService { | |||
| 380 | 387 | // | |
| 381 | 388 | // It is idempotent: the summary of a step is replaced by each call, so a | |
| 382 | 389 | // retry changes nothing, and an empty markdown removes the summary of the | |
| 383 | - | // step. The Markdown is at most 1 MiB (1,048,576 bytes) and valid UTF-8; | |
| 384 | - | // clients set a message size limit above it. | |
| 390 | + | // step. The Markdown is at most 1 MiB (1,048,576 bytes) and valid UTF-8. The | |
| 391 | + | // server reads requests of up to 1 MiB plus the envelope (job id, step | |
| 392 | + | // number, framing), so a summary of exactly 1 MiB is accepted; clients set | |
| 393 | + | // their own message size limit above that. | |
| 385 | 394 | // | |
| 386 | 395 | // Fails with invalid_argument if a rule is broken (size, UTF-8, step number) | |
| 387 | 396 | // and with failed_precondition and a JobEnded detail if the job has ended. | |
| @@ -548,8 +557,9 @@ message UpdateJobRequest { | |||
| 548 | 557 | // Annotations are the annotations of the steps that the call names: for | |
| 549 | 558 | // each step_number present, all the annotations of that step known so far, | |
| 550 | 559 | // not only the new ones (see the rules on UpdateJob). At most 10 per level | |
| 551 | - | // and per step; more is invalid_argument. The server ignores them without | |
| 552 | - | // the feature "ci.annotations". | |
| 560 | + | // and per step, and each one within the limits of Annotation; otherwise the | |
| 561 | + | // whole call is invalid_argument. The server ignores them without the | |
| 562 | + | // feature "ci.annotations". | |
| 553 | 563 | repeated Annotation annotations = 3; | |
| 554 | 564 | } | |
| 555 | 565 | ||
| @@ -741,19 +751,22 @@ message CancelRequest { | |||
| 741 | 751 | // produces them from the workflow commands ::notice, ::warning and ::error and | |
| 742 | 752 | // from problem matchers, after masking. | |
| 743 | 753 | // | |
| 744 | - | // The runner sends at most 10 annotations of each level per step (the ones | |
| 745 | - | // beyond only reach the log) and the server rejects more. | |
| 754 | + | // Limits, checked by the server: at most 10 annotations of each level per step | |
| 755 | + | // (the runner sends no more: the ones beyond only reach the log, as with | |
| 756 | + | // GitHub). A call that breaks a limit below is rejected whole with | |
| 757 | + | // invalid_argument. Lengths count characters (Unicode code points), not bytes. | |
| 746 | 758 | message Annotation { | |
| 747 | 759 | // Level is the severity. Required. | |
| 748 | 760 | AnnotationLevel level = 1; | |
| 749 | - | // Title is the optional title. Empty when not given. | |
| 761 | + | // Title is the optional title, at most 255 characters. Empty when not given. | |
| 750 | 762 | string title = 2; | |
| 751 | - | // Message is the text, at most 4,096 characters (the runner cuts longer | |
| 752 | - | // ones). Required, not empty. | |
| 763 | + | // Message is the text. Required, not empty, at most 4,096 characters; a | |
| 764 | + | // longer one is invalid_argument. The runner never sends a longer one: like | |
| 765 | + | // GitHub, it only logs such an annotation. | |
| 753 | 766 | string message = 3; | |
| 754 | 767 | // File is the path the annotation is about, relative to the repository when | |
| 755 | - | // the runner can tell, else as given. Empty when the annotation is not about | |
| 756 | - | // a file. | |
| 768 | + | // the runner can tell, else as given. At most 1,024 characters. Empty when | |
| 769 | + | // the annotation is not about a file. | |
| 757 | 770 | string file = 4; | |
| 758 | 771 | // StartLine is the first line, counted from 1. 0 when not given. | |
| 759 | 772 | int32 start_line = 5; | |
| @@ -799,13 +812,17 @@ message ResolvedAction { | |||
| 799 | 812 | // NameWithOwner is the repository of the action, "owner/repo", with the | |
| 800 | 813 | // case of the repository as the source gives it. Empty when error is set. | |
| 801 | 814 | string name_with_owner = 2; | |
| 802 | - | // Path is the sub-path of the action inside the repository, without leading | |
| 803 | - | // or trailing slash: "path/to/action" for "owner/repo/path/to/action@ref". | |
| 804 | - | // Empty for an action at the root of the repository. | |
| 815 | + | // Path is the sub-path of the action inside the repository, a clean | |
| 816 | + | // relative path: "path/to/action" for "owner/repo/path/to/action@ref", with | |
| 817 | + | // "/" separators, no leading or trailing slash, no empty, "." or ".." | |
| 818 | + | // element, never absolute. Empty for an action at the root of the | |
| 819 | + | // repository. | |
| 805 | 820 | string path = 3; | |
| 806 | 821 | // ResolvedSha is the full id of the commit the ref points to, 40 lowercase | |
| 807 | 822 | // hexadecimal characters for SHA-1 (the commit that an annotated tag points | |
| 808 | - | // to, not the tag object). Empty when error is set. | |
| 823 | + | // to, not the tag object). Stable for a run attempt: every job and every | |
| 824 | + | // call of the attempt gets the same value for the same ref. Empty when error | |
| 825 | + | // is set. | |
| 809 | 826 | string resolved_sha = 4; | |
| 810 | 827 | // TarballUrl is where to download the archive of the repository at | |
| 811 | 828 | // resolved_sha, a gzip-compressed tar with one top-level directory. The | |
| @@ -816,7 +833,8 @@ message ResolvedAction { | |||
| 816 | 833 | // For ACTION_SOURCE_ERMITE it is a read token for that one repository, | |
| 817 | 834 | // valid until the job ends, so a job can use an action of another private | |
| 818 | 835 | // repository of the server that its own repository token cannot read. It is | |
| 819 | - | // a secret: the runner masks it, and neither the runner nor the server logs | |
| 836 | + | // issued per job and never shared across jobs (two jobs resolving the same | |
| 837 | + | // action get different tokens). It is a secret: the runner masks it, and neither the runner nor the server logs | |
| 820 | 838 | // it. | |
| 821 | 839 | string token = 6; | |
| 822 | 840 | // Source is where the action was found. UNSPECIFIED when error is set. | |
| @@ -229,7 +229,12 @@ service RunnerService { | |||||
| 229 | // step_number present in annotations, the annotations of that step stored | 229 | // step_number present in annotations, the annotations of that step stored | ||
| 230 | // so far are replaced by the ones of the request, so a retry never | 230 | // so far are replaced by the ones of the request, so a retry never | ||
| 231 | // duplicates them. A step number absent from the request keeps its | 231 | // duplicates them. A step number absent from the request keeps its | ||
| 232 | - | // annotations. | 232 | + | // annotations. The step of an annotation need not be in the steps of the |
| 233 | + | // same call, and may already be COMPLETED: its annotations can still be | |||
| 234 | + | // replaced (the rule that a COMPLETED step cannot change applies to | |||
| 235 | + | // StepUpdate, not to annotations), until the job ends. A runner sends one | |||
| 236 | + | // UpdateJob (or CompleteJob) at a time for a job, never concurrent calls, | |||
| 237 | + | // so replacements apply in the order of the calls. | |||
| 233 | // | 238 | // | ||
| 234 | // Fails with invalid_argument if a rule is broken (including the annotation | 239 | // Fails with invalid_argument if a rule is broken (including the annotation | ||
| 235 | // limits), with failed_precondition if a step goes back (a COMPLETED step | 240 | // limits), with failed_precondition if a step goes back (a COMPLETED step | ||
| @@ -339,7 +344,8 @@ service RunnerService { | |||||
| 339 | // ends are completed by the server as CI_CONCLUSION_CANCELLED (or SKIPPED when | 344 | // ends are completed by the server as CI_CONCLUSION_CANCELLED (or SKIPPED when | ||
| 340 | // they never started and the job did not end by cancellation). | 345 | // they never started and the job did not end by cancellation). | ||
| 341 | // | 346 | // | ||
| 342 | - | // Annotations are applied as in UpdateJob, together with the conclusion. | 347 | + | // Annotations are applied as in UpdateJob (replacement per step number, also |
| 348 | + | // for COMPLETED steps and steps not in steps), together with the conclusion. | |||
| 343 | // Summaries are not part of this call: a runner sends them with | 349 | // Summaries are not part of this call: a runner sends them with | ||
| 344 | // UploadSummary before it. | 350 | // UploadSummary before it. | ||
| 345 | // | 351 | // | ||
| @@ -363,9 +369,10 @@ service RunnerService { | |||||
| 363 | // as is. Only a failure of the call itself (credential, ended job, bad | 369 | // as is. Only a failure of the call itself (credential, ended job, bad | ||
| 364 | // request, server error) is an RPC error; the runner then fails the job. | 370 | // request, server error) is an RPC error; the runner then fails the job. | ||
| 365 | // | 371 | // | ||
| 366 | - | // Resolution is stable for a run: the same ref resolves to the same sha for | 372 | + | // Resolution is stable for a run attempt: the same ref resolves to the same |
| 367 | - | // every job and every call of one attempt of the run. A re-run attempt | 373 | + | // sha (ResolvedAction.resolved_sha) for every job and every call of that |
| 368 | - | // resolves again. | 374 | + | // attempt. A re-run attempt resolves again. Tokens are not shared: each |
| 375 | + | // job gets its own (ResolvedAction.token). | |||
| 369 | // | 376 | // | ||
| 370 | // Fails with unauthenticated or permission_denied as the other job RPCs, | 377 | // Fails with unauthenticated or permission_denied as the other job RPCs, | ||
| 371 | // with failed_precondition and a JobEnded detail if the job has ended, and | 378 | // with failed_precondition and a JobEnded detail if the job has ended, and | ||
| @@ -380,8 +387,10 @@ service RunnerService { | |||||
| 380 | // | 387 | // | ||
| 381 | // It is idempotent: the summary of a step is replaced by each call, so a | 388 | // It is idempotent: the summary of a step is replaced by each call, so a | ||
| 382 | // retry changes nothing, and an empty markdown removes the summary of the | 389 | // retry changes nothing, and an empty markdown removes the summary of the | ||
| 383 | - | // step. The Markdown is at most 1 MiB (1,048,576 bytes) and valid UTF-8; | 390 | + | // step. The Markdown is at most 1 MiB (1,048,576 bytes) and valid UTF-8. The |
| 384 | - | // clients set a message size limit above it. | 391 | + | // server reads requests of up to 1 MiB plus the envelope (job id, step |
| 392 | + | // number, framing), so a summary of exactly 1 MiB is accepted; clients set | |||
| 393 | + | // their own message size limit above that. | |||
| 385 | // | 394 | // | ||
| 386 | // Fails with invalid_argument if a rule is broken (size, UTF-8, step number) | 395 | // Fails with invalid_argument if a rule is broken (size, UTF-8, step number) | ||
| 387 | // and with failed_precondition and a JobEnded detail if the job has ended. | 396 | // and with failed_precondition and a JobEnded detail if the job has ended. | ||
| @@ -548,8 +557,9 @@ message UpdateJobRequest { | |||||
| 548 | // Annotations are the annotations of the steps that the call names: for | 557 | // Annotations are the annotations of the steps that the call names: for | ||
| 549 | // each step_number present, all the annotations of that step known so far, | 558 | // each step_number present, all the annotations of that step known so far, | ||
| 550 | // not only the new ones (see the rules on UpdateJob). At most 10 per level | 559 | // not only the new ones (see the rules on UpdateJob). At most 10 per level | ||
| 551 | - | // and per step; more is invalid_argument. The server ignores them without | 560 | + | // and per step, and each one within the limits of Annotation; otherwise the |
| 552 | - | // the feature "ci.annotations". | 561 | + | // whole call is invalid_argument. The server ignores them without the |
| 562 | + | // feature "ci.annotations". | |||
| 553 | repeated Annotation annotations = 3; | 563 | repeated Annotation annotations = 3; | ||
| 554 | } | 564 | } | ||
| 555 | 565 | ||||
| @@ -741,19 +751,22 @@ message CancelRequest { | |||||
| 741 | // produces them from the workflow commands ::notice, ::warning and ::error and | 751 | // produces them from the workflow commands ::notice, ::warning and ::error and | ||
| 742 | // from problem matchers, after masking. | 752 | // from problem matchers, after masking. | ||
| 743 | // | 753 | // | ||
| 744 | - | // The runner sends at most 10 annotations of each level per step (the ones | 754 | + | // Limits, checked by the server: at most 10 annotations of each level per step |
| 745 | - | // beyond only reach the log) and the server rejects more. | 755 | + | // (the runner sends no more: the ones beyond only reach the log, as with |
| 756 | + | // GitHub). A call that breaks a limit below is rejected whole with | |||
| 757 | + | // invalid_argument. Lengths count characters (Unicode code points), not bytes. | |||
| 746 | message Annotation { | 758 | message Annotation { | ||
| 747 | // Level is the severity. Required. | 759 | // Level is the severity. Required. | ||
| 748 | AnnotationLevel level = 1; | 760 | AnnotationLevel level = 1; | ||
| 749 | - | // Title is the optional title. Empty when not given. | 761 | + | // Title is the optional title, at most 255 characters. Empty when not given. |
| 750 | string title = 2; | 762 | string title = 2; | ||
| 751 | - | // Message is the text, at most 4,096 characters (the runner cuts longer | 763 | + | // Message is the text. Required, not empty, at most 4,096 characters; a |
| 752 | - | // ones). Required, not empty. | 764 | + | // longer one is invalid_argument. The runner never sends a longer one: like |
| 765 | + | // GitHub, it only logs such an annotation. | |||
| 753 | string message = 3; | 766 | string message = 3; | ||
| 754 | // File is the path the annotation is about, relative to the repository when | 767 | // File is the path the annotation is about, relative to the repository when | ||
| 755 | - | // the runner can tell, else as given. Empty when the annotation is not about | 768 | + | // the runner can tell, else as given. At most 1,024 characters. Empty when |
| 756 | - | // a file. | 769 | + | // the annotation is not about a file. |
| 757 | string file = 4; | 770 | string file = 4; | ||
| 758 | // StartLine is the first line, counted from 1. 0 when not given. | 771 | // StartLine is the first line, counted from 1. 0 when not given. | ||
| 759 | int32 start_line = 5; | 772 | int32 start_line = 5; | ||
| @@ -799,13 +812,17 @@ message ResolvedAction { | |||||
| 799 | // NameWithOwner is the repository of the action, "owner/repo", with the | 812 | // NameWithOwner is the repository of the action, "owner/repo", with the | ||
| 800 | // case of the repository as the source gives it. Empty when error is set. | 813 | // case of the repository as the source gives it. Empty when error is set. | ||
| 801 | string name_with_owner = 2; | 814 | string name_with_owner = 2; | ||
| 802 | - | // Path is the sub-path of the action inside the repository, without leading | 815 | + | // Path is the sub-path of the action inside the repository, a clean |
| 803 | - | // or trailing slash: "path/to/action" for "owner/repo/path/to/action@ref". | 816 | + | // relative path: "path/to/action" for "owner/repo/path/to/action@ref", with |
| 804 | - | // Empty for an action at the root of the repository. | 817 | + | // "/" separators, no leading or trailing slash, no empty, "." or ".." |
| 818 | + | // element, never absolute. Empty for an action at the root of the | |||
| 819 | + | // repository. | |||
| 805 | string path = 3; | 820 | string path = 3; | ||
| 806 | // ResolvedSha is the full id of the commit the ref points to, 40 lowercase | 821 | // ResolvedSha is the full id of the commit the ref points to, 40 lowercase | ||
| 807 | // hexadecimal characters for SHA-1 (the commit that an annotated tag points | 822 | // hexadecimal characters for SHA-1 (the commit that an annotated tag points | ||
| 808 | - | // to, not the tag object). Empty when error is set. | 823 | + | // to, not the tag object). Stable for a run attempt: every job and every |
| 824 | + | // call of the attempt gets the same value for the same ref. Empty when error | |||
| 825 | + | // is set. | |||
| 809 | string resolved_sha = 4; | 826 | string resolved_sha = 4; | ||
| 810 | // TarballUrl is where to download the archive of the repository at | 827 | // TarballUrl is where to download the archive of the repository at | ||
| 811 | // resolved_sha, a gzip-compressed tar with one top-level directory. The | 828 | // resolved_sha, a gzip-compressed tar with one top-level directory. The | ||
| @@ -816,7 +833,8 @@ message ResolvedAction { | |||||
| 816 | // For ACTION_SOURCE_ERMITE it is a read token for that one repository, | 833 | // For ACTION_SOURCE_ERMITE it is a read token for that one repository, | ||
| 817 | // valid until the job ends, so a job can use an action of another private | 834 | // valid until the job ends, so a job can use an action of another private | ||
| 818 | // repository of the server that its own repository token cannot read. It is | 835 | // repository of the server that its own repository token cannot read. It is | ||
| 819 | - | // a secret: the runner masks it, and neither the runner nor the server logs | 836 | + | // issued per job and never shared across jobs (two jobs resolving the same |
| 837 | + | // action get different tokens). It is a secret: the runner masks it, and neither the runner nor the server logs | |||
| 820 | // it. | 838 | // it. | ||
| 821 | string token = 6; | 839 | string token = 6; | ||
| 822 | // Source is where the action was found. UNSPECIFIED when error is set. | 840 | // Source is where the action was found. UNSPECIFIED when error is set. | ||