diff --git a/actions/test/action.yml b/actions/test/action.yml index 0c9864f..ab1b129 100644 --- a/actions/test/action.yml +++ b/actions/test/action.yml @@ -53,6 +53,10 @@ inputs: description: | GitHub token for coverage PR comments. Required when coverage is set to `github`. + Requires permissions to create and update PR comments: + + - `issues: write` + - `pull-requests: write` required: false default: "" @@ -138,12 +142,64 @@ runs: title: "Code Coverage Report" body: ${{ steps.parse-coverage-reports.outputs.markdown }} - # Install dependencies for codecov in container mode - - name: Install Codecov dependencies - if: inputs.coverage == 'codecov' && inputs.container == 'true' + # Check and install dependencies for codecov in container mode + - name: Check and install Codecov dependencies + if: always() && inputs.coverage == 'codecov' && inputs.container == 'true' + id: check-codecov-deps + uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8.0.0 + with: + script: | + // Check which dependencies are missing + const deps = {"git": "git", "curl": "curl", "gpg": "gnupg.org"}; + const missingDeps = []; + + for (const [dep, pkg] of Object.entries(deps)) { + try { + await io.which(dep, true); + } catch { + missingDeps.push(pkg); + } + } + + if (missingDeps.length > 0) { + core.setOutput('missing-deps', missingDeps.join(' ')); + } + + - name: Install missing Codecov dependencies + if: always() && steps.check-codecov-deps.outputs.missing-deps uses: pkgxdev/setup@f211ee4db3110b42e5a156282372527e7c1ed723 # v4.0.0 with: - +: git curl gnupg.org + +: ${{ steps.check-codecov-deps.outputs.missing-deps }} + + # Fix pkgxdev gnupg's gpgconf.ctl which contains unexpanded environment variables + - name: Fix GPG configuration + if: always() && contains(steps.check-codecov-deps.outputs.missing-deps, 'gnupg.org') + uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8.0.0 + with: + script: | + const fs = require('node:fs'); + const path = require('node:path'); + const os = require('node:os'); + + // Find and remove the malformed gpgconf.ctl file that contains unexpanded shell variables + // The pkgxdev gnupg installs gpgconf.ctl next to the gpgconf binary + try { + const gpgconfPath = await io.which('gpgconf', false); + if (gpgconfPath) { + const gpgconfCtl = path.join(path.dirname(gpgconfPath), 'gpgconf.ctl'); + if (fs.existsSync(gpgconfCtl)) { + core.info(`Removing malformed gpgconf.ctl: ${gpgconfCtl}`); + await io.rmRF(gpgconfCtl); + } + } + } catch (error) { + core.warning(`Failed to check/remove gpgconf.ctl: ${error.message}`); + } + + // Ensure GNUPGHOME is set up correctly + const gnupgHome = path.join(os.homedir(), '.gnupg'); + await io.mkdirP(gnupgHome); + fs.chmodSync(gnupgHome, 0o700); - name: 📊 Upload coverage to Codecov if: always() && inputs.coverage == 'codecov'