scm: make ScmOverride hashable with nested values - #704
Conversation
3c20b19 to
a652b60
Compare
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## master #704 +/- ##
==========================================
+ Coverage 89.23% 89.25% +0.01%
==========================================
Files 50 50
Lines 16450 16456 +6
==========================================
+ Hits 14679 14687 +8
+ Misses 1771 1769 -2 ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
2140c86 to
d6c21cc
Compare
|
Wouldn't it be more natural to add support for "user:password" standard basic authentication in the URL? Regarding the "token" field, this seems to be a non standard header. You can already add custom headers to an URL SCM. This should even work through scmOverride... |
ScmOverride.__hash__ built a frozenset from the raw 'match' and 'set'
items. Both allow arbitrary values (schema '{str: object}'), e.g. the
'headers' dict of an url SCM. A nested dict/list value made the override
unhashable, so as soon as such an override matched, collecting it into
the builder's active-overrides set() crashed with:
TypeError: unhashable type: 'dict'
Recursively freeze nested dicts/lists into frozensets/tuples before
hashing. This makes it possible to inject e.g. authentication headers
into a url SCM via scmOverrides:
scmOverrides:
- match:
url: "https://gitea.example.com/*"
set:
headers:
Authorization: "token <personal access token>"
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
d6c21cc to
356c155
Compare
unluckely it doesn't work like expected. i switched this PR to fix the remaining issue. |
Problem
scmOverridesallows arbitrary values inmatchandset(schema{str: object}).A natural use case is injecting authentication headers into a
urlSCM so thatdownloads from a private server work — matched by host and kept out of the
version-controlled recipe:
This crashes as soon as the override actually matches:
ScmOverride.__hash__builds afrozensetdirectly from the raw match/setitems. A nested dict/list value (like headers) is unhashable, and since
matched overrides are collected into a
set()in the builder(
builder.getActiveOverrides()), any build that hits such an override fails.Fix
Recursively freeze nested dict/list values into frozenset/tuple before
hashing. __eq__already compares the raw structures correctly and is leftunchanged.
Tests
Added two regression tests to
test/unit/test_input_scmoverride.py:set()(equal overrides collapse, unequal ones stay distinct);Note
This came out of a discussion about a proposed urlCredentials config option.
With this fix, authenticated url SCMs can be handled entirely through the
existing headers attribute + scmOverrides (kept in a git-ignored
user.yaml), so no dedicated credentials setting is needed.