Skip to content

Commit 4b91081

Browse files
authored
Merge pull request #9 from alliedmodders/psy/amxx-asset-match
Add asset_match_filter option
2 parents 458b0af + 7bf8021 commit 4b91081

File tree

4 files changed

+65
-15
lines changed

4 files changed

+65
-15
lines changed

README.md

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -72,8 +72,29 @@ log:
7272
level: "INFO" # env: LOG__LEVEL
7373
```
7474
75-
`storage` is required. `database` and `repo` are optional — omitting them disables
76-
DB upsert and reconciliation.
75+
`storage` is optional. Omitting it disables PDB symbol store processing and build-drop
76+
downloads — useful for products that only need commit log tracking.
77+
`database` and `repo` are optional — omitting them disables DB upsert and reconciliation.
78+
79+
### Repo Settings
80+
81+
The `repo` section supports additional options:
82+
83+
```yaml
84+
repo:
85+
owner: "alliedmodders"
86+
name: "sourcemod"
87+
product_name: "sourcemod"
88+
workflow_path: ".github/workflows/build-release.yml" # Workflow to monitor
89+
version_branches: # Maps version prefix → branch name
90+
"1.12": "1.12-dev"
91+
"1.13": "master"
92+
reconcile_max_age_days: 90 # How far back reconciliation looks (null = no limit)
93+
asset_match_filter: null # If set, only release assets containing this string
94+
# are matched for the windows/linux URL columns.
95+
# Useful for multi-package releases, e.g. set to "base"
96+
# to match only the base package archive.
97+
```
7798

7899
## Running the Server
79100

app.py

Lines changed: 20 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,11 @@ class RepoSettings(BaseModel):
7878
# Prevents stale broken releases from blocking pagination indefinitely.
7979
# Set to null to disable.
8080
reconcile_max_age_days: int | None = 90
81+
# When set, only release assets whose name contains this string are
82+
# matched for the windows_url / linux_url columns. Useful for
83+
# multi-package releases (e.g. set to "base" to match only the base
84+
# package archive).
85+
asset_match_filter: str | None = None
8186

8287
@property
8388
def full_name(self) -> str:
@@ -106,14 +111,14 @@ def settings_customise_sources(
106111
return (init_settings, env_settings, YamlConfigSettingsSource(settings_cls))
107112

108113
api: ApiSettings = Field(default_factory=ApiSettings)
109-
storage: StorageSettings
114+
storage: StorageSettings | None = None
110115
github: GithubSettings = Field(default_factory=GithubSettings)
111116
database: DatabaseSettings | None = None
112117
repo: RepoSettings | None = None
113118
log: LogSettings = Field(default_factory=LogSettings)
114119

115120

116-
config = AppConfig() # ty: ignore[missing-argument]
121+
config = AppConfig()
117122

118123
logging.basicConfig(
119124
level=logging.INFO, format="%(asctime)s - %(name)s - %(levelname)s - %(message)s"
@@ -141,12 +146,17 @@ def _run_reconcile():
141146
_releases_client,
142147
config.database,
143148
config.repo.version_branches,
144-
drop_base_path=config.storage.build_drop_base_path,
145-
process_symbols_fn=_process_pdb_artifact_for_sha,
149+
drop_base_path=config.storage.build_drop_base_path
150+
if config.storage
151+
else None,
152+
process_symbols_fn=_process_pdb_artifact_for_sha
153+
if config.storage
154+
else None,
146155
download_fn=lambda url, path: download_file(url, path),
147156
product_name=config.repo.product_name,
148157
max_age_days=config.repo.reconcile_max_age_days,
149158
commit_log_table=config.database.commit_log_table,
159+
asset_match_filter=config.repo.asset_match_filter,
150160
)
151161
except Exception:
152162
logger.exception("Scheduled reconciliation failed")
@@ -236,6 +246,7 @@ def _process_symbols_only(
236246
auth_headers: dict,
237247
) -> None:
238248
"""Download PDB zip, extract, and commit to symstore. Serialized via _storage_lock."""
249+
assert config.storage is not None
239250
base_symbols_path = config.storage.symbol_store_base_path
240251

241252
product_symbols_path = Path(base_symbols_path).resolve()
@@ -320,7 +331,7 @@ def _process_pdb_artifact_for_sha(sha: str, product_name: str) -> None:
320331
download the PDB artifact, and process into symstore.
321332
Artifacts expire after ~90 days; logs a warning and returns if unavailable.
322333
"""
323-
if not _releases_client or not config.repo:
334+
if not _releases_client or not config.repo or not config.storage:
324335
return
325336

326337
run = _releases_client.find_workflow_run_for_commit(sha, config.repo.workflow_path)
@@ -378,13 +389,13 @@ def process_artifacts(
378389
auth_headers = {"Authorization": f"Bearer {token}"} if token else {}
379390

380391
# Download and process symbol files
381-
if symbols_url:
392+
if symbols_url and config.storage:
382393
_process_symbols_only(symbols_url, safe_version, product_name, auth_headers)
383394

384395
# Fetch the GitHub Release once; used for both DB upsert and build drop.
385396
release = None
386397
needs_release = (config.database and config.repo) or (
387-
config.storage.build_drop_base_path and config.repo
398+
config.storage and config.storage.build_drop_base_path and config.repo
388399
)
389400
if needs_release and _releases_client:
390401
try:
@@ -405,14 +416,15 @@ def process_artifacts(
405416
config.database,
406417
config.repo.version_branches,
407418
commit_log_table=config.database.commit_log_table,
419+
asset_match_filter=config.repo.asset_match_filter,
408420
)
409421
except Exception:
410422
logger.exception(
411423
"DB upsert failed for build %s (non-fatal)", build_version
412424
)
413425

414426
# Download build archives to the local drop directory as a backup mirror.
415-
if release and config.storage.build_drop_base_path:
427+
if release and config.storage and config.storage.build_drop_base_path:
416428
try:
417429
version_prefix = ".".join(build_version.split(".")[:2])
418430
drop_dir = Path(config.storage.build_drop_base_path) / version_prefix

reconciler.py

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ def upsert_from_release(
1818
db_config,
1919
version_branches: dict[str, str],
2020
commit_log_table: str = "sm_commit_log",
21+
asset_match_filter: str | None = None,
2122
) -> bool:
2223
"""
2324
Resolve and upsert a single GitHub release to the DB.
@@ -48,7 +49,9 @@ def upsert_from_release(
4849
return False
4950

5051
timestamp = client.release_timestamp(release)
51-
windows_url, linux_url = client.parse_release_assets(release)
52+
windows_url, linux_url = client.parse_release_assets(
53+
release, asset_filter=asset_match_filter
54+
)
5255

5356
with get_connection(db_config) as conn:
5457
upsert_build(
@@ -121,6 +124,7 @@ def reconcile(
121124
product_name: str | None = None,
122125
max_age_days: int | None = 90,
123126
commit_log_table: str = "sm_commit_log",
127+
asset_match_filter: str | None = None,
124128
) -> int:
125129
"""
126130
Fetch GitHub releases and reconcile DB records, build archives, and symbols.
@@ -193,7 +197,9 @@ def reconcile(
193197
all_done = False
194198

195199
if needs_url_update:
196-
windows_url, linux_url = client.parse_release_assets(release)
200+
windows_url, linux_url = client.parse_release_assets(
201+
release, asset_filter=asset_match_filter
202+
)
197203
if windows_url or linux_url:
198204
with get_connection(db_config) as conn:
199205
update_build_urls(
@@ -226,7 +232,9 @@ def reconcile(
226232
continue
227233

228234
timestamp = client.release_timestamp(release)
229-
windows_url, linux_url = client.parse_release_assets(release)
235+
windows_url, linux_url = client.parse_release_assets(
236+
release, asset_filter=asset_match_filter
237+
)
230238

231239
with get_connection(db_config) as conn:
232240
upsert_build(

releases.py

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -122,11 +122,20 @@ def parse_tag(tag: str) -> tuple[str, int] | None:
122122
return m.group(1), int(m.group(2))
123123

124124
@staticmethod
125-
def parse_release_assets(release: dict) -> tuple[str | None, str | None]:
126-
"""Extract (windows_url, linux_url) from release assets."""
125+
def parse_release_assets(
126+
release: dict, asset_filter: str | None = None
127+
) -> tuple[str | None, str | None]:
128+
"""Extract (windows_url, linux_url) from release assets.
129+
130+
If asset_filter is set, only assets whose name contains the filter
131+
string are considered (e.g. "base" to match only the base package
132+
in a multi-package release).
133+
"""
127134
windows_url = linux_url = None
128135
for asset in release.get("assets", []):
129136
name = asset["name"]
137+
if asset_filter and asset_filter not in name:
138+
continue
130139
if re.search(r"-windows\.zip$", name, re.IGNORECASE):
131140
windows_url = asset["browser_download_url"]
132141
elif re.search(r"-linux\.tar\.gz$", name, re.IGNORECASE):

0 commit comments

Comments
 (0)