diff --git a/.github/workflows/__greetings.yml b/.github/workflows/__greetings.yml index 0d06601..5e4bacb 100644 --- a/.github/workflows/__greetings.yml +++ b/.github/workflows/__greetings.yml @@ -10,7 +10,7 @@ permissions: {} jobs: greetings: - uses: hoverkraft-tech/ci-github-common/.github/workflows/greetings.yml@5e8d0e6d1e76d8577a070db6d0128a91b1c9d5ad # 0.30.2 + uses: hoverkraft-tech/ci-github-common/.github/workflows/greetings.yml@e6733528d06b6e1668674c35ef3612ac416cedda # 0.31.1 permissions: contents: read issues: write diff --git a/.github/workflows/__main-ci.yml b/.github/workflows/__main-ci.yml index bb7c345..67012ac 100644 --- a/.github/workflows/__main-ci.yml +++ b/.github/workflows/__main-ci.yml @@ -35,7 +35,7 @@ jobs: release: needs: ci if: github.event_name != 'schedule' - uses: hoverkraft-tech/ci-github-publish/.github/workflows/release-actions.yml@dbdcce2870b33525ac1fa26069bf95b2dd586fda # 0.15.2 + uses: hoverkraft-tech/ci-github-publish/.github/workflows/release-actions.yml@ed864a88ec8610dc2a1b9aab1dbde2864bf75df4 # 0.16.0 permissions: contents: read with: diff --git a/.github/workflows/__need-fix-to-issue.yml b/.github/workflows/__need-fix-to-issue.yml index 8aa11bd..fd9e5ba 100644 --- a/.github/workflows/__need-fix-to-issue.yml +++ b/.github/workflows/__need-fix-to-issue.yml @@ -18,7 +18,7 @@ permissions: {} jobs: main: - uses: hoverkraft-tech/ci-github-common/.github/workflows/need-fix-to-issue.yml@5e8d0e6d1e76d8577a070db6d0128a91b1c9d5ad # 0.30.2 + uses: hoverkraft-tech/ci-github-common/.github/workflows/need-fix-to-issue.yml@e6733528d06b6e1668674c35ef3612ac416cedda # 0.31.1 permissions: contents: read issues: write diff --git a/.github/workflows/__semantic-pull-request.yml b/.github/workflows/__semantic-pull-request.yml index be904c7..76e8ddf 100644 --- a/.github/workflows/__semantic-pull-request.yml +++ b/.github/workflows/__semantic-pull-request.yml @@ -12,7 +12,7 @@ permissions: {} jobs: main: - uses: hoverkraft-tech/ci-github-common/.github/workflows/semantic-pull-request.yml@5e8d0e6d1e76d8577a070db6d0128a91b1c9d5ad # 0.30.2 + uses: hoverkraft-tech/ci-github-common/.github/workflows/semantic-pull-request.yml@e6733528d06b6e1668674c35ef3612ac416cedda # 0.31.1 permissions: contents: write pull-requests: write diff --git a/.github/workflows/__shared-ci.yml b/.github/workflows/__shared-ci.yml index 586d01a..7e1c761 100644 --- a/.github/workflows/__shared-ci.yml +++ b/.github/workflows/__shared-ci.yml @@ -7,7 +7,7 @@ permissions: {} jobs: linter: - uses: hoverkraft-tech/ci-github-common/.github/workflows/linter.yml@5e8d0e6d1e76d8577a070db6d0128a91b1c9d5ad # 0.30.2 + uses: hoverkraft-tech/ci-github-common/.github/workflows/linter.yml@e6733528d06b6e1668674c35ef3612ac416cedda # 0.31.1 permissions: contents: read statuses: write diff --git a/.github/workflows/__stale.yml b/.github/workflows/__stale.yml index 1f24242..b09f6e7 100644 --- a/.github/workflows/__stale.yml +++ b/.github/workflows/__stale.yml @@ -8,7 +8,7 @@ permissions: {} jobs: main: - uses: hoverkraft-tech/ci-github-common/.github/workflows/stale.yml@5e8d0e6d1e76d8577a070db6d0128a91b1c9d5ad # 0.30.2 + uses: hoverkraft-tech/ci-github-common/.github/workflows/stale.yml@e6733528d06b6e1668674c35ef3612ac416cedda # 0.31.1 permissions: issues: write pull-requests: write diff --git a/.github/workflows/__test-workflow-continuous-integration.yml b/.github/workflows/__test-workflow-continuous-integration.yml index 014f15a..4cdb897 100644 --- a/.github/workflows/__test-workflow-continuous-integration.yml +++ b/.github/workflows/__test-workflow-continuous-integration.yml @@ -63,7 +63,7 @@ jobs: packages: write issues: read pull-requests: read - uses: hoverkraft-tech/ci-github-container/.github/workflows/docker-build-images.yml@6b0d5ca498b7a533b43e1f2e8d988678d164a429 # 0.29.1 + uses: hoverkraft-tech/ci-github-container/.github/workflows/docker-build-images.yml@0d92511a38c93e30ae0f8b82346116946987a9ca # 0.30.0 with: sign: false images: | diff --git a/.github/workflows/continuous-integration.yml b/.github/workflows/continuous-integration.yml index b0e82a9..3c9cb72 100644 --- a/.github/workflows/continuous-integration.yml +++ b/.github/workflows/continuous-integration.yml @@ -293,7 +293,7 @@ jobs: security-events: write runs-on: *ci-runner steps: - - uses: hoverkraft-tech/ci-github-common/actions/checkout@5e8d0e6d1e76d8577a070db6d0128a91b1c9d5ad # 0.30.2 + - uses: hoverkraft-tech/ci-github-common/actions/checkout@e6733528d06b6e1668674c35ef3612ac416cedda # 0.31.1 - uses: github/codeql-action/init@fdbfb4d2750291e159f0156def62b853c2798ca2 # v4.31.5 with: languages: ${{ inputs.code-ql }} @@ -306,7 +306,7 @@ jobs: contents: read runs-on: *ci-runner steps: - - uses: hoverkraft-tech/ci-github-common/actions/checkout@5e8d0e6d1e76d8577a070db6d0128a91b1c9d5ad # 0.30.2 + - uses: hoverkraft-tech/ci-github-common/actions/checkout@e6733528d06b6e1668674c35ef3612ac416cedda # 0.31.1 - uses: actions/dependency-review-action@3c4e3dcb1aa7874d2c16be7d79418e9b7efd6261 # v4.8.2 setup: @@ -334,7 +334,7 @@ jobs: steps: - name: Checkout repository if: inputs.container == '' - uses: hoverkraft-tech/ci-github-common/actions/checkout@5e8d0e6d1e76d8577a070db6d0128a91b1c9d5ad # 0.30.2 + uses: hoverkraft-tech/ci-github-common/actions/checkout@e6733528d06b6e1668674c35ef3612ac416cedda # 0.31.1 - id: working-directory uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8.0.0 @@ -458,24 +458,15 @@ jobs: permissions: contents: read packages: read - # FIXME: This is a workaround for having workflow ref. See https://github.com/orgs/community/discussions/38659 - id-token: write + id-token: write # Needed for getting local workflow actions steps: - - uses: hoverkraft-tech/ci-github-common/actions/checkout@5e8d0e6d1e76d8577a070db6d0128a91b1c9d5ad # 0.30.2 + - uses: hoverkraft-tech/ci-github-common/actions/checkout@e6733528d06b6e1668674c35ef3612ac416cedda # 0.31.1 if: inputs.container == '' - - id: oidc - uses: ChristopherHX/oidc@73eee1ff03fdfce10eda179f617131532209edbd # v3 - - uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0 + - id: local-workflow-actions + uses: hoverkraft-tech/ci-github-common/actions/local-workflow-actions@e6733528d06b6e1668674c35ef3612ac416cedda # 0.31.1 with: - path: ./self-workflow - repository: ${{ steps.oidc.outputs.job_workflow_repo_name_and_owner }} - ref: ${{ steps.oidc.outputs.job_workflow_repo_ref }} - sparse-checkout: | - actions - - run: | - if [ -f .gitignore ]; then grep -q "self-workflow" .gitignore || echo "self-workflow" >> .gitignore; else echo "self-workflow" >> .gitignore; fi - if [ -f .dockerignore ]; then grep -q "self-workflow" .dockerignore || echo "self-workflow" >> .dockerignore; else echo "self-workflow" >> .dockerignore; fi + actions-path: actions - id: preparel-lint-options uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8.0.0 @@ -508,6 +499,15 @@ jobs: report-file: ${{ steps.preparel-lint-options.outputs.report-file }} path-mapping: ${{ needs.prepare.outputs.path-mapping || '' }} + # jscpd:ignore-start + - uses: hoverkraft-tech/ci-github-common/actions/local-workflow-actions@e6733528d06b6e1668674c35ef3612ac416cedda # 0.31.1 + if: always() && steps.local-workflow-actions.outputs.repository + with: + actions-path: actions + repository: ${{ steps.local-workflow-actions.outputs.repository }} + ref: ${{ steps.local-workflow-actions.outputs.ref }} + # jscpd:ignore-end + build: if: inputs.checks == true name: ๐Ÿ—๏ธ Build @@ -519,30 +519,17 @@ jobs: permissions: contents: read packages: read - # FIXME: This is a workaround for having workflow ref. See https://github.com/orgs/community/discussions/38659 - id-token: write + id-token: write # Needed for getting local workflow actions outputs: artifact-id: ${{ steps.build.outputs.artifact-id }} steps: - - uses: hoverkraft-tech/ci-github-common/actions/checkout@5e8d0e6d1e76d8577a070db6d0128a91b1c9d5ad # 0.30.2 + - uses: hoverkraft-tech/ci-github-common/actions/checkout@e6733528d06b6e1668674c35ef3612ac416cedda # 0.31.1 if: needs.setup.outputs.build-commands && inputs.container == '' - # FIXME: This is a workaround for having workflow ref. See https://github.com/orgs/community/discussions/38659 - - id: oidc - if: needs.setup.outputs.build-commands - uses: ChristopherHX/oidc@73eee1ff03fdfce10eda179f617131532209edbd # v3 - - uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0 - if: needs.setup.outputs.build-commands + - id: local-workflow-actions + uses: hoverkraft-tech/ci-github-common/actions/local-workflow-actions@e6733528d06b6e1668674c35ef3612ac416cedda # 0.31.1 with: - path: ./self-workflow - repository: ${{ steps.oidc.outputs.job_workflow_repo_name_and_owner }} - ref: ${{ steps.oidc.outputs.job_workflow_repo_ref }} - sparse-checkout: | - actions - - if: needs.setup.outputs.build-commands - run: | - if [ -f .gitignore ]; then grep -q "self-workflow" .gitignore || echo "self-workflow" >> .gitignore; else echo "self-workflow" >> .gitignore; fi - if [ -f .dockerignore ]; then grep -q "self-workflow" .dockerignore || echo "self-workflow" >> .dockerignore; else echo "self-workflow" >> .dockerignore; fi + actions-path: actions - id: build if: needs.setup.outputs.build-commands @@ -555,6 +542,15 @@ jobs: build-env: ${{ needs.setup.outputs.build-env }} build-artifact: ${{ needs.setup.outputs.build-artifact }} + # jscpd:ignore-start + - uses: hoverkraft-tech/ci-github-common/actions/local-workflow-actions@e6733528d06b6e1668674c35ef3612ac416cedda # 0.31.1 + if: always() && steps.local-workflow-actions.outputs.repository + with: + actions-path: actions + repository: ${{ steps.local-workflow-actions.outputs.repository }} + ref: ${{ steps.local-workflow-actions.outputs.ref }} + # jscpd:ignore-end + test: if: inputs.checks == true && inputs.test name: ๐Ÿงช Test @@ -568,10 +564,9 @@ jobs: contents: read pull-requests: write packages: read - # FIXME: This is a workaround for having workflow ref. See https://github.com/orgs/community/discussions/38659 - id-token: write + id-token: write # Needed for getting local workflow actions steps: - - uses: hoverkraft-tech/ci-github-common/actions/checkout@5e8d0e6d1e76d8577a070db6d0128a91b1c9d5ad # 0.30.2 + - uses: hoverkraft-tech/ci-github-common/actions/checkout@e6733528d06b6e1668674c35ef3612ac416cedda # 0.31.1 if: inputs.container == '' - if: needs.build.outputs.artifact-id && inputs.container == '' @@ -580,19 +575,10 @@ jobs: artifact-ids: ${{ needs.build.outputs.artifact-id }} path: "/" - # FIXME: This is a workaround for having workflow ref. See https://github.com/orgs/community/discussions/38659 - - id: oidc - uses: ChristopherHX/oidc@73eee1ff03fdfce10eda179f617131532209edbd # v3 - - uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0 + - id: local-workflow-actions + uses: hoverkraft-tech/ci-github-common/actions/local-workflow-actions@e6733528d06b6e1668674c35ef3612ac416cedda # 0.31.1 with: - path: ./self-workflow - repository: ${{ steps.oidc.outputs.job_workflow_repo_name_and_owner }} - ref: ${{ steps.oidc.outputs.job_workflow_repo_ref }} - sparse-checkout: | - actions - - run: | - if [ -f .gitignore ]; then grep -q "self-workflow" .gitignore || echo "self-workflow" >> .gitignore; else echo "self-workflow" >> .gitignore; fi - if [ -f .dockerignore ]; then grep -q "self-workflow" .dockerignore || echo "self-workflow" >> .dockerignore; else echo "self-workflow" >> .dockerignore; fi + actions-path: actions - id: prepare-test-options uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8.0.0 @@ -630,3 +616,12 @@ jobs: report-file: ${{ steps.prepare-test-options.outputs.report-file }} path-mapping: ${{ needs.prepare.outputs.path-mapping || '' }} github-token: ${{ secrets.github-token || github.token }} + + # jscpd:ignore-start + - uses: hoverkraft-tech/ci-github-common/actions/local-workflow-actions@e6733528d06b6e1668674c35ef3612ac416cedda # 0.31.1 + if: always() && steps.local-workflow-actions.outputs.repository + with: + actions-path: actions + repository: ${{ steps.local-workflow-actions.outputs.repository }} + ref: ${{ steps.local-workflow-actions.outputs.ref }} + # jscpd:ignore-end diff --git a/actions/codecov/action.yml b/actions/codecov/action.yml index 43e7134..c22a863 100644 --- a/actions/codecov/action.yml +++ b/actions/codecov/action.yml @@ -51,58 +51,103 @@ runs: with: +: ${{ steps.check-codecov-deps.outputs.missing-deps }} - # Fix pkgxdev gnupg's gpgconf.ctl which contains unexpanded environment variables - - name: Fix GPG configuration - if: contains(steps.check-codecov-deps.outputs.missing-deps, 'gnupg.org') + - name: Fix unexpanded environment variables + if: steps.check-codecov-deps.outputs.missing-deps 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); - } + const templatePattern = /\$\{([^}:]+)(?::-([^}]*))?\}/g; + const unsafeSyntaxPattern = /`|\$\(/; + const resolving = new Set(); + const resolvedCache = new Map(); + + const hasTemplate = (value) => { + if (typeof value !== 'string') { + return false; } - } 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); + templatePattern.lastIndex = 0; + return templatePattern.test(value); + }; - # Fix pkgxdev curl's .curlrc which contains unexpanded environment variables - - name: Fix curl configuration - if: contains(steps.check-codecov-deps.outputs.missing-deps, 'curl') - uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8.0.0 - with: - script: | - const fs = require('node:fs'); - const path = require('node:path'); - - // Find and fix the .curlrc file that contains unexpanded shell variables like ${SSL_CERT_FILE:-...} - // The pkgxdev curl installs .curlrc next to the curl binary - try { - const curlPath = await io.which('curl', false); - if (curlPath) { - const curlrc = path.join(path.dirname(curlPath), '.curlrc'); - if (fs.existsSync(curlrc)) { - core.info(`Removing malformed .curlrc: ${curlrc}`); - await io.rmRF(curlrc); + const getReferencedVariables = (value) => { + templatePattern.lastIndex = 0; + return Array.from(value.matchAll(templatePattern), (match) => match[1]); + }; + + const sanitizeForDoubleQuotes = (value) => value.replace(/(["\\])/g, '\\$1'); + + const resolveEnvVariable = async (envKey) => { + const rawValue = process.env[envKey]; + + if (!hasTemplate(rawValue)) { + core.debug(`Skipping ${envKey} because it does not match the template pattern.`); + return rawValue; + } + + if (unsafeSyntaxPattern.test(rawValue)) { + core.debug(`Skipping ${envKey} because it contains unsupported command substitution syntax.`); + return rawValue; + } + + if (resolvedCache.has(envKey)) { + return resolvedCache.get(envKey); + } + + if (resolving.has(envKey)) { + core.debug(`Detected circular reference while resolving ${envKey}, falling back to defaults.`); + return rawValue; + } + + resolving.add(envKey); + + const referencedVariables = getReferencedVariables(rawValue); + for (const variableName of referencedVariables) { + if (variableName === envKey) { + continue; } + + await resolveEnvVariable(variableName); } - } catch (error) { - core.warning(`Failed to check/remove .curlrc: ${error.message}`); + + const envForBash = { ...process.env }; + delete envForBash[envKey]; + + const scriptLines = [ + 'set -eo pipefail', + `resolved_value="${sanitizeForDoubleQuotes(rawValue)}"`, + "printf '%s' \"${resolved_value}\"", + ]; + + let resolvedValue = rawValue; + try { + const { stdout } = await exec.getExecOutput( + 'bash', + ['-c', scriptLines.join('\n')], + { env: envForBash, silent: true } + ); + + resolvedValue = stdout.replace(/\r?\n$/, ''); + } catch (error) { + core.warning(`Failed to resolve ${envKey}: ${error.message}`); + } + + resolving.delete(envKey); + resolvedCache.set(envKey, resolvedValue); + + if (resolvedValue !== rawValue) { + core.debug(`Resolved ${envKey}: "${rawValue}" -> "${resolvedValue}"`); + process.env[envKey] = resolvedValue; + core.exportVariable(envKey, resolvedValue); + } else { + core.debug(`No changes for ${envKey}, skipping update.`); + } + + return resolvedValue; + }; + + for (const envKey of Object.keys(process.env)) { + await resolveEnvVariable(envKey); } - name: ๐Ÿ“Š Upload coverage to Codecov diff --git a/actions/lint/action.yml b/actions/lint/action.yml index 21afeee..a993b6f 100644 --- a/actions/lint/action.yml +++ b/actions/lint/action.yml @@ -103,7 +103,7 @@ runs: - name: ๐Ÿ“Š Parse lint reports if: always() - uses: hoverkraft-tech/ci-github-common/actions/parse-ci-reports@5e8d0e6d1e76d8577a070db6d0128a91b1c9d5ad # 0.30.2 + uses: hoverkraft-tech/ci-github-common/actions/parse-ci-reports@e6733528d06b6e1668674c35ef3612ac416cedda # 0.31.1 with: working-directory: ${{ inputs.working-directory }} report-paths: ${{ inputs.report-file || 'auto:lint' }} diff --git a/actions/test/action.yml b/actions/test/action.yml index 7bee100..48078e0 100644 --- a/actions/test/action.yml +++ b/actions/test/action.yml @@ -104,7 +104,6 @@ runs: const runScriptCommand = process.env.RUN_TEST_COMMAND; const testCommand = process.env.TEST_COMMAND || 'test:ci'; - core.info(`๐Ÿงช Running test command: ${testCommand}...`); try { @@ -127,7 +126,7 @@ runs: - name: ๐Ÿ“Š Parse coverage reports if: always() && inputs.coverage == 'github' id: parse-coverage-reports - uses: hoverkraft-tech/ci-github-common/actions/parse-ci-reports@5e8d0e6d1e76d8577a070db6d0128a91b1c9d5ad # 0.30.2 + uses: hoverkraft-tech/ci-github-common/actions/parse-ci-reports@e6733528d06b6e1668674c35ef3612ac416cedda # 0.31.1 with: working-directory: ${{ inputs.working-directory }} report-name: "Coverage Results" @@ -137,7 +136,7 @@ runs: - name: ๐Ÿ“Š Add coverage PR comment if: always() && inputs.coverage == 'github' && github.event_name == 'pull_request' && steps.parse-coverage-reports.outputs.markdown - uses: hoverkraft-tech/ci-github-common/actions/create-or-update-comment@5e8d0e6d1e76d8577a070db6d0128a91b1c9d5ad # 0.30.2 + uses: hoverkraft-tech/ci-github-common/actions/create-or-update-comment@e6733528d06b6e1668674c35ef3612ac416cedda # 0.31.1 with: title: "Code Coverage Report" body: ${{ steps.parse-coverage-reports.outputs.markdown }}