Skip to content

Build the configuration

Answer what your deployment is, and this writes the three things that run it: the config.yaml a normal run reads, the command that runs it, and the step a workflow gives the composite Action. All three come from one set of answers, and none of them asks for a credential.

The controls are not a copy of the settings. cmd/gen_config exports internal/config’s own types into a file the page reads, down to the default each key resolves to, which it measures by validating a probe rather than by restating a number. make check-config-options fails when that file is no longer what the code produces, in the analysis suite and in CI, so the form cannot offer a setting the binary does not have and cannot miss one it does.

The other direction is checked too, and its limit is worth saying out loud. The configurations this form writes for the answer sets in internal/config/testdata/config-cases.json go through the real parser in internal/config’s own tests, including the shapes that have caught people out: a cadence per family under every.families, an include_private left off, a sink whose credentials are ${VAR} references, a card-only run with no destination at all, and answers the parser is expected to refuse. Those cases are generated by the module this page runs, so they cannot be a copy of it, and every branch of that module that can change what it writes has one. What the corpus does not prove is behaviour no answer set produces, which is why the file that owns it lists what it cannot cover and why.

What the form allows and the parser refuses

Section titled “What the form allows and the parser refuses”

A form is a form: a destination is a checkbox and the keys it cannot resolve without are not, so a few clicks are enough to write a file that dies at start-up. The page warns about the ones its own generated list of settings can see, above the outputs, and names the rest here. Refusing the rest in the form would mean keeping a second copy of a parser rule on this page, which is the drift the whole arrangement exists to avoid.

  • A destination switched on with a required key left empty is refused by name, with an example: sinks.loki: url is required, for example http://loki:3100. The form warns about this one.
  • A credential field answered with the credential instead of the name of an environment variable is left out of the file. The form warns about this one.
  • A file with nothing in it is refused: the file is empty.
  • No account at all is refused: targets: set at least one of user, orgs or repos.
  • heartbeat: 0 is refused: it must be positive, and leaving the key out is how the loop’s tick is derived instead.
  • A cadence that is not a duration is refused where it is used: every.families.repo: time: invalid duration "soon".
  • sinks.elasticsearch.api_key filled in beside sinks.elasticsearch.username is refused: sinks.elasticsearch: set either api_key or username and password, not both.
  • Writing - as sinks.sql.path while sinks.stdout is on is accepted and gives two writers one stream; pick one of them.
The account and its API5

Read about these settings

What to collect7

Read about these settings

Where the points go50

Read about these settings

influxdb
prometheus
otlp
loki
file
telegraf
graphite
sql
elasticsearch
How often3

Read about these settings

every.groups
every.families
The run's own log5

Read about these settings

The run4

Read about these settings

groups

config.yaml

Save this beside the binary, or at the path you give to -config, and run it with the command below.

github:
  token: ${GITHUB_TOKEN}
targets:
  user: octocat
sinks:
  stdout: true

The command that runs it

ghchronicle -config config.yaml -once

Workflow step

Paste this into the steps of a workflow job. The token is a repository secret, never a value in the file.

- uses: jmrplens/ghchronicle@v1
  with:
    token: ${{ secrets.GHCHRONICLE_TOKEN }}
    config: .github/ghchronicle.yaml

A credential field takes the NAME of an environment variable, and the file gets ${NAME}, which the binary expands at start-up. An answer that is not a variable name is left out of the file rather than written into it. The headers field is the exception: it is free text, and whatever is typed there is written as it stands.

There is not one command, which is why the form writes it. A configuration that names a destination is run with -once. A configuration that names none is refused by -once, with the parser asking for a sink you deliberately did not want, so it is run with -card-only and a path for the card instead. The command above changes with the answers, and so does the step.

The step goes in the steps: of a workflow job. Answers no input can carry make the step read the file, and the file has to be committed at the path the step names; answers the four inputs can carry are written into the step itself, and then there is no file at all. A step with no file that names no destination is a card run, mode: card with a card: path, because that is the one thing the Action turns into -card-only.

The two outputs default the opposite way on one setting, and the step is written so it says which one you are getting. include-private is off unless you ask for it, because a card that counts private repositories names them in a public README; targets.include_private is on unless you say otherwise, because the token already reaches them. So a file-less step always writes the input out rather than leaving it to a default that means the opposite of the file beside it. See GitHub Actions for the workflow around it, and the token for what the secret needs to be able to do.

  • The file: what each block is for, and what happens when a value is wrong.
  • Targets: which repositories.
  • Cadences: every family, its group and its built-in interval.
  • Choosing a store: one page per destination.