diff --git a/.vale/styles/Google/Anthropomorphism.yml b/.vale/styles/Google/Anthropomorphism.yml new file mode 100644 index 0000000..36137a1 --- /dev/null +++ b/.vale/styles/Google/Anthropomorphism.yml @@ -0,0 +1,12 @@ +extends: existence +message: "Don't attribute human qualities to software or hardware ('%s')." +link: https://developers.google.com/style/anthropomorphism +level: suggestion +ignorecase: true +# Limited to the two verbs the guide itself names. Broader lists (wants, knows, +# thinks) can't tell a software subject from a human one: on a 950-file corpus +# they produced 8 false positives ('the customer wants', 'your audience knows') +# for every 2 real ones. +tokens: + - sees + - tells diff --git a/.vale/styles/Google/ExcessiveClaims.yml b/.vale/styles/Google/ExcessiveClaims.yml new file mode 100644 index 0000000..a44aca1 --- /dev/null +++ b/.vale/styles/Google/ExcessiveClaims.yml @@ -0,0 +1,14 @@ +extends: existence +message: "Avoid the unverifiable claim '%s'." +link: https://developers.google.com/style/excessive-claims +level: suggestion +ignorecase: true +# The guide also names 'never', 'always', and 'ensure', but in technical writing +# those are usually legitimate instructions ('never commit secrets') rather than +# product claims: they accounted for 125 of 142 hits on a 950-file corpus. +# 'best practices' is a fixed term, not a superlative. +tokens: + - 'best(?! practices?)' + - simplest + - fastest + - guarantees? diff --git a/.vale/styles/Google/Jargon.yml b/.vale/styles/Google/Jargon.yml new file mode 100644 index 0000000..c8cc8fb --- /dev/null +++ b/.vale/styles/Google/Jargon.yml @@ -0,0 +1,13 @@ +extends: existence +message: "Avoid the jargon '%s'." +link: https://developers.google.com/style/jargon +level: suggestion +ignorecase: true +# The guide also cites 'solution', 'support', and 'workload' as overloaded +# terms, but those have ordinary technical meanings and accounted for every hit +# on a 950-file corpus, so only the unambiguous figurative terms are listed. +tokens: + - break-glass + - camel ?case + - out-of-the-box + - swim ?lane diff --git a/.vale/styles/Google/Timeless.yml b/.vale/styles/Google/Timeless.yml new file mode 100644 index 0000000..943f449 --- /dev/null +++ b/.vale/styles/Google/Timeless.yml @@ -0,0 +1,13 @@ +extends: existence +message: "Avoid time-based words like '%s' in product documentation." +link: https://developers.google.com/style/timeless-documentation +level: suggestion +ignorecase: true +# The guide also names 'now' and 'new', but both have common senses that aren't +# time-anchored ('create a new project'): adding them took a 950-file corpus of +# technical documentation from 14 hits to 117. 'recently' is left out too — every +# hit in that corpus was the UI idiom 'recently used'. +tokens: + - currently + - latest + - soon diff --git a/.vale/styles/Google/WordListCase.yml b/.vale/styles/Google/WordListCase.yml new file mode 100644 index 0000000..0228496 --- /dev/null +++ b/.vale/styles/Google/WordListCase.yml @@ -0,0 +1,68 @@ +extends: substitution +message: "Use '%s' instead of '%s'." +link: "https://developers.google.com/style/word-list" +level: warning +# The case-insensitive half of the word list, so sentence-initial use is caught +# ('Touch the screen', not only 'touch the screen'). Entries that must stay +# case-sensitive are in WordList.yml. +ignorecase: true +action: + name: replace +swap: + "(?:API Console|dev|developer) key": API key + "(?:cell ?phone|smart ?phone)": phone|mobile phone + "(?:dev|developer|APIs) console": API console + "(?:e-mail|Email|E-mail)": email + "(?:file ?path|path ?name)": path + "(?:kill|terminate|abort)": stop|exit|cancel|end + # Longest form first: with the shortest alternative leading, 'OAuth 2' matched + # only 'OAuth', so applying the suggestion produced 'OAuth 2.0 2'. The rule is + # already case-insensitive, so the inline (?i) is redundant. See issue #41. + '\bOauth2\.0\b|\bOAuth ?2\b(?!\.0)|\bOauth\b(?! ?2)': OAuth 2.0 + "(?:ok|Okay)": OK|okay + "(?:WiFi|wifi)": Wi-Fi + '[\.]+apk': APK + '3\-D': 3D + 'Google (?:I\-O|IO)': Google I/O + "tap (?:&|and) hold": touch & hold + "un(?:check|select)": clear + above: preceding + account name: username + action bar: app bar + admin: administrator + a\.k\.a|aka: or|also known as + application: app + approx\.: approximately + autoupdate: automatically update + cellular data: mobile data + cellular network: mobile network + chapter: documents|pages|sections + check box: checkbox + click on: click|click in + content type: media type + curated roles: predefined roles + data are: data is + disabled?: turn off|off + ephemeral IP address: ephemeral external IP address + fewer data: less data + file name: filename + firewalls: firewall rules + functionality: capability|feature + grayed-out: unavailable + in order to: to + ingest: import|load + long press: touch & hold + network IP address: internal IP address + omnibox: address bar + open-source: open source + overview screen: recents screen + regex: regular expression + sign into: sign in to + '(? dict[str, str]: """Build environment for a single molecule pair.""" _role, _scenario, platform_name, platform_image, platform_command = parse_pair(pair) env = base_env.copy() + # Append runner index to platform name when running in CI matrix to avoid + # Docker container name conflicts when multiple runners share the same Docker host. + matrix_index = env.get("MATRIX_INDEX") + if matrix_index: + platform_name = f"{platform_name}-r{matrix_index}" env["MOLECULE_PLATFORM_NAME"] = platform_name env["MOLECULE_PLATFORM_IMAGE"] = platform_image if platform_command: diff --git a/tests/unit/test_molecule_ci_guard.py b/tests/unit/test_molecule_ci_guard.py index 4fd4a9f..fda5ebc 100644 --- a/tests/unit/test_molecule_ci_guard.py +++ b/tests/unit/test_molecule_ci_guard.py @@ -102,6 +102,16 @@ class TestBuildEnvForPair: env = build_env_for_pair("default|ubuntu-2204|img:latest|", {"MOLECULE_HOME": "/custom/home"}) assert env["MOLECULE_HOME"] == "/custom/home" + def test_appends_matrix_index_to_platform_name(self) -> None: + """When MATRIX_INDEX is set, platform name gets a unique suffix.""" + env = build_env_for_pair("default|ubuntu-2604|img:latest|sleep infinity", {"MATRIX_INDEX": "3"}) + assert env["MOLECULE_PLATFORM_NAME"] == "ubuntu-2604-r3" + + def test_no_matrix_index_keeps_platform_name(self) -> None: + """Without MATRIX_INDEX, platform name is unchanged.""" + env = build_env_for_pair("default|ubuntu-2604|img:latest|sleep infinity", {}) + assert env["MOLECULE_PLATFORM_NAME"] == "ubuntu-2604" + class TestPollForOtherFailures: def test_sets_failed_event_when_other_runner_fails(self) -> None: