-
Notifications
You must be signed in to change notification settings - Fork 11
feat(submit): add KCIDB build submission subcommand and payload helpers #266
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
nuclearcat
wants to merge
1
commit into
kernelci:main
Choose a base branch
from
nuclearcat:submit-cmd
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
+816
−14
Open
Changes from all commits
Commits
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,210 @@ | ||
| #!/usr/bin/env python3 | ||
| # -*- coding: utf-8 -*- | ||
|
|
||
| import hashlib | ||
| import json | ||
| import os | ||
| import urllib.parse | ||
|
|
||
| import click | ||
|
|
||
| from kcidev.libs.common import kci_err, kci_msg, kci_warning, kcidev_session | ||
|
|
||
| KCIDB_SCHEMA_MAJOR = 5 | ||
| KCIDB_SCHEMA_MINOR = 3 | ||
|
|
||
|
|
||
| # --------------------- | ||
| # ID generation | ||
| # --------------------- | ||
|
|
||
|
|
||
| def _sha256_hex(data): | ||
| return hashlib.sha256(data.encode("utf-8")).hexdigest() | ||
|
|
||
|
|
||
| def generate_checkout_id(origin, repo_url, branch, commit, patchset_hash=""): | ||
| """ | ||
| Deterministic checkout ID from source identity. | ||
| Format: origin:ck-<sha256(repo_url|branch|commit|patchset_hash)> | ||
| """ | ||
| seed = f"{repo_url}|{branch}|{commit}|{patchset_hash}" | ||
| return f"{origin}:ck-{_sha256_hex(seed)}" | ||
|
|
||
|
|
||
| def generate_build_id(origin, checkout_id, arch, config_name, compiler, start_time): | ||
| """ | ||
| Deterministic build ID from build parameters. | ||
| Format: origin:b-<sha256(checkout_id|arch|config_name|compiler|start_time)> | ||
| """ | ||
| seed = f"{checkout_id}|{arch}|{config_name}|{compiler}|{start_time}" | ||
| return f"{origin}:b-{_sha256_hex(seed)}" | ||
|
|
||
|
|
||
| # --------------------- | ||
| # Payload building | ||
| # --------------------- | ||
|
|
||
|
|
||
| def build_checkout_payload(origin, checkout_id, **kwargs): | ||
| """Build a checkout object for the KCIDB JSON payload.""" | ||
| checkout = { | ||
| "id": checkout_id, | ||
| "origin": origin, | ||
| } | ||
| for key in [ | ||
| "tree_name", | ||
| "git_repository_url", | ||
| "git_repository_branch", | ||
| "git_commit_hash", | ||
| "patchset_hash", | ||
| "start_time", | ||
| "valid", | ||
| ]: | ||
| if kwargs.get(key) is not None: | ||
| checkout[key] = kwargs[key] | ||
| return checkout | ||
|
|
||
|
|
||
| def build_build_payload(origin, build_id, checkout_id, **kwargs): | ||
| """Build a build object for the KCIDB JSON payload.""" | ||
| build = { | ||
| "id": build_id, | ||
| "origin": origin, | ||
| "checkout_id": checkout_id, | ||
| } | ||
| for key in [ | ||
| "start_time", | ||
| "duration", | ||
| "architecture", | ||
| "compiler", | ||
| "config_name", | ||
| "config_url", | ||
| "log_url", | ||
| "comment", | ||
| "command", | ||
| "status", | ||
| ]: | ||
| if kwargs.get(key) is not None: | ||
| build[key] = kwargs[key] | ||
| return build | ||
|
|
||
|
|
||
| def build_submission_payload(checkouts, builds): | ||
| """Build the complete KCIDB v5.3 submission JSON.""" | ||
| payload = { | ||
| "version": {"major": KCIDB_SCHEMA_MAJOR, "minor": KCIDB_SCHEMA_MINOR}, | ||
| } | ||
| if checkouts: | ||
| payload["checkouts"] = checkouts | ||
| if builds: | ||
| payload["builds"] = builds | ||
| return payload | ||
|
|
||
|
|
||
| # --------------------- | ||
| # Config resolution | ||
| # --------------------- | ||
|
|
||
|
|
||
| def _parse_kcidb_rest_env(env_value): | ||
| """ | ||
| Parse KCIDB_REST env var. | ||
| Format: https://token@host[:port][/path] | ||
| Returns (url, token) or (None, None) on failure. | ||
| """ | ||
| parsed = urllib.parse.urlparse(env_value) | ||
| token = parsed.username | ||
| if not token: | ||
| return None, None | ||
|
|
||
| # Rebuild URL without credentials | ||
| host = parsed.hostname | ||
| if parsed.port: | ||
| host = f"{host}:{parsed.port}" | ||
| path = parsed.path if parsed.path else "/" | ||
| if not path.endswith("/submit"): | ||
| path = path.rstrip("/") + "/submit" | ||
|
|
||
| clean_url = urllib.parse.urlunparse( | ||
| (parsed.scheme, host, path, parsed.params, parsed.query, parsed.fragment) | ||
| ) | ||
| return clean_url, token | ||
|
|
||
|
|
||
| def resolve_kcidb_config(cfg, instance, cli_rest_url, cli_token): | ||
| """ | ||
| Resolve KCIDB REST URL and token. Priority: | ||
| 1. CLI flags (--kcidb-rest-url, --kcidb-token) | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. raise a error if user specify only one of them
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Done, extended logic, so if we provide anything over cli, second argument should be present |
||
| 2. KCIDB_REST environment variable | ||
| 3. Instance config (kcidb_rest_url, kcidb_token in TOML) | ||
|
|
||
| Returns (rest_url, token) tuple. | ||
| Raises click.Abort if no valid credentials found. | ||
| """ | ||
| # 1. CLI flags | ||
| if cli_rest_url or cli_token: | ||
| if not cli_rest_url or not cli_token: | ||
| kci_err("Both --kcidb-rest-url and --kcidb-token must be provided together") | ||
| raise click.Abort() | ||
| return cli_rest_url, cli_token | ||
|
|
||
| # 2. Environment variable | ||
| kcidb_rest_env = os.environ.get("KCIDB_REST") | ||
| if kcidb_rest_env: | ||
| url, token = _parse_kcidb_rest_env(kcidb_rest_env) | ||
| if url and token: | ||
| return url, token | ||
| kci_err("KCIDB_REST env var set but could not parse token from it") | ||
|
|
||
| # 3. Instance config | ||
| if cfg and instance and instance in cfg: | ||
| inst_cfg = cfg[instance] | ||
| rest_url = inst_cfg.get("kcidb_rest_url") | ||
| token = inst_cfg.get("kcidb_token") | ||
| if rest_url and token: | ||
| return rest_url, token | ||
|
|
||
| kci_err( | ||
| "No KCIDB credentials found. Provide --kcidb-rest-url and --kcidb-token, " | ||
| "set KCIDB_REST env var, or configure kcidb_rest_url/kcidb_token in config file" | ||
| ) | ||
| raise click.Abort() | ||
|
|
||
|
|
||
| # --------------------- | ||
| # REST submission | ||
| # --------------------- | ||
|
|
||
|
|
||
| def submit_to_kcidb(rest_url, token, payload, timeout=60): | ||
| """ | ||
| POST the JSON payload to the KCIDB REST API. | ||
|
|
||
| Returns the response text on success. | ||
| Raises click.Abort on failure. | ||
| """ | ||
| headers = { | ||
| "Content-Type": "application/json", | ||
| "Authorization": f"Bearer {token}", | ||
| } | ||
| try: | ||
| response = kcidev_session.post( | ||
| rest_url, json=payload, headers=headers, timeout=timeout | ||
| ) | ||
| except Exception as e: | ||
| kci_err(f"KCIDB API connection error: {e}") | ||
| raise click.Abort() | ||
|
|
||
| if response.status_code < 300: | ||
| try: | ||
| return response.json() | ||
| except Exception: | ||
| return response.text | ||
| else: | ||
| kci_err(f"KCIDB submission failed: HTTP {response.status_code}") | ||
| try: | ||
| kci_err(response.json()) | ||
| except Exception: | ||
| kci_err(response.text) | ||
| raise click.Abort() | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
document the following added parameters in the client help or raise error when this parameters are missing
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
When parameters are missing we provide client help
No KCIDB credentials found. Provide --kcidb-rest-url and --kcidb-token, set KCIDB_REST env var, or configure kcidb_rest_url/kcidb_token in config file. Also i added in documentation fileconfig_file.md.Just curiosity, i noticed in
config_file.mdthere is 3 spaces at end of each line, is it intentional?