From f454218f0770e0249a37be5617d47148de7b98b2 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 26 May 2026 20:23:34 +0000 Subject: [PATCH 1/4] Fix instance API endpoint: add missing api_keys config The instance API endpoint (/api/1.0/instance/) uses APIAuthentication which references config.api_keys, but this attribute was not defined in the config module, causing an AttributeError crash. JS usage: Not called directly from JavaScript in the project. The endpoint is used by external API consumers with API key auth. Curl test: curl http://127.0.0.1:8000/api/1.0/instance/?format=json&id= Before fix: 500 AttributeError: module 'errortracker.config' has no attribute 'api_keys' After fix: 401 Unauthorized (expected for unauthenticated requests) --- src/errortracker/config.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/errortracker/config.py b/src/errortracker/config.py index e6c89f9b..c9a3fccb 100644 --- a/src/errortracker/config.py +++ b/src/errortracker/config.py @@ -57,6 +57,9 @@ # Allow the Django app to fill bugs allow_bug_filing = True +# API keys for the instance API endpoint +api_keys = [] + # Some variable still used by the launchpad.py module lp_oauth_token = "todofixme" lp_oauth_secret = "todofixme" From 9ce44a51664fc057321f8967ac4163327c3d3846 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 26 May 2026 20:24:07 +0000 Subject: [PATCH 2/4] Fix package-version-new-buckets endpoint: handle non-dict json_request response The is_valid_source_version() function in launchpad.py called .keys() on the return value of json_request(), which returns an empty string "" when the Launchpad API is unreachable. Calling .keys() on a string causes an AttributeError crash. JS usage: Not called directly from JavaScript. Used by external consumers to find new crash buckets between package versions. Curl test: curl 'http://127.0.0.1:8000/api/1.0/package-version-new-buckets/?format=json&package=pkg&previous_version=1.0&new_version=2.0' Before fix: 500 AttributeError: 'str' object has no attribute 'keys' After fix: 404 NotFound (expected when LP API is unreachable) --- src/errortracker/launchpad.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/errortracker/launchpad.py b/src/errortracker/launchpad.py index b2beb2cd..e7c60a57 100644 --- a/src/errortracker/launchpad.py +++ b/src/errortracker/launchpad.py @@ -491,7 +491,9 @@ def is_valid_source_version(src_package, version): urllib.parse.quote_plus(version), ) json_data = json_request(url) - if "total_size" not in list(json_data.keys()): + if not isinstance(json_data, dict): + return False + if "total_size" not in json_data: return False if json_data["total_size"] == 0: return False From 85d41bc0a95bd5564ca0a0beafaf638ed1caa3b3 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 26 May 2026 20:24:50 +0000 Subject: [PATCH 3/4] Fix lp_use_staging comparison: use truthiness instead of string comparison The config.lp_use_staging is set to True (boolean) but was compared with "True" (string), which always evaluates to False. This caused all Launchpad API requests to use production URLs instead of staging URLs when staging was configured. This affects multiple API endpoints that query Launchpad: - binary-package-versions (JS: most_common_problems.js calls /api/1.0/binary-package-versions/) - most-common-problems (JS: most_common_problems.js calls /api/1.0/most-common-problems/) - versions (JS: bucket page uses /api/1.0/versions/) - reports-state (JS: most_common_problems.js POSTs to /api/1.0/reports-state/) - package-version-is-most-recent (JS: most_common_problems.js POSTs) - release-package-version-pockets (JS: most_common_problems.js POSTs) - package-rate-of-crashes - package-version-new-buckets - create-bug-report --- src/errortracker/launchpad.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/errortracker/launchpad.py b/src/errortracker/launchpad.py index e7c60a57..d1262560 100644 --- a/src/errortracker/launchpad.py +++ b/src/errortracker/launchpad.py @@ -19,7 +19,7 @@ ): raise ImportError("You must set lp_oauth_token and lp_oauth_secret in local_config") -if config.lp_use_staging == "True": +if config.lp_use_staging: _create_bug_url = "https://api.qastaging.launchpad.net/devel/bugs" _ubuntu_target = "https://api.qastaging.launchpad.net/devel/ubuntu" _oauth_realm = "https://api.qastaging.launchpad.net" @@ -628,7 +628,7 @@ def create_bug(signature, source="", releases=[], hashed=None, lastseen=""): response.read() try: number = response.headers["Location"].rsplit("/", 1)[1] - if config.lp_use_staging == "True": + if config.lp_use_staging: return (number, "https://qastaging.launchpad.net/bugs/" + number) else: return (number, "https://bugs.launchpad.net/bugs/" + number) From b6fe51ba258d9b508b3c9f95a647c11fea624016 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 26 May 2026 20:43:50 +0000 Subject: [PATCH 4/4] Add API.md documenting all JS API endpoints --- API.md | 191 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 191 insertions(+) create mode 100644 API.md diff --git a/API.md b/API.md new file mode 100644 index 00000000..fd2e5009 --- /dev/null +++ b/API.md @@ -0,0 +1,191 @@ +# API Endpoints + +A report of every REST API endpoint found in the JavaScript source files, listing where each call is made and what parameters it uses. + +--- + +## `/api/1.0/most-common-problems/` + +- **File:** `src/errors/static/js/most_common_problems.js` (line 329) +- **Called by:** `DataSource.IO` source used by the problems data table, loaded via `interval_changed()` +- **Method:** GET +- **Parameters (query string, all optional):** + - `format` – response format (always `json`) + - `release` – Ubuntu release codename + - `rootfs_build_version` – rootfs build version filter + - `channel_name` – system-image channel name + - `device_name` – device name + - `device_image_version` – device image version + - `package` – binary package name + - `snap` – whether the package is a snap (`True`) + - `packageset` – package set name + - `user` – Launchpad username (subscriber filter) + - `period` – time period (e.g. `day`, `week`, `month`) + - `from` – start date for a custom date range + - `to` – end date for a custom date range + - `version` – specific package version (URL-encoded) + - `pkg_arch` – package architecture + +--- + +## `/api/1.0/create-bug-report/` + +- **Files:** + - `src/errors/static/js/most_common_problems.js` (line 48) + - `src/errors/templates/bucket.html` (line 203) +- **Called by:** `createBug()` function +- **Method:** POST +- **Parameters:** + - `format=json` (query string) + - Request body (JSON): `{"signature": ""}` +- **Headers:** `Content-Type: application/json`, `X-CSRFToken: ` + +--- + +## `/api/1.0/package-version-is-most-recent/` + +- **File:** `src/errors/static/js/most_common_problems.js` (line 78) +- **Called by:** `getPackagesState()` +- **Method:** POST (queued via `Y.io.queue`) +- **Parameters:** + - `format=json` (query string) + - Request body (JSON): `{"packages": [...], "release": ""}` (release is optional) +- **Headers:** `Content-Type: application/json` + +--- + +## `/api/1.0/release-package-version-pockets/` + +- **File:** `src/errors/static/js/most_common_problems.js` (line 102) +- **Called by:** `getPackagesPockets()` +- **Method:** POST (queued via `Y.io.queue`) +- **Parameters:** + - `format=json` (query string) + - Request body (JSON): `{"packages_data": [...]}` +- **Headers:** `Content-Type: application/json` + +--- + +## `/api/1.0/reports-state/` + +- **File:** `src/errors/static/js/most_common_problems.js` (line 130) +- **Called by:** `getReportsState()` +- **Method:** POST (queued via `Y.io.queue`) +- **Parameters:** + - `format=json` (query string) + - Request body (JSON): `{"reports": [...], "release": ""}` (release is optional) +- **Headers:** `Content-Type: application/json` + +--- + +## `/api/1.0/binary-package-versions/` + +- **File:** `src/errors/static/js/most_common_problems.js` (line 789) +- **Called by:** `package_changed()` +- **Method:** GET +- **Parameters (query string):** + - `format=json` + - `binary_package` – binary package name (required) + - `release` – Ubuntu release codename (optional) + +--- + +## `/api/1.0/system-image-versions/` + +- **File:** `src/errors/static/js/most_common_problems.js` (line 812) +- **Called by:** `populate_image_versions()` +- **Method:** GET +- **Parameters (query string):** + - `format=json` + - `image_type` – the type of system image (required) + +--- + +## `/api/1.0/average-crashes/` + +- **File:** `src/errors/static/js/mean_time_between_failures.js` (lines 275 and 282) +- **Called by:** `mean_time_between_failures_changed()` and `mean_time_between_failures_graph()` +- **Method:** GET (data fetched via `d3.json()`) +- **Parameters (query string):** + - `limit=0` + - `release` – Ubuntu release codename (optional) + - `package` – binary package name (optional) + - `version` – specific package version (optional) + +--- + +## `/api/1.0/average-instances/` + +- **File:** `src/errors/templates/bucket.html` (line 67) +- **Called by:** inline script on the bucket detail page, passed to `mean_time_between_failures_request()` +- **Method:** GET (data fetched via `d3.json()`) +- **Parameters (query string):** + - `limit=0` + - `id` – bucket identifier (required) + +--- + +## `/api/1.0/versions` + +- **File:** `src/errors/templates/bucket.html` (line 127) +- **Called by:** `DataSource.IO` source for the versions table on the bucket page +- **Method:** GET +- **Parameters (query string, appended by datasource load):** + - `limit=0` + - `id` – bucket identifier (required) + +--- + +## `/api/1.0/instances` + +- **File:** `src/errors/templates/bucket.html` (line 216) +- **Called by:** `DataSource.IO` source for the examples/instances table on the bucket page +- **Method:** GET +- **Parameters (query string, appended by datasource load):** + - `limit` – number of results (e.g. `100`) + - `id` – bucket identifier (required) + - `start` – incident ID for pagination (optional, used for infinite scroll) + +--- + +## `/api/1.0/reports-for-system` + +- **File:** `src/errors/templates/user.html` (line 23) +- **Called by:** `DataSource.Get` source for the user's crash reports table +- **Method:** GET +- **Parameters (query string, appended by datasource load):** + - `limit` – number of results (e.g. `50`) + - `system` – system identifier (required) + +--- + +## `/api/1.0/retracers-average-processing-time/` + +- **File:** `src/errors/static/js/retracers.js` (line 67) +- **Called by:** `retracers_graph()` +- **Method:** GET (via `Y.io`) +- **Parameters (query string):** + - `limit=32767` + - `format=json` + +--- + +## `/api/1.0/retracers-results/` + +- **File:** `src/errors/static/js/retracers.js` (line 95) +- **Called by:** `retracers_results_graph()` +- **Method:** GET (via `Y.io`) +- **Parameters (query string):** + - `limit=32767` + - `format=json` + +--- + +## `/api/1.0/instances-count/` + +- **File:** `src/errors/static/js/retracers.js` (line 122) +- **Called by:** `instances_graph()` +- **Method:** GET (via `Y.io`) +- **Parameters (query string):** + - `limit=365` + - `format=json`