diff --git a/.github/dependabot.yml b/.github/dependabot.yml index 742ec57..049ee6d 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -4,6 +4,10 @@ updates: directory: / schedule: interval: weekly + # Let a release settle before opening a PR for it, so a compromised or + # promptly-yanked version is less likely to be picked up. + cooldown: + default-days: 7 groups: actions-minor: update-types: @@ -14,6 +18,8 @@ updates: directory: / schedule: interval: weekly + cooldown: + default-days: 7 groups: npm-development: dependency-type: development diff --git a/.github/linters/.codespellrc b/.github/linters/.codespellrc new file mode 100644 index 0000000..5838502 --- /dev/null +++ b/.github/linters/.codespellrc @@ -0,0 +1,2 @@ +[codespell] +ignore-words-list = thirdparty diff --git a/.github/linters/trivy.yaml b/.github/linters/trivy.yaml new file mode 100644 index 0000000..dae4525 --- /dev/null +++ b/.github/linters/trivy.yaml @@ -0,0 +1,11 @@ +--- +exit-code: 1 +exit-on-eol: 2 +scan: + disable-telemetry: true + scanners: + - vuln + - misconfig + - secret + skip-dirs: + - dist diff --git a/.github/workflows/check-dist.yml b/.github/workflows/check-dist.yml index 55dcb53..8fb8065 100644 --- a/.github/workflows/check-dist.yml +++ b/.github/workflows/check-dist.yml @@ -26,11 +26,13 @@ jobs: steps: - name: Checkout id: checkout - uses: actions/checkout@v7 + uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 + with: + persist-credentials: false - name: Setup Node.js id: setup-node - uses: actions/setup-node@v7 + uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0 with: node-version-file: package.json cache: npm @@ -58,7 +60,7 @@ jobs: - if: ${{ failure() && steps.diff.outcome == 'failure' }} name: Upload Artifact id: upload - uses: actions/upload-artifact@v7 + uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 with: name: dist path: dist/ diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index e6c4d29..1a12356 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -17,11 +17,13 @@ jobs: steps: - name: Checkout id: checkout - uses: actions/checkout@v7 + uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 + with: + persist-credentials: false - name: Setup Node.js id: setup-node - uses: actions/setup-node@v7 + uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0 with: node-version-file: package.json cache: npm @@ -49,7 +51,9 @@ jobs: steps: - name: Checkout id: checkout - uses: actions/checkout@v7 + uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 + with: + persist-credentials: false - run: cp __tests__/data/pyproject.test1.toml pyproject.toml @@ -64,7 +68,9 @@ jobs: steps: - name: Checkout id: checkout - uses: actions/checkout@v7 + uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 + with: + persist-credentials: false - run: cp __tests__/data/pyproject.test1.toml pyproject.toml diff --git a/.github/workflows/jekyll-gh-pages.yml b/.github/workflows/jekyll-gh-pages.yml index 7894ece..4ed848e 100644 --- a/.github/workflows/jekyll-gh-pages.yml +++ b/.github/workflows/jekyll-gh-pages.yml @@ -9,11 +9,8 @@ on: # Allows you to run this workflow manually from the Actions tab workflow_dispatch: -# Sets permissions of the GITHUB_TOKEN to allow deployment to GitHub Pages permissions: contents: read - pages: write - id-token: write # Allow only one concurrent deployment, skipping runs queued between the run in-progress and latest queued. # However, do NOT cancel in-progress runs as we want to allow these production deployments to complete. @@ -27,19 +24,27 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout - uses: actions/checkout@v7 + uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 + with: + persist-credentials: false - name: Setup Pages - uses: actions/configure-pages@v6 + uses: actions/configure-pages@45bfe0192ca1faeb007ade9deae92b16b8254a0d # v6.0.0 - name: Build with Jekyll - uses: actions/jekyll-build-pages@v1 + uses: actions/jekyll-build-pages@44a6e6beabd48582f863aeeb6cb2151cc1716697 # v1.0.13 with: source: ./ destination: ./_site - name: Upload artifact - uses: actions/upload-pages-artifact@v5 + uses: actions/upload-pages-artifact@fc324d3547104276b827a68afc52ff2a11cc49c9 # v5.0.0 # Deployment job deploy: + # Only this job deploys, so the GITHUB_TOKEN write scopes it needs to reach + # GitHub Pages are granted here rather than to every job in the workflow. + permissions: + contents: read + pages: write + id-token: write environment: name: github-pages url: ${{ steps.deployment.outputs.page_url }} @@ -48,4 +53,4 @@ jobs: steps: - name: Deploy to GitHub Pages id: deployment - uses: actions/deploy-pages@v5 + uses: actions/deploy-pages@cd2ce8fcbc39b97be8ca5fce6e763baed58fa128 # v5.0.0 diff --git a/.github/workflows/linter.yml b/.github/workflows/linter.yml index b24fe88..672c867 100644 --- a/.github/workflows/linter.yml +++ b/.github/workflows/linter.yml @@ -19,11 +19,16 @@ jobs: steps: - name: Checkout id: checkout - uses: actions/checkout@v7 + uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 + with: + # super-linter resolves the default branch with `git rev-parse`, so it + # needs the full git history rather than a shallow clone. + fetch-depth: 0 + persist-credentials: false - name: Setup Node.js id: setup-node - uses: actions/setup-node@v7 + uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0 with: node-version-file: package.json cache: npm @@ -34,12 +39,34 @@ jobs: - name: Lint Codebase id: super-linter - uses: super-linter/super-linter/slim@v5 + uses: super-linter/super-linter/slim@4ce20838b8ab83717e78138c5b3a1407148e0918 # v8.7.0 env: DEFAULT_BRANCH: main - FILTER_REGEX_EXCLUDE: dist/**/* + # v8 posts a summary comment by default, which needs pull-requests or + # issues write. Not worth broadening the token for: results already + # show up as status checks and in the job summary. Left enabled it + # only logs a non-fatal 403 on every run. + ENABLE_GITHUB_PULL_REQUEST_SUMMARY_COMMENT: false + # This is a regex, not a glob: the previous value (dist/**/*) also + # matched check-dist.yml and excluded it from every linter. Anchoring + # needs STRIP_DEFAULT_WORKSPACE_FOR_REGEX, because otherwise the regex + # is matched against /github/workspace/... and ^ never matches. + FILTER_REGEX_EXCLUDE: ^dist/.* + STRIP_DEFAULT_WORKSPACE_FOR_REGEX: true GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - JAVASCRIPT_DEFAULT_STYLE: prettier VALIDATE_ALL_CODEBASE: true + # ci.yml already runs `npm run lint`, which is this repo's eslint and + # this repo's eslint.config.mjs. super-linter cannot be pointed at that + # config instead: JAVASCRIPT_ES_CONFIG_FILE is shared with the JSON, + # JSONC and VUE linters, and our config has no JSON language support, + # so reusing it would silently stop linting JSON. Rather than lint JS + # twice under two different rule sets, defer to ci.yml and let + # super-linter keep its own config for JSON/JSONC. + VALIDATE_JAVASCRIPT_ES: false VALIDATE_JSCPD: false VALIDATE_HTML: false + # Biome is a competing formatter/linter: it wants semicolons and + # double quotes, while .prettierrc.yml sets semi: false and + # singleQuote: true. Prettier and eslint are this repo's tools. + VALIDATE_BIOME_FORMAT: false + VALIDATE_BIOME_LINT: false diff --git a/README.md b/README.md index c9014ae..7ba4702 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ [![GitHub Super-Linter](https://github.com/python-build-tools/pipx-install-action/actions/workflows/linter.yml/badge.svg)](https://github.com/super-linter/super-linter) ![CI](https://github.com/python-build-tools/pipx-install-action/actions/workflows/ci.yml/badge.svg) -![Test Converage](https://raw.githubusercontent.com/python-build-tools/pipx-install-action/main/badges/coverage.svg) +![Test Coverage](https://raw.githubusercontent.com/python-build-tools/pipx-install-action/main/badges/coverage.svg) This action installs Python tools using [pipx](https://github.com/pypa/pipx). diff --git a/__tests__/data/.github/workflows/test-workflow-1.yml b/__tests__/data/.github/workflows/test-workflow-1.yml index 738a572..ac5926a 100644 --- a/__tests__/data/.github/workflows/test-workflow-1.yml +++ b/__tests__/data/.github/workflows/test-workflow-1.yml @@ -1,4 +1,8 @@ on: push + +permissions: + contents: read + jobs: test: runs-on: ubuntu-latest @@ -16,11 +20,13 @@ jobs: - run: echo "/root/.local/bin" >> "$GITHUB_PATH" # Test the pipx-install action - - uses: actions/checkout@v4 + - uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4.4.0 + with: + persist-credentials: false - run: cp __tests__/data/pyproject.test1.toml pyproject.toml - uses: './' # Run this repo's action. - # Comfirm that expected tools are installed and runnable. + # Confirm that expected tools are installed and runnable. - run: poetry --version - run: poetry bundle venv --help - run: tox --version diff --git a/action.yml b/action.yml index 5be05bb..3c09abf 100644 --- a/action.yml +++ b/action.yml @@ -16,7 +16,7 @@ inputs: description: When 'true', packages will be saved to the repository's GitHub Action cache and restored whenever possible to avoid downloading from the - upstream pacakge repository (eg. PyPI) + upstream package repository (eg. PyPI) default: true runs: diff --git a/dist/index.js b/dist/index.js index a5284e6..f6a87b6 100644 --- a/dist/index.js +++ b/dist/index.js @@ -85241,7 +85241,7 @@ async function checkForPipxSharedPreExists(pipxSharedDir) { try { await fs$2.stat(pipxSharedDir); return true - } catch (error) { + } catch { return false } } diff --git a/docs/superpowers/specs/2026-08-13-esm-migration-design.md b/docs/superpowers/specs/2026-08-13-esm-migration-design.md index ebc427c..98bf543 100644 --- a/docs/superpowers/specs/2026-08-13-esm-migration-design.md +++ b/docs/superpowers/specs/2026-08-13-esm-migration-design.md @@ -89,7 +89,7 @@ Two consequences deserve explicit note. **`pipx-install.test.js` needs a partial mock of `node:fs/promises`.** It mocks `symlink` and `stat` but relies on `readFile` being real so the TOML fixtures in `__tests__/data/` still load. `unstable_mockModule` replaces a whole module, so -the fixture re-exports the real module and overrides only those two functions: +the fixture reexports the real module and overrides only those two functions: ```js const real = await import('node:fs/promises') @@ -170,7 +170,7 @@ Three deliberate deviations from the upstream template's configuration: dependency is `@actions/core`. Here, `@actions/cache` imports its own `package.json`, and the build fails outright without this plugin. - **`sourcemap: false`.** The generated source map is roughly 16.5 MB. Because - `dist/` is committed, enabling it would add that volume to git history on + `dist/` is committed, enabling it would add that volume to Git history on every dependency bump and would bury the `dist/` diff that `check-dist.yml` reports. With source maps off, `dist/` keeps exactly the two files it holds today, `index.js` and `licenses.txt`, so the migration introduces no new diff --git a/src/pipx-install.js b/src/pipx-install.js index 46622a5..262893d 100644 --- a/src/pipx-install.js +++ b/src/pipx-install.js @@ -173,7 +173,7 @@ async function checkForPipxSharedPreExists(pipxSharedDir) { try { await fs.stat(pipxSharedDir) return true - } catch (error) { + } catch { return false } }