Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
66 changes: 66 additions & 0 deletions doc/config-reference.md
Original file line number Diff line number Diff line change
Expand Up @@ -228,3 +228,69 @@ kernel. It is used in `kselftest`-related jobs.
The `dtbs_check` parameter is used to enable or disable the dtbs_check build.
The dtbs_check build is additional kind of build that will verify the
device tree blobs.

## Build Configs configuration

The `build_configs` section defines which kernel trees and branches to monitor
for new commits. Each build config specifies a tree/branch combination that the
trigger service will poll for changes.

Build configs are typically defined in separate files under `config/trees/`
directory, one file per tree (e.g., `config/trees/chromiumos.yaml`).

### Mandatory parameters

- **tree**: string - Name of the tree (must match an entry in `trees` section)
- **branch**: string - Branch name to monitor

### Optional parameters

- **architectures**: list of strings - Filter to limit which architectures to build
- **frequency**: string - Limit how often checkout nodes are created

### Parameter frequency (optional)

- **Value**: [Nd][Nh][Nm]
- **Default**: none (no limit)

The frequency parameter in `build_configs` limits how often the trigger service
creates new checkout nodes for a tree/branch combination. This is useful for
trees where all jobs have frequency limits - without this setting, empty
checkout nodes would be created that show as zeros in the dashboard.

When set, the trigger service checks if a checkout node for the same tree/branch
was created within the specified time period. If so, it skips creating a new
checkout node even if a new commit is detected.

This is different from the job-level `frequency` parameter which controls how
often individual jobs run. The build_config frequency controls checkout node
creation at the source, preventing empty checkouts entirely.

**Recommendation**: Set this to match the minimum frequency of all jobs
scheduled for this tree/branch. For example, if all jobs for chromiumos have
`frequency: 1d` or higher, set `frequency: 1d` in the build_config.

Example:
```yaml
build_configs:
chromiumos:
tree: chromiumos
branch: 'master'
frequency: 1d
architectures:
- x86_64
- arm64
- arm

chromiumos-6.6:
tree: chromiumos
branch: 'chromeos-6.6'
frequency: 1d
```

In this example, new checkout nodes for chromiumos branches will only be created
once per day, even if multiple commits are pushed. This prevents empty checkout
nodes when all jobs have daily frequency limits.

**Note**: The `--force` flag on the trigger service overrides the frequency
check, allowing checkout creation regardless of the frequency setting.
64 changes: 64 additions & 0 deletions src/trigger.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@

import copy
import datetime
import re
import sys
import time

Expand All @@ -21,6 +22,28 @@
from base import Service, validate_url


def translate_freq(freq):
"""
Translate the frequency string to seconds.
Format is: [Nd][Nh][Nm], where each field is optional.
Examples: "1d" = 1 day, "12h" = 12 hours, "1d12h" = 1.5 days
"""
if not freq:
return 0
freq_sec = 0
freq_re = re.compile(r'(?:(\d+)d)?(?:(\d+)h)?(?:(\d+)m)?')
freq_match = freq_re.match(freq)
if freq_match:
days, hours, minutes = freq_match.groups()
if days:
freq_sec += int(days) * 24 * 60 * 60
if hours:
freq_sec += int(hours) * 60 * 60
if minutes:
freq_sec += int(minutes) * 60
return freq_sec


class Trigger(Service):

def __init__(self, configs, args):
Expand All @@ -32,6 +55,43 @@ def __init__(self, configs, args):
def _log_revision(self, message, build_config, head_commit):
self.log.info(f"{message:32s} {build_config.name:32s} {head_commit}")

def _check_frequency(self, build_config):
"""Check if a checkout can be created based on frequency limit.

Returns True if a new checkout can be created, False if we should skip
due to frequency limit (a recent checkout already exists).
"""
frequency = build_config.frequency
if not frequency:
return True

freq_sec = translate_freq(frequency)
if not freq_sec or freq_sec < 60:
self.log.warning(f"Invalid frequency '{frequency}' for {build_config.name}")
return True

# Calculate the timestamp threshold
now = datetime.datetime.now(datetime.UTC)
tstamp = now - datetime.timedelta(seconds=freq_sec)

# Search for checkouts with this tree/branch created after threshold
search_terms = {
"kind": "checkout",
"data.kernel_revision.tree": build_config.tree.name,
"data.kernel_revision.branch": build_config.branch,
"owner": self._current_user['username'],
"submitter": "service:pipeline",
"created__gte": tstamp.isoformat(),
}
node_count = self._api.node.count(search_terms)

if node_count > 0:
self.log.info(f"Skipping {build_config.name}: checkout created within "
f"frequency limit ({frequency})")
return False

return True

def _run_trigger(self, build_config, force, timeout, trees):
if trees and len(trees) > 1:
tree_condition = "not" if trees.startswith("!") else "only"
Expand All @@ -41,6 +101,10 @@ def _run_trigger(self, build_config, force, timeout, trees):
(not tree_in_list and tree_condition == "only"):
return

# Check frequency limit before doing any git operations
if not force and not self._check_frequency(build_config):
return

try:
current_config = copy.copy(build_config)
if validate_url(current_config.branch):
Expand Down