protobuf upgrade
7e63f64 · gmorell · 2026-05-22 16:10
Files changed
modified
lib/git_gud_web/controllers/runner_controller.ex
+22
−11
@@ -163,14 +163,23 @@ defmodule GitGudWeb.RunnerController do
| 163 | 163 | %TaskMsg{ |
| 164 | 164 | id: job.id, |
| 165 | 165 | workflow_payload: GitGud.Workflows.RunnerPayload.encode(job), |
| 166 | − context: build_context(job, run, repo, token), | |
| 166 | + context: build_context_struct(job, run, repo, token), | |
| 167 | 167 | secrets: secrets, |
| 168 | − needs: job.needs || [], | |
| 168 | + # Modern proto changed `needs` from `repeated string` to | |
| 169 | + # `map<string, TaskNeed>`. We don't (yet) carry forward upstream | |
| 170 | + # job results, so emit an empty map. | |
| 171 | + needs: %{}, | |
| 169 | 172 | vars: vars |
| 170 | 173 | } |
| 171 | 174 | end |
| 172 | 175 | |
| 173 | − defp build_context(job, run, repo, token) do | |
| 176 | + # Forgejo's runner proto switched `Task.context` from | |
| 177 | + # `map<string,string>` to `google.protobuf.Struct` so values can carry | |
| 178 | + # nested objects, numbers, and bools. Our context is still all | |
| 179 | + # strings, but the wire format requires Struct{ fields: %{ key => | |
| 180 | + # Value{ kind: {:string_value, v} } } } — `kind` is a oneof, so we | |
| 181 | + # pass the tuple form `{:string_value, v}`. | |
| 182 | + defp build_context_struct(job, run, repo, token) do | |
| 174 | 183 | base = GitGudWeb.Endpoint.url() |
| 175 | 184 | |
| 176 | 185 | %{ |
@@ -191,6 +200,16 @@ defmodule GitGudWeb.RunnerController do
| 191 | 200 | "ACTIONS_RUNTIME_TOKEN" => token, |
| 192 | 201 | "ACTIONS_CACHE_URL" => base <> "/api/actions/_apis/artifactcache/" |
| 193 | 202 | } |
| 203 | + |> wrap_as_struct() | |
| 204 | + end | |
| 205 | + | |
| 206 | + defp wrap_as_struct(map) when is_map(map) do | |
| 207 | + %Google.Protobuf.Struct{ | |
| 208 | + fields: | |
| 209 | + Map.new(map, fn {k, v} -> | |
| 210 | + {k, %Google.Protobuf.Value{kind: {:string_value, v}}} | |
| 211 | + end) | |
| 212 | + } | |
| 194 | 213 | end |
| 195 | 214 | |
| 196 | 215 | # ── update_task ────────────────────────────────────────────────────── |
@@ -326,15 +345,7 @@ defmodule GitGudWeb.RunnerController do
| 326 | 345 | {:protobuf, echoed_ct} -> |
| 327 | 346 | body = msg.__struct__.encode(msg) |> IO.iodata_to_binary() |
| 328 | 347 | |
| 329 | − require Logger | |
| 330 | − | |
| 331 | − Logger.info( | |
| 332 | − "runner-respond struct=#{inspect(msg.__struct__)} body_bytes=#{byte_size(body)} " <> | |
| 333 | − "task_present=#{inspect(match?(%{task: t} when not is_nil(t), msg))}" | |
| 334 | − ) | |
| 335 | − | |
| 336 | 348 | conn |
| 337 | − |> put_resp_header("x-debug-body-size", Integer.to_string(byte_size(body))) | |
| 338 | 349 | |> put_resp_content_type(echoed_ct, nil) |
| 339 | 350 | |> send_resp(200, body) |
| 340 | 351 |
modified
lib/git_gud_web/protos/runner/v1/messages.pb.ex
+31
−5
@@ -102,11 +102,11 @@ defmodule Runner.V1.DeclareResponse do
| 102 | 102 | field :runner, 1, type: Runner.V1.Runner |
| 103 | 103 | end |
| 104 | 104 | |
| 105 | −defmodule Runner.V1.Task.ContextEntry do | |
| 105 | +defmodule Runner.V1.TaskNeed.OutputsEntry do | |
| 106 | 106 | @moduledoc false |
| 107 | 107 | |
| 108 | 108 | use Protobuf, |
| 109 | − full_name: "runner.v1.Task.ContextEntry", | |
| 109 | + full_name: "runner.v1.TaskNeed.OutputsEntry", | |
| 110 | 110 | map: true, |
| 111 | 111 | protoc_gen_elixir_version: "0.16.0", |
| 112 | 112 | syntax: :proto3 |
@@ -115,6 +115,18 @@ defmodule Runner.V1.Task.ContextEntry do
| 115 | 115 | field :value, 2, type: :string |
| 116 | 116 | end |
| 117 | 117 | |
| 118 | +defmodule Runner.V1.TaskNeed do | |
| 119 | + @moduledoc false | |
| 120 | + | |
| 121 | + use Protobuf, | |
| 122 | + full_name: "runner.v1.TaskNeed", | |
| 123 | + protoc_gen_elixir_version: "0.16.0", | |
| 124 | + syntax: :proto3 | |
| 125 | + | |
| 126 | + field :result, 1, type: Runner.V1.Result, enum: true | |
| 127 | + field :outputs, 2, repeated: true, type: Runner.V1.TaskNeed.OutputsEntry, map: true | |
| 128 | +end | |
| 129 | + | |
| 118 | 130 | defmodule Runner.V1.Task.SecretsEntry do |
| 119 | 131 | @moduledoc false |
| 120 | 132 |
@@ -128,6 +140,19 @@ defmodule Runner.V1.Task.SecretsEntry do
| 128 | 140 | field :value, 2, type: :string |
| 129 | 141 | end |
| 130 | 142 | |
| 143 | +defmodule Runner.V1.Task.NeedsEntry do | |
| 144 | + @moduledoc false | |
| 145 | + | |
| 146 | + use Protobuf, | |
| 147 | + full_name: "runner.v1.Task.NeedsEntry", | |
| 148 | + map: true, | |
| 149 | + protoc_gen_elixir_version: "0.16.0", | |
| 150 | + syntax: :proto3 | |
| 151 | + | |
| 152 | + field :key, 1, type: :string | |
| 153 | + field :value, 2, type: Runner.V1.TaskNeed | |
| 154 | +end | |
| 155 | + | |
| 131 | 156 | defmodule Runner.V1.Task.VarsEntry do |
| 132 | 157 | @moduledoc false |
| 133 | 158 |
@@ -148,10 +173,11 @@ defmodule Runner.V1.Task do
| 148 | 173 | |
| 149 | 174 | field :id, 1, type: :int64 |
| 150 | 175 | field :workflow_payload, 2, type: :bytes, json_name: "workflowPayload" |
| 151 | − field :context, 3, repeated: true, type: Runner.V1.Task.ContextEntry, map: true | |
| 176 | + field :context, 3, type: Google.Protobuf.Struct | |
| 152 | 177 | field :secrets, 4, repeated: true, type: Runner.V1.Task.SecretsEntry, map: true |
| 153 | − field :needs, 5, repeated: true, type: :string | |
| 154 | − field :vars, 6, repeated: true, type: Runner.V1.Task.VarsEntry, map: true | |
| 178 | + field :machine, 5, type: :string | |
| 179 | + field :needs, 6, repeated: true, type: Runner.V1.Task.NeedsEntry, map: true | |
| 180 | + field :vars, 7, repeated: true, type: Runner.V1.Task.VarsEntry, map: true | |
| 155 | 181 | end |
| 156 | 182 | |
| 157 | 183 | defmodule Runner.V1.FetchTaskRequest do |
Parents: 99d66f7