diff --git a/.github/workflows/actionlint.yml b/.github/workflows/actionlint.yml new file mode 100644 index 0000000..1400fb0 --- /dev/null +++ b/.github/workflows/actionlint.yml @@ -0,0 +1,23 @@ +name: 'Actionlint' +on: + pull_request: + workflow_dispatch: + +permissions: + contents: 'read' + pull-requests: 'write' + +concurrency: + group: 'actionlint-${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}' + cancel-in-progress: true + +jobs: + lint: + runs-on: 'ubuntu-latest' + steps: + - uses: 'actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd' # ratchet:actions/checkout@v6 + - name: 'Run actionlint with reviewdog' + uses: 'reviewdog/action-actionlint@6fb7acc99f4a1008869fa8a0f09cfca740837d9d' # ratchet:reviewdog/action-actionlint@v1.72.0 + with: + fail_level: 'error' + reporter: 'github-pr-check' diff --git a/.github/workflows/centralized-stale.yml b/.github/workflows/centralized-stale.yml new file mode 100644 index 0000000..ed2cefa --- /dev/null +++ b/.github/workflows/centralized-stale.yml @@ -0,0 +1,101 @@ +name: 'Centralized Organization Stale Bot' +permissions: {} +on: + schedule: + # Run daily at 01:00 UTC + - cron: '0 1 * * *' + workflow_dispatch: + +jobs: + # Stage 1: Query the organization for all active repositories + fetch-repositories: + runs-on: 'ubuntu-latest' + outputs: + matrix: '${{ steps.set-matrix.outputs.repos }}' + steps: + - id: 'auth-minty' + name: 'Authenticate to Google Cloud' + uses: 'google-github-actions/auth@6fc4af4b145ae7821d527454aa9bd537d1f2dc5f' # ratchet:google-github-actions/auth@v2 + with: + create_credentials_file: false + export_environment_variables: false + workload_identity_provider: '${{ vars.TOKEN_MINTER_WIF_PROVIDER }}' + service_account: '${{ vars.TOKEN_MINTER_WIF_SERVICE_ACCOUNT }}' + token_format: 'id_token' + id_token_audience: '${{ vars.TOKEN_MINTER_SERVICE_AUDIENCE }}' + id_token_include_email: true + + - id: 'mint-github-token' + uses: 'abcxyz/github-token-minter/.github/actions/minty@45c29ca3418ff3bb3ad5815d88a80536efeba21b' # ratchet:abcxyz/github-token-minter/.github/actions/minty@main + with: + id_token: '${{ steps.auth-minty.outputs.id_token }}' + service_url: '${{ vars.TOKEN_MINTER_SERVICE_URL }}' + requested_permissions: |- + { + "scope": "stale-bot", + "repositories": ["*"], + "org_name": "google-github-actions" + } + + - name: 'List active repositories' + id: set-matrix + env: + GH_TOKEN: '${{ steps.mint-github-token.outputs.token }}' + run: | + # Query GitHub API for active, public, non-forked repositories and force single-line JSON to prevent GITHUB_OUTPUT truncation + REPOS=$(gh api --paginate /orgs/google-github-actions/repos | jq -s 'add | [.[] | select(.archived == false and .private == false and .fork == false) | .name]' -c) + echo "repos=${REPOS}" >> "$GITHUB_OUTPUT" + + # Stage 2: Fan out official actions/stale across all discovered repositories + apply-stale-rules: + needs: fetch-repositories + runs-on: 'ubuntu-latest' + strategy: + fail-fast: false + matrix: + repo: '${{ fromJson(needs.fetch-repositories.outputs.matrix) }}' + + steps: + - id: 'auth-minty' + name: 'Authenticate to Google Cloud' + uses: 'google-github-actions/auth@6fc4af4b145ae7821d527454aa9bd537d1f2dc5f' # ratchet:google-github-actions/auth@v2 + with: + create_credentials_file: false + export_environment_variables: false + workload_identity_provider: '${{ vars.TOKEN_MINTER_WIF_PROVIDER }}' + service_account: '${{ vars.TOKEN_MINTER_WIF_SERVICE_ACCOUNT }}' + token_format: 'id_token' + id_token_audience: '${{ vars.TOKEN_MINTER_SERVICE_AUDIENCE }}' + id_token_include_email: true + + - id: 'mint-github-token' + uses: 'abcxyz/github-token-minter/.github/actions/minty@45c29ca3418ff3bb3ad5815d88a80536efeba21b' # ratchet:abcxyz/github-token-minter/.github/actions/minty@main + with: + id_token: '${{ steps.auth-minty.outputs.id_token }}' + service_url: '${{ vars.TOKEN_MINTER_SERVICE_URL }}' + requested_permissions: |- + { + "scope": "stale-bot", + "repositories": ["${{ matrix.repo }}"], + "org_name": "google-github-actions" + } + + - name: 'Run official stale bot' + uses: 'actions/stale@b5d41d4e1d5dceea10e7104786b73624c18a190f' # ratchet:actions/stale@v10.2.0 + env: + GITHUB_REPOSITORY: 'google-github-actions/${{ matrix.repo }}' + with: + repo-token: '${{ steps.mint-github-token.outputs.token }}' + operations-per-run: 300 # Increased burndown limit for first execution + + # Issue configuration (60 days total: 53 inactive + 7 warning) + days-before-issue-stale: 53 + days-before-issue-close: 7 + stale-issue-message: 'This issue has been automatically marked as stale because it has not had recent activity. It will be closed in 7 days if no further activity occurs.' + stale-issue-label: 'stale' + + # PR configuration (30 days total: 23 inactive + 7 warning) + days-before-pr-stale: 23 + days-before-pr-close: 7 + stale-pr-message: 'This pull request has been automatically marked as stale because it has not had recent activity. Please leave a comment to remove this status.' + stale-pr-label: 'stale' diff --git a/.github/workflows/draft-release.yml b/.github/workflows/draft-release.yml index 15c0797..26563ac 100644 --- a/.github/workflows/draft-release.yml +++ b/.github/workflows/draft-release.yml @@ -11,132 +11,80 @@ on: ACTIONS_BOT_TOKEN: required: true -env: - PR_BRANCH: 'actions/draft-release-${{ github.ref_name }}' +permissions: + contents: 'read' + pull-requests: 'write' + +defaults: + run: + shell: 'bash' jobs: draft-release: name: 'Draft Release' runs-on: 'ubuntu-latest' - permissions: - contents: 'write' steps: - - uses: 'actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11' # ratchet:actions/checkout@v4 + - name: 'Checkout' + uses: 'actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683' # ratchet:actions/checkout@v4 - - uses: 'actions/setup-node@60edb5dd545a775178f52524783378180af0d1f8' # ratchet:actions/setup-node@v4 + - name: 'Setup node' + uses: 'actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020' # ratchet:actions/setup-node@v4 with: - node-version: '22.x' + node-version: '24.x' - - name: 'Build and push' + - name: 'Build' + id: 'build' shell: 'bash' env: VERSION_STRATEGY: '${{ inputs.version_strategy }}' run: |- - # configure username and email for git to show who made the changes - git config user.name "google-github-actions-bot" - git config user.email "github-actions-bot@google.com" - - git checkout -b $PR_BRANCH - - npm version $VERSION_STRATEGY --git-tag-version=false - - NEW_VERSION=$(cat package.json | jq -r .version) - echo "NEW_VERSION=${NEW_VERSION}" >> $GITHUB_ENV + CURRENT_VERSION="$(jq -r .version ./package.json)" + echo "::debug::computed current version: ${CURRENT_VERSION}" + echo "current_version=${CURRENT_VERSION}" >> $GITHUB_OUTPUT + + npm version "${VERSION_STRATEGY}" \ + --no-git-tag-version \ + --no-commit-hooks \ + --no-workspaces-update + NEXT_VERSION="$(jq -r .version ./package.json)" + echo "::debug::computed next version: ${NEXT_VERSION}" + echo "next_version=${NEXT_VERSION}" >> $GITHUB_OUTPUT npm ci [[ "$(npm run --json | jq -r 'has("docs")')" == "true" ]] && npm run docs npm run build - git add . - git commit -m "Release: v${NEW_VERSION}" - git push origin $PR_BRANCH --force - - name: 'Generate release notes' + id: 'generate-release-notes' uses: 'actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea' # ratchet:actions/github-script@v7 + env: + CURRENT_VERSION: '${{ steps.build.outputs.current_version }}' + NEXT_VERSION: '${{ steps.build.outputs.next_version }}' with: + github-token: '${{ secrets.ACTIONS_BOT_TOKEN }}' script: |- - let previousTagName = ""; - + let releaseNotes = ''; try { - const latestRelease = await github.rest.repos.getLatestRelease({ + const releaseNotesResponse = await github.rest.repos.generateReleaseNotes({ owner: context.repo.owner, repo: context.repo.repo, + tag_name: `v${process.env.NEXT_VERSION}`, + previous_tag_name: `v${process.env.CURRENT_VERSION}`, }); - previousTagName = latestRelease.data.tag_name; - } catch (err) { - if (err["status"] !== 404) { - core.setFailed(`Failed to load latest release: ${err}`); - } - - core.info(`No existing releases found`); - } - - try { - const releaseNotesRequest = { - owner: context.repo.owner, - repo: context.repo.repo, - tag_name: context.sha, - target_commitish: context.sha, - }; - - if (previousTagName) { - releaseNotesRequest.previous_tag_name = previousTagName; - } - - const releaseNotes = await github.rest.repos.generateReleaseNotes( - releaseNotesRequest - ); - - core.exportVariable("RELEASE_NOTES", releaseNotes.data.body) - } catch (err) { - core.setFailed(`Failed to generate release notes: ${err}`); + releaseNotes = releaseNotesResponse.data.body; + } catch(err) { + core.debug(`error generating release notes: ${err}`) + core.warning('No existing releases found, assuming initial release'); + releaseNotes = 'Initial release' } + core.setOutput('release_notes', releaseNotes) - - name: 'Create Pull Request' - uses: 'actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea' # ratchet:actions/github-script@v7 + - name: 'Create/Update Pull Request' + uses: 'abcxyz/actions/.github/actions/create-pull-request@main' # ratchet:exclude with: - github-token: '${{ secrets.ACTIONS_BOT_TOKEN }}' - script: |- - const tag = "v" + process.env.NEW_VERSION; - - try { - const listResponse = await github.rest.pulls.list({ - owner: context.repo.owner, - repo: context.repo.repo, - state: "open", - head: context.repo.owner + ":" + process.env.PR_BRANCH, - base: process.env.GITHUB_REF_NAME, - }); - - core.isDebug() && console.log(listResponse); - - if (!listResponse.data.length) { - const createResponse = await github.rest.pulls.create({ - owner: context.repo.owner, - repo: context.repo.repo, - title: "Release: " + tag, - body: process.env.RELEASE_NOTES, - head: process.env.PR_BRANCH, - base: process.env.GITHUB_REF_NAME, - }); - - core.info( - `Created PR #${createResponse.data.number} at ${createResponse.data.html_url}` - ); - } else { - const updateResponse = await github.rest.pulls.update({ - owner: context.repo.owner, - repo: context.repo.repo, - pull_number: listResponse.data[0].number, - title: "Release: " + tag, - body: process.env.RELEASE_NOTES, - }); - - core.info( - `Updated PR #${updateResponse.data.number} at ${updateResponse.data.html_url}` - ); - } - } catch (err) { - console.error(err); - core.setFailed(`Failed to create pull request: ${err}`); - } + token: '${{ secrets.ACTIONS_BOT_TOKEN }}' + base_branch: '${{ github.ref_name }}' + head_branch: 'actions/draft-release-${{ github.ref_name }}' + title: 'Release: v${{ steps.build.outputs.next_version }}' + body: '${{ steps.generate-release-notes.outputs.release_notes }}' + compute_paths: true diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml new file mode 100644 index 0000000..fa12d5b --- /dev/null +++ b/.github/workflows/lint.yml @@ -0,0 +1,176 @@ +name: 'Lint' + +# NOTE: This workflow is NOT intended to be a reusable workflow via +# workflow_call. Instead it will be "reused" by configuring via organization +# rulesets as a required workflow. +on: + # Note that for org required workflows: + # "Any filters you specify for the supported events are ignored + # - for example, branches, branches-ignore, paths, types and so on." + # https://docs.github.com/en/enterprise-cloud@latest/repositories/configuring-branches-and-merges-in-your-repository/managing-rulesets/available-rules-for-rulesets#supported-event-triggers + pull_request: + merge_group: + +concurrency: + group: '${{ github.workflow }}-${{ github.head_ref || github.ref }}' + cancel-in-progress: true + +permissions: + contents: 'read' + statuses: 'write' + +defaults: + run: + shell: 'bash' + +jobs: + init: + name: 'Lint (Initialize)' + runs-on: 'ubuntu-latest' + if: | + ${{ github.repository != 'google-github-actions/.github' }} + outputs: + lint-targets: '${{ steps.lint-targets.outputs.lint-targets }}' + ratchet-files: '${{ steps.lint-targets.outputs.ratchet-files }}' + steps: + - name: 'Checkout' + uses: 'actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683' # ratchet:actions/checkout@v4 + with: + fetch-depth: 1 + ref: '${{ github.event.pull_request.head.sha }}' + + - name: 'Identify lint targets' + id: 'lint-targets' + env: + REF: '${{ github.event.pull_request.head.sha }}' + LC_ALL: 'C' + run: |- + set -euo pipefail + + find_files() { + local filepattern="${1}" + git ls-tree -r --name-only "${REF}" | grep -E "${filepattern}" | sort || true + } + + match_files() { + local filepattern="${1}" + matches="$(git ls-tree -r --name-only "${REF}" | grep -m 1 -E "${filepattern}")" + code="${?}" + if [[ -n "${matches}" ]]; then + # Ignore exit codes because we found a match. + # Exit code 141 and higher may occur because we exit early. + return 0 + fi + return "${code}" + } + + declare -a TARGETS=() + if match_files '.*(\.dockerfile|Dockerfile)$'; then + TARGETS+=("docker") + fi + if match_files '(action\.(yaml|yml))|(\.github/(actions|workflows)/.*\.(yaml|yml))$'; then + TARGETS+=("github" "ratchet") + RATCHET_FILES="$(find_files '(action\.(yaml|yml))|(\.github/(actions|workflows)/.*\.(yaml|yml))$' | tr '\n' ' ')" + echo "::debug::Found ratchetable files: ${RATCHET_FILES}" + echo "ratchet-files=${RATCHET_FILES}" >> "${GITHUB_OUTPUT}" + fi + if match_files 'go.mod$'; then + TARGETS+=("go") + fi + if match_files '.*\.(java)$'; then + TARGETS+=("java") + fi + if match_files 'package.json$'; then + TARGETS+=("javascript") + fi + if match_files '.*\.(sh)$'; then + TARGETS+=("shell") + fi + if match_files '.*\.(tf)$'; then + TARGETS+=("terraform") + fi + if match_files '.*\.(yaml|yml)$'; then + TARGETS+=("yaml") + fi + + LINT_TARGETS="$(jq --compact-output --null-input '$ARGS.positional' --args -- "${TARGETS[@]}")" + echo "::debug::Found lint targets: ${LINT_TARGETS}" + echo "lint-targets=${LINT_TARGETS}" >> "${GITHUB_OUTPUT}" + + lint: + runs-on: 'ubuntu-latest' + name: 'Lint (${{ matrix.lint-target }})' + needs: + - 'init' + if: |- + ${{ needs.init.outputs.lint-targets != '[]' && github.repository != 'google-github-actions/.github' }} + strategy: + fail-fast: false + max-parallel: 100 + matrix: + lint-target: '${{ fromJSON(needs.init.outputs.lint-targets) }}' + steps: + - name: 'Checkout' + uses: 'actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683' # ratchet:actions/checkout@v4 + with: + fetch-depth: 1 + + - name: 'Lint (Docker)' + if: |- + ${{ matrix.lint-target == 'docker' }} + uses: 'abcxyz/actions/.github/actions/lint-docker@main' # ratchet:exclude + with: + hadolint_config_url: 'https://raw.githubusercontent.com/abcxyz/actions/main/.hadolint.yml' + hadolint_version: '2.12.0' + + - name: 'Lint (GitHub Actions)' + if: |- + ${{ matrix.lint-target == 'github' }} + uses: 'abcxyz/actions/.github/actions/lint-github-actions@main' # ratchet:exclude + with: + actionlint_version: '1.7.7' + + - name: 'Lint (Go)' + if: |- + ${{ matrix.lint-target == 'go' }} + uses: 'abcxyz/actions/.github/actions/lint-go@main' # ratchet:exclude + with: + golangci_url: 'https://raw.githubusercontent.com/abcxyz/actions/main/default.golangci.yml' + + - name: 'Lint (Go modules)' + if: |- + ${{ matrix.lint-target == 'go' }} + uses: 'abcxyz/actions/.github/actions/lint-go-modules@main' # ratchet:exclude + + - name: 'Lint (Java)' + if: |- + ${{ matrix.lint-target == 'java' }} + uses: 'abcxyz/actions/.github/actions/lint-java@main' # ratchet:exclude + with: + google_java_format_version: '1.27.0' + github_token: '${{ secrets.GITHUB_TOKEN }}' + + - name: 'Lint (JavaScript)' + if: |- + ${{ matrix.lint-target == 'javascript' }} + uses: 'abcxyz/actions/.github/actions/lint-javascript@main' # ratchet:exclude + + - name: 'Lint (Ratchet)' + if: |- + ${{ matrix.lint-target == 'ratchet' }} + uses: 'sethvargo/ratchet@main' # ratchet:exclude + with: + files: '${{ needs.init.outputs.ratchet-files }}' + + - name: 'Lint (Shell)' + if: |- + ${{ matrix.lint-target == 'shell' }} + uses: 'abcxyz/actions/.github/actions/lint-shell@main' # ratchet:exclude + + - name: 'Lint (YAML)' + if: |- + ${{ matrix.lint-target == 'yaml' }} + uses: 'abcxyz/actions/.github/actions/lint-yaml@main' # ratchet:exclude + with: + yamllint_url: 'https://raw.githubusercontent.com/google-github-actions/.github/refs/heads/main/.yamllint.yml' + yamllint_version: '1.37.1' diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 49945b4..939dcc6 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -6,81 +6,63 @@ on: ACTIONS_BOT_TOKEN: required: true +permissions: + attestations: 'write' + contents: 'write' + packages: 'write' + +defaults: + run: + shell: 'bash' + jobs: - release: - name: 'Release' + create-release: + if: |- + ${{ startsWith(github.event.head_commit.message, 'Release: v') }} runs-on: 'ubuntu-latest' + outputs: + created: '${{ steps.create-release.outputs.created || false }}' + tag: '${{ steps.create-release.outputs.tag }}' + version: '${{ steps.create-release.outputs.version }}' steps: - - uses: 'actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11' # ratchet:actions/checkout@v4 - - - name: 'Get package version' - run: |- - echo "NEW_VERSION=$(cat package.json | jq -r .version)" >> $GITHUB_ENV - - - name: 'Get previous release tag' - uses: 'actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea' # ratchet:actions/github-script@v7 - with: - github-token: '${{ secrets.ACTIONS_BOT_TOKEN }}' - script: |- - try { - const latestRelease = await github.rest.repos.getLatestRelease({ - owner: context.repo.owner, - repo: context.repo.repo, - }); - core.exportVariable("PREV_TAG", latestRelease.data.tag_name); - } catch (err) { - if (err["status"] === 404) { - core.info(`No releases found`); - } else { - core.setFailed(`Failed to load latest release: ${err}`); - } - } - - name: 'Create release' - uses: 'actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea' # ratchet:actions/github-script@v7 + id: 'create-release' + uses: 'abcxyz/actions/.github/actions/create-release@main' # ratchet:exclude with: - github-token: '${{ secrets.ACTIONS_BOT_TOKEN }}' - script: |- - const tag = "v" + process.env.NEW_VERSION; + github_token: '${{ secrets.ACTIONS_BOT_TOKEN }}' + expected_email: '72759630+google-github-actions-bot@users.noreply.github.com' - try { - const createReleaseRequest = { - owner: context.repo.owner, - repo: context.repo.repo, - tag_name: tag, - target_commitish: context.sha, - name: tag, - generate_release_notes: true, - }; - - if (process.env.PREV_TAG) { - const releaseNotes = await github.rest.repos.generateReleaseNotes({ - owner: context.repo.owner, - repo: context.repo.repo, - tag_name: tag, - target_commitish: context.sha, - previous_tag_name: process.env.PREV_TAG, - }); - - createReleaseRequest.body = releaseNotes.data.body; - createReleaseRequest.generate_release_notes = false; - } - - const response = await github.rest.repos.createRelease(createReleaseRequest); - - core.info( - `Created release ${response.data.name} at ${response.data.html_url}` - ); - } catch (err) { - core.setFailed(`Failed to create release: ${err}`); - } + publish-release: + runs-on: 'ubuntu-latest' + needs: + - 'create-release' + steps: + - name: 'Publish release' + env: + GH_TOKEN: '${{ secrets.ACTIONS_BOT_TOKEN }}' + RELEASE_VERSION: 'v${{ needs.create-release.outputs.version }}' + REPO: '${{ github.repository }}' + run: |- + gh release edit "${RELEASE_VERSION}" \ + --repo "${REPO}" \ + --draft=false + update-floating-tag: + runs-on: 'ubuntu-latest' + needs: + - 'create-release' + steps: - name: 'Update floating tag' uses: 'actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea' # ratchet:actions/github-script@v7 + env: + RELEASE_VERSION: 'v${{ needs.create-release.outputs.version }}' + REPO: '${{ github.repository }}' with: + github-token: '${{ secrets.ACTIONS_BOT_TOKEN }}' script: |- - const tag = "v" + process.env.NEW_VERSION; + const tag = process.env.RELEASE_VERSION; const major = tag.split(".")[0]; + const githubActionsRef = `${process.env.REPO}@${major}` // Try to update the ref first. If that fails, it probably does not // exist yet, and we should create it. @@ -92,7 +74,7 @@ jobs: sha: context.sha, force: true, }); - core.info(`Updated ${major} to ${context.sha}`); + core.info(`Updated ${githubActionsRef} to ${context.sha} (${tag})`); } catch (err) { core.warning(`Failed to create tag ${major}: ${err}`); @@ -102,5 +84,23 @@ jobs: ref: "refs/tags/" + major, sha: context.sha, }); - core.info(`Created ${major} at ${context.sha}`); + core.info(`Created ${githubActionsRef} at ${context.sha} (${tag})`); } + + cleanup-failed-release: + if: |- + ${{ always() && needs.create-release.outputs.created == 'true' && contains(fromJSON('["failure", "cancelled", "skipped"]'), needs.publish-release.result) }} + runs-on: 'ubuntu-latest' + needs: + - 'create-release' + - 'publish-release' + steps: + - name: 'Cleanup failed release' + env: + GH_TOKEN: '${{ secrets.ACTIONS_BOT_TOKEN }}' + RELEASE_VERSION: 'v${{ needs.create-release.outputs.version }}' + REPO: '${{ github.repository }}' + run: |- + gh release delete "${RELEASE_VERSION}" \ + --repo "${REPO}" \ + --yes diff --git a/.github/workflows/scorecard.yml b/.github/workflows/scorecard.yml new file mode 100644 index 0000000..4baadd5 --- /dev/null +++ b/.github/workflows/scorecard.yml @@ -0,0 +1,29 @@ +name: 'Scorecard' +on: + pull_request: + workflow_dispatch: + +permissions: 'read-all' + +jobs: + analyze: + runs-on: 'ubuntu-latest' + permissions: + contents: 'read' + security-events: 'write' + id-token: 'write' + timeout-minutes: 20 + steps: + - uses: 'actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd' # ratchet:actions/checkout@v6 + with: + persist-credentials: false + - name: 'Run Scorecard' + uses: 'ossf/scorecard-action@4eaacf0543bb3f2c246792bd56e8cdeffafb205a' # ratchet:ossf/scorecard-action@v2.4.3 + with: + results_file: 'results.sarif' + results_format: 'sarif' + publish_results: false + - name: 'Upload to GitHub Security Tab' + uses: 'github/codeql-action/upload-sarif@c10b8064de6f491fea524254123dbe5e09572f13' # ratchet:github/codeql-action/upload-sarif@v4.35.1 + with: + sarif_file: 'results.sarif' diff --git a/.idea/.gitignore b/.idea/.gitignore new file mode 100644 index 0000000..b58b603 --- /dev/null +++ b/.idea/.gitignore @@ -0,0 +1,5 @@ +# Default ignored files +/shelf/ +/workspace.xml +# Editor-based HTTP Client requests +/httpRequests/ diff --git a/.yamllint.yml b/.yamllint.yml new file mode 100644 index 0000000..a4edf4a --- /dev/null +++ b/.yamllint.yml @@ -0,0 +1,89 @@ +rules: + anchors: + forbid-duplicated-anchors: true + forbid-undeclared-aliases: true + forbid-unused-anchors: true + + braces: + forbid: 'non-empty' + min-spaces-inside-empty: 0 + max-spaces-inside-empty: 0 + + brackets: + min-spaces-inside: 0 + max-spaces-inside: 0 + min-spaces-inside-empty: 0 + max-spaces-inside-empty: 0 + + colons: + max-spaces-before: 0 + max-spaces-after: 1 + + commas: + max-spaces-before: 0 + min-spaces-after: 1 + max-spaces-after: 1 + + comments: + require-starting-space: true + ignore-shebangs: true + min-spaces-from-content: 1 + + comments-indentation: {} + + document-end: + present: false + + document-start: + present: false + + empty-lines: + max: 2 + max-start: 0 + max-end: 1 + + empty-values: + forbid-in-block-mappings: false + forbid-in-flow-mappings: true + + float-values: + forbid-inf: false + forbid-nan: false + forbid-scientific-notation: false + require-numeral-before-decimal: false + + hyphens: + max-spaces-after: 1 + + indentation: + spaces: 2 + indent-sequences: true + check-multi-line-strings: false + + key-duplicates: {} + + new-line-at-end-of-file: {} + + new-lines: + type: 'unix' + + octal-values: + forbid-implicit-octal: true + forbid-explicit-octal: false + + quoted-strings: + quote-type: 'single' + required: true + allow-quoted-quotes: true + + trailing-spaces: {} + + truthy: + allowed-values: ['true', 'false', 'on'] # GitHub Actions uses "on" + check-keys: true + +ignore: + - 'node_modules/' + - 'thirdparty/' + - 'third_party/' + - 'vendor/'