From 4a45b7df37244a6878e6aa00f1343d23fa0d7c1f Mon Sep 17 00:00:00 2001 From: Eric Searcy Date: Fri, 21 Aug 2026 11:49:27 -0700 Subject: [PATCH 1/7] ci: use recommended-replacement format in cspell flagWords (LFXV2-3338) Match the flagWords format already used in linuxfoundation/lfx-v1-sync-helper's .cspell.json, where each entry includes a suggested replacement (e.g. "master: controller, primary, main, leader, parent") instead of just the flagged word alone. This gives contributors an actionable suggestion instead of just a bare rejection. Also picks up the grandfathered entry that was missing here. Assisted-by: github-copilot:claude-sonnet-5 Signed-off-by: Eric Searcy --- .cspell.json | 33 +++++++++++++++++---------------- 1 file changed, 17 insertions(+), 16 deletions(-) diff --git a/.cspell.json b/.cspell.json index 4de95cc..3ef2ede 100644 --- a/.cspell.json +++ b/.cspell.json @@ -35,22 +35,23 @@ "zizmor" ], "flagWords": [ - "abort", - "abortion", - "blackhat", - "black-hat", - "whitehat", - "white-hat", - "cripple", - "crippled", - "master", - "slave", - "tribe", - "sanity-check", - "whitelist", - "white-list", - "blacklist", - "black-list" + "abort: cancel, end, fail, halt, stop, terminate", + "abortion: cancelation, ending, failure, halting, stopping, termination", + "blackhat: attacker, malicious", + "black-hat: attacker, malicious", + "whitehat: ethical, security, researcher", + "white-hat: ethical, security, researcher", + "cripple: disable, degrade, impact", + "crippled: disabled, degraded, impacted", + "grandfathered: legacy, exempted, preauthorized", + "master: controller, primary, main, leader, parent", + "slave: agent, replica, secondary, follower, child", + "tribe: squad, team, group", + "sanity-check: test, verify, validate", + "whitelist: allowlist", + "white-list: allow-list", + "blacklist: denylist", + "black-list: deny-list" ], "ignorePaths": [ ".cspell.json", From de23cb6092e99d932e4ca2586975df69598c4019 Mon Sep 17 00:00:00 2001 From: Eric Searcy Date: Fri, 21 Aug 2026 11:58:44 -0700 Subject: [PATCH 2/7] ci: use shared cspell flagWords snippet (LFXV2-3338) Replace the inline flagWords list with an empty placeholder pulled in at MegaLinter run time from linuxfoundation/lfx-public-workflows' cspell/flagwords.snippet.json (see that repo's cspell/README.md), instead of duplicating and drifting the list locally. Assisted-by: github-copilot:claude-sonnet-5 Signed-off-by: Eric Searcy --- .cspell.json | 31 ++++++++++--------------------- .mega-linter.yml | 7 +++++++ 2 files changed, 17 insertions(+), 21 deletions(-) diff --git a/.cspell.json b/.cspell.json index 3ef2ede..0c4c40d 100644 --- a/.cspell.json +++ b/.cspell.json @@ -1,6 +1,11 @@ { "language": "en", - "dictionaries": ["companies", "filetypes", "fullstack", "softwareTerms"], + "dictionaries": [ + "companies", + "filetypes", + "fullstack", + "softwareTerms" + ], "words": [ "aquasecurity", "artipacked", @@ -34,25 +39,7 @@ "urfave", "zizmor" ], - "flagWords": [ - "abort: cancel, end, fail, halt, stop, terminate", - "abortion: cancelation, ending, failure, halting, stopping, termination", - "blackhat: attacker, malicious", - "black-hat: attacker, malicious", - "whitehat: ethical, security, researcher", - "white-hat: ethical, security, researcher", - "cripple: disable, degrade, impact", - "crippled: disabled, degraded, impacted", - "grandfathered: legacy, exempted, preauthorized", - "master: controller, primary, main, leader, parent", - "slave: agent, replica, secondary, follower, child", - "tribe: squad, team, group", - "sanity-check: test, verify, validate", - "whitelist: allowlist", - "white-list: allow-list", - "blacklist: denylist", - "black-list: deny-list" - ], + "flagWords": [], "ignorePaths": [ ".cspell.json", "CODEOWNERS", @@ -64,7 +51,9 @@ "languageSettings": [ { "languageId": "markdown", - "ignoreRegExpList": ["/^\\s*```\\s*(mermaid)[\\s\\S]*?^\\s*```/gm"] + "ignoreRegExpList": [ + "/^\\s*```\\s*(mermaid)[\\s\\S]*?^\\s*```/gm" + ] } ] } diff --git a/.mega-linter.yml b/.mega-linter.yml index b93d824..fa395ac 100644 --- a/.mega-linter.yml +++ b/.mega-linter.yml @@ -18,6 +18,13 @@ DISABLE_ERRORS_LINTERS: - SPELL_CSPELL YAML_YAMLLINT_CONFIG_FILE: .yamllint SPELL_CSPELL_ANALYZE_FILE_NAMES: false +SPELL_CSPELL_PRE_COMMANDS: + - command: >- + curl -sf + https://raw.githubusercontent.com/linuxfoundation/lfx-public-workflows/main/cspell/flagwords.snippet.json + -o /tmp/flagwords.snippet.json && + sed -i -e '/"flagWords": \[\]/{r /tmp/flagwords.snippet.json' -e 'd}' .cspell.json + cwd: "workspace" # Ignore YAML files with templating macros; these typically fail linting and/or # schema checking. FILTER_REGEX_EXCLUDE: '(templates/.*\.yml|templates/.*\.yaml)' From 34952db9a86c73fff3ead3af09487406f488c3ad Mon Sep 17 00:00:00 2001 From: Eric Searcy Date: Fri, 21 Aug 2026 12:18:38 -0700 Subject: [PATCH 3/7] ci: back up and restore .cspell.json around the cspell pre-command (LFXV2-3338) Address review feedback on the shared cspell flagWords mechanism: the sed substitution mutated the tracked .cspell.json in place. In CI this is harmless (ephemeral checkout), but a developer running MegaLinter locally via 'make megalinter' bind-mounts the real working directory, so the substitution would persist to disk and could get accidentally committed, and a second local run would silently no-op (placeholder already consumed) instead of re-fetching the latest shared list. Back up .cspell.json before the substitution and restore it via a global POST_COMMANDS entry once the run finishes, matching the fix landed in linuxfoundation/lfx-public-workflows#15. Assisted-by: github-copilot:claude-sonnet-5 Signed-off-by: Eric Searcy --- .mega-linter.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.mega-linter.yml b/.mega-linter.yml index fa395ac..b4b3c2e 100644 --- a/.mega-linter.yml +++ b/.mega-linter.yml @@ -20,11 +20,15 @@ YAML_YAMLLINT_CONFIG_FILE: .yamllint SPELL_CSPELL_ANALYZE_FILE_NAMES: false SPELL_CSPELL_PRE_COMMANDS: - command: >- + cp .cspell.json /tmp/cspell.json.orig && curl -sf https://raw.githubusercontent.com/linuxfoundation/lfx-public-workflows/main/cspell/flagwords.snippet.json -o /tmp/flagwords.snippet.json && sed -i -e '/"flagWords": \[\]/{r /tmp/flagwords.snippet.json' -e 'd}' .cspell.json cwd: "workspace" +POST_COMMANDS: + - command: cp /tmp/cspell.json.orig .cspell.json + cwd: "workspace" # Ignore YAML files with templating macros; these typically fail linting and/or # schema checking. FILTER_REGEX_EXCLUDE: '(templates/.*\.yml|templates/.*\.yaml)' From da1907dff23f641cd68287c18c0fe0937cb21f88 Mon Sep 17 00:00:00 2001 From: Eric Searcy Date: Fri, 21 Aug 2026 14:20:35 -0700 Subject: [PATCH 4/7] ci: use scoped SPELL_CSPELL_POST_COMMANDS and fail loudly on fetch errors (LFXV2-3338) Address review feedback on the shared cspell flagWords mechanism: - MegaLinter v9.6.0 supports per-linter _POST_COMMANDS. Use SPELL_CSPELL_POST_COMMANDS instead of the global POST_COMMANDS, so the restore runs immediately after cspell finishes rather than waiting for every other linter to complete, and can't fire in a run where cspell itself didn't execute. - MegaLinter's PRE_COMMANDS default to continue_if_failed: true, so a failed curl fetch or sed substitution would silently leave the placeholder-only flagWords: [] in place and let the run continue. Set continue_if_failed: false explicitly, and use curl -sSf (instead of -sf) so a fetch failure's error detail is preserved in logs. Matches the fix landed in linuxfoundation/lfx-public-workflows#15. Assisted-by: github-copilot:claude-sonnet-5 Signed-off-by: Eric Searcy --- .mega-linter.yml | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/.mega-linter.yml b/.mega-linter.yml index b4b3c2e..0a7591c 100644 --- a/.mega-linter.yml +++ b/.mega-linter.yml @@ -21,12 +21,13 @@ SPELL_CSPELL_ANALYZE_FILE_NAMES: false SPELL_CSPELL_PRE_COMMANDS: - command: >- cp .cspell.json /tmp/cspell.json.orig && - curl -sf + curl -sSf https://raw.githubusercontent.com/linuxfoundation/lfx-public-workflows/main/cspell/flagwords.snippet.json -o /tmp/flagwords.snippet.json && sed -i -e '/"flagWords": \[\]/{r /tmp/flagwords.snippet.json' -e 'd}' .cspell.json cwd: "workspace" -POST_COMMANDS: + continue_if_failed: false +SPELL_CSPELL_POST_COMMANDS: - command: cp /tmp/cspell.json.orig .cspell.json cwd: "workspace" # Ignore YAML files with templating macros; these typically fail linting and/or From eb3f753dd616561ddc9c0e379eb844c663796e5a Mon Sep 17 00:00:00 2001 From: Eric Searcy Date: Tue, 25 Aug 2026 14:12:01 -0700 Subject: [PATCH 5/7] ci: commit cspell flagWords directly instead of runtime injection The runtime injection via SPELL_CSPELL_PRE_COMMANDS fetched a flagwords snippet from a URL that does not exist on lfx-public-workflows's main branch, causing the MegaLinter cspell pre-command to fail on every run. Commit the recommended-replacement flagWords entries directly in .cspell.json instead, matching the lfx-v1-sync-helper reference configuration. Also add the MegaLinter env: hygiene comment, and megalinter-reports/ gitignore entry per the LFXV2-3338 standardization. LFXV2-3338 Assisted-by: github-copilot:claude-sonnet-5 Signed-off-by: Eric Searcy --- .cspell.json | 20 +++++++++++++++++++- .github/workflows/mega-linter.yml | 4 ++++ .gitignore | 3 ++- .mega-linter.yml | 12 ------------ 4 files changed, 25 insertions(+), 14 deletions(-) diff --git a/.cspell.json b/.cspell.json index 0c4c40d..a1327c8 100644 --- a/.cspell.json +++ b/.cspell.json @@ -39,7 +39,25 @@ "urfave", "zizmor" ], - "flagWords": [], + "flagWords": [ + "abort: cancel, end, fail, halt, stop, terminate", + "abortion: cancelation, ending, failure, halting, stopping, termination", + "blackhat: attacker, malicious", + "black-hat: attacker, malicious", + "whitehat: ethical, security, researcher", + "white-hat: ethical, security, researcher", + "cripple: disable, degrade, impact", + "crippled: disabled, degraded, impacted", + "grandfathered: legacy, exempted, preauthorized", + "master: controller, primary, main, leader, parent", + "slave: agent, replica, secondary, follower, child", + "tribe: squad, team, group", + "sanity-check: test, verify, validate", + "whitelist: allowlist", + "white-list: allow-list", + "blacklist: denylist", + "black-list: deny-list" + ], "ignorePaths": [ ".cspell.json", "CODEOWNERS", diff --git a/.github/workflows/mega-linter.yml b/.github/workflows/mega-linter.yml index 66a695b..b5d036d 100644 --- a/.github/workflows/mega-linter.yml +++ b/.github/workflows/mega-linter.yml @@ -37,6 +37,10 @@ jobs: # `megalinter` target in the Makefile. uses: oxsecurity/megalinter/flavors/go@ef3e84b8b836d76db562d0f3ed7da61e8fd538bc # v9.6.0 env: + # Only Actions-specific values (secrets, runner behavior) belong + # here. Generic MegaLinter/repo config belongs in .mega-linter.yml + # so local runs (e.g. mega-linter-runner) get the same behavior. + # # All available variables are described in documentation # https://megalinter.io/latest/configuration/ GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/.gitignore b/.gitignore index 9374fa0..0d4f855 100644 --- a/.gitignore +++ b/.gitignore @@ -119,4 +119,5 @@ docs/_build/ site/ # Lint files -megalinter-reports +# MegaLinter local-run report output. +megalinter-reports/ diff --git a/.mega-linter.yml b/.mega-linter.yml index 0a7591c..b93d824 100644 --- a/.mega-linter.yml +++ b/.mega-linter.yml @@ -18,18 +18,6 @@ DISABLE_ERRORS_LINTERS: - SPELL_CSPELL YAML_YAMLLINT_CONFIG_FILE: .yamllint SPELL_CSPELL_ANALYZE_FILE_NAMES: false -SPELL_CSPELL_PRE_COMMANDS: - - command: >- - cp .cspell.json /tmp/cspell.json.orig && - curl -sSf - https://raw.githubusercontent.com/linuxfoundation/lfx-public-workflows/main/cspell/flagwords.snippet.json - -o /tmp/flagwords.snippet.json && - sed -i -e '/"flagWords": \[\]/{r /tmp/flagwords.snippet.json' -e 'd}' .cspell.json - cwd: "workspace" - continue_if_failed: false -SPELL_CSPELL_POST_COMMANDS: - - command: cp /tmp/cspell.json.orig .cspell.json - cwd: "workspace" # Ignore YAML files with templating macros; these typically fail linting and/or # schema checking. FILTER_REGEX_EXCLUDE: '(templates/.*\.yml|templates/.*\.yaml)' From e87a5c52d00fb6abfd59c5d2ec8d87ffbbadbcad Mon Sep 17 00:00:00 2001 From: Eric Searcy Date: Fri, 28 Aug 2026 14:00:50 -0700 Subject: [PATCH 6/7] docs: fix object_type typo in my-grants README example Assisted-by: github-copilot:claude-sonnet-5 Signed-off-by: Eric Searcy --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 9d215a2..99ae5e6 100644 --- a/README.md +++ b/README.md @@ -39,7 +39,7 @@ lfx auth token lfx auth logout # Make an authenticated call to an LFX platform API endpoint. -lfx api '/my-grants?v=1&object_type=projects' +lfx api '/my-grants?v=1&object_type=project' lfx api /projects --field name=example # auto-promotes to POST lfx api -X PUT /projects/123 --input - -H "If-Match: " < input.json # Content-Type: application/json is added automatically ``` From 67666ac219d938beed1f2d7e52d25aaad8bfc169 Mon Sep 17 00:00:00 2001 From: Eric Searcy Date: Mon, 31 Aug 2026 11:40:49 -0700 Subject: [PATCH 7/7] test: align object_type example with singular 'project' Assisted-by: github-copilot:claude-sonnet-5 Signed-off-by: Eric Searcy --- internal/commands/api_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/internal/commands/api_test.go b/internal/commands/api_test.go index 4aa4ae0..6e514d8 100644 --- a/internal/commands/api_test.go +++ b/internal/commands/api_test.go @@ -71,7 +71,7 @@ func TestAPIJoinURL(t *testing.T) { {name: "trailing slash on base", base: "https://api.example.com/", path: "projects", want: "https://api.example.com/projects"}, {name: "leading slash on path", base: "https://api.example.com", path: "/projects", want: "https://api.example.com/projects"}, {name: "both slashes", base: "https://api.example.com/", path: "/projects", want: "https://api.example.com/projects"}, - {name: "query string preserved", base: "https://api.example.com", path: "/my-grants?v=1&object_type=projects", want: "https://api.example.com/my-grants?v=1&object_type=projects"}, + {name: "query string preserved", base: "https://api.example.com", path: "/my-grants?v=1&object_type=project", want: "https://api.example.com/my-grants?v=1&object_type=project"}, {name: "fragment preserved", base: "https://api.example.com", path: "/projects#frag", want: "https://api.example.com/projects#frag"}, {name: "encoded slash preserved verbatim", base: "https://api.example.com", path: "/objects/a%2Fb", want: "https://api.example.com/objects/a%2Fb"}, }