{% extends "base.html" %} {% import "admin_nav.html" as an %} {# One level's update settings (oxygenhub#322); `top` is the site, which inherits from nothing. #} {% macro policy_fields(p, top) %} {% endmacro %} {% block title %}Runner updates · Administration{% endblock %} {% block content %}

Runners Administration

{% call an::nav(crate::web::admin::AdminSection::RunnerUpdates) %}
{% if let Some(n) = notice %}

{{ n }}

{% endif %} {% if let Some(e) = error %}

{{ e }}

{% endif %}

Runners update themselves

A runner asks the hub which build it should run, fetches it, checks it as a release, finishes what it holds and swaps itself in; a build that does not reach the hub goes back to the one before. Off unless chosen. The site, an owner, a test group and a runner each may set any of the settings below, and the nearest setting wins: a runner's own, then its test groups', then its owner's, then the site's. A runner's flow.toml can still refuse every update ([runner.update] allow = false).

A rollout: turn updates on for a test group (two chosen runners, or 10% of them), watch it, then widen it to 50%, then turn updates on for everyone. A percentage is taken by a stable hash of each runner's id, so it is the same machines every time, and 10% sits inside 50%.

Where builds come from

Each release offers one file per machine, flow-linux-x86_64, flow-linux-aarch64, flow-linux-riscv64, flow-windows-x86_64.exe. stable is its newest release, canary its newest including pre-releases; a version (0.3.4) pins it, going back if need be.

The site

What every runner does unless a nearer level says otherwise: {{ site.summary() }}.

{% call policy_fields(site, true) %}

Owners

For the runners an account or organisation registered for its own repositories.

{% if owners.is_empty() %}

No owner sets anything; their runners follow the site.

{% endif %} {% for o in owners %}
{{ o.key }}{% call policy_fields(o, false) %}
{% endfor %}
{% call policy_fields(site, false) %}

Test groups

A named set of runners: those you choose, or a percentage of the site's runners (or one owner's). Give a group its own settings to try a build on it before the rest.

{% if groups.is_empty() %}

No test groups yet.

{% endif %} {% for gv in groups %}{% let g = gv.g %}

{{ g.name }} {{ gv.reach }} · {% if let Some(p) = g.percent %}{{ p }}%{% else %}chosen{% endif %} · {{ gv.members.len()|plural("runner", "runners") }} now

{% if gv.members.is_empty() %}No runners in it.{% else %}{% for m in gv.members %}{{ m }} {% endfor %}{% endif %}

{% call policy_fields(gv.policy, false) %}
Who is in it
{% for rv in runners %}{% if g.owner.is_empty() || g.owner == rv.r.scope_owner %}{% endif %}{% endfor %}
{% endfor %}

New test group

{% for rv in runners %}{% endfor %}

Runners

{% if runners.is_empty() %}

No runners yet.

{% else %}
{% for rv in runners %}{% let r = rv.r %} {% endfor %}
RunnerRunsGroupsIts policyNowLast saidIts own settings
{{ r.name }}{% if !r.scope_owner.is_empty() %}
{{ r.scope_owner }}'s{% endif %}
{% if r.version.is_empty() %}unknown{% else %}flow {{ r.version }}{% endif %} {% for g in rv.groups %}{{ g }} {% endfor %} {{ rv.effective_words() }} {{ rv.offer }} {% if r.update_note.is_empty() %}nothing yet{% else %}{{ r.update_note }}{% if let Some(t) = r.update_ms %} {% endif %}{% endif %}
{% call policy_fields(rv.policy, false) %}
{% endif %}
{% endblock %}