From 7e6bbd17878a610657945058f31aa39dd2fcb51f Mon Sep 17 00:00:00 2001 From: aeneasr <3372410+aeneasr@users.noreply.github.com> Date: Tue, 11 Aug 2026 12:47:29 +0200 Subject: [PATCH 1/2] fix: harden credentialed shared actions --- .github/workflows/docs-cli-next.yml | 185 ++++++++++++++++++++++++++++ .github/workflows/test.yml | 42 ++++++- checkout/action.yml | 5 +- newsletter/action.yml | 46 +++++-- newsletter/slack-notify/action.yml | 3 +- releaser/action.yml | 133 +++++++++++--------- 6 files changed, 333 insertions(+), 81 deletions(-) create mode 100644 .github/workflows/docs-cli-next.yml diff --git a/.github/workflows/docs-cli-next.yml b/.github/workflows/docs-cli-next.yml new file mode 100644 index 0000000..ba2af9e --- /dev/null +++ b/.github/workflows/docs-cli-next.yml @@ -0,0 +1,185 @@ +name: Build and publish CLI docs + +on: + workflow_call: + inputs: + output-dir: + description: Directory in ory/docs that receives the generated Markdown. + required: true + type: string + docs-branch: + description: Branch in ory/docs to update. + required: false + default: master + type: string + arg: + description: Optional arguments passed to the CLI documentation generator. + required: false + default: "" + type: string + secrets: + token: + description: Token used only to push the generated documentation. + required: true + +permissions: {} + +jobs: + generate: + name: Generate CLI docs + runs-on: ubuntu-latest + permissions: + contents: read + steps: + - name: Validate output directory + env: + OUTPUT_DIR: ${{ inputs.output-dir }} + run: | + set -euo pipefail + [[ "$OUTPUT_DIR" =~ ^[A-Za-z0-9._/-]+$ ]] + [[ "$OUTPUT_DIR" != /* ]] + [[ "$OUTPUT_DIR" != -* ]] + [[ "/$OUTPUT_DIR/" != *"/../"* ]] + [[ "/$OUTPUT_DIR/" != *"/./"* ]] + [[ "$OUTPUT_DIR" != *"//"* ]] + - name: Checkout source repository + uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7 + with: + path: current-repo + fetch-depth: 0 + persist-credentials: false + - name: Checkout documentation repository + uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7 + with: + repository: ory/docs + ref: ${{ inputs.docs-branch }} + path: docs + persist-credentials: false + - uses: actions/setup-go@924ae3a1cded613372ab5595356fb5720e22ba16 # v6 + with: + check-latest: true + go-version-file: current-repo/go.mod + - uses: actions/setup-node@249970729cb0ef3589644e2896645e5dc5ba9c38 # v6 + with: + node-version: "24" + - name: Generate CLI docs + working-directory: current-repo + env: + CLI_DOC_ARG: ${{ inputs.arg }} + OUTPUT_DIR: ${{ inputs.output-dir }} + run: | + set -euo pipefail + args=() + if [[ -n "$CLI_DOC_ARG" ]]; then + read -r -a args <<< "$CLI_DOC_ARG" + fi + make .bin/clidoc + .bin/clidoc "${args[@]}" "../docs/${OUTPUT_DIR}" + - name: Format generated docs + working-directory: docs + env: + OUTPUT_DIR: ${{ inputs.output-dir }} + run: | + set -euo pipefail + mkdir -p node_modules/ory-prettier-styles + tarball=$(npm pack ory-prettier-styles@1.3.0 --silent) + tar -xf "$tarball" -C node_modules/ory-prettier-styles --strip-components=1 + npm install --global prettier@3.2.5 + rm "$tarball" + npx --no-install prettier --write "$OUTPUT_DIR" + - name: Validate generated docs + env: + OUTPUT_DIR: ${{ inputs.output-dir }} + run: | + set -euo pipefail + generated="docs/${OUTPUT_DIR}" + if find "$generated" -type l | grep -q .; then + echo "generated documentation contains symlinks" >&2 + exit 1 + fi + if find "$generated" -type f ! -name '*.md' | grep -q .; then + echo "generated documentation contains non-Markdown files" >&2 + exit 1 + fi + test -n "$(find "$generated" -type f -name '*.md' -print -quit)" + - uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7 + with: + name: cli-docs + path: docs/${{ inputs.output-dir }} + if-no-files-found: error + retention-days: 1 + + publish: + name: Publish CLI docs + if: ${{ github.ref_name == 'master' || github.ref_type == 'tag' }} + needs: + - generate + runs-on: ubuntu-latest + permissions: {} + steps: + - name: Checkout documentation repository + uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7 + with: + repository: ory/docs + ref: ${{ inputs.docs-branch }} + path: docs + fetch-depth: 0 + persist-credentials: false + - uses: actions/download-artifact@37930b1c2abaa49bbe596cd826c3c89aef350131 # v7 + with: + name: cli-docs + path: generated + - name: Validate generated docs + env: + OUTPUT_DIR: ${{ inputs.output-dir }} + run: | + set -euo pipefail + [[ "$OUTPUT_DIR" =~ ^[A-Za-z0-9._/-]+$ ]] + [[ "$OUTPUT_DIR" != /* ]] + [[ "$OUTPUT_DIR" != -* ]] + [[ "/$OUTPUT_DIR/" != *"/../"* ]] + [[ "/$OUTPUT_DIR/" != *"/./"* ]] + [[ "$OUTPUT_DIR" != *"//"* ]] + if find generated -type l | grep -q .; then + echo "generated documentation contains symlinks" >&2 + exit 1 + fi + if find generated -type f ! -name '*.md' | grep -q .; then + echo "generated documentation contains non-Markdown files" >&2 + exit 1 + fi + test -n "$(find generated -type f -name '*.md' -print -quit)" + - name: Commit generated docs + id: commit + working-directory: docs + env: + DOCS_BRANCH: ${{ inputs.docs-branch }} + OUTPUT_DIR: ${{ inputs.output-dir }} + run: | + set -euo pipefail + rm -rf -- "$OUTPUT_DIR" + mkdir -p -- "$OUTPUT_DIR" + cp -R ../generated/. "$OUTPUT_DIR/" + if [[ -z "$(git status --porcelain -- "$OUTPUT_DIR")" ]]; then + echo "Nothing to commit" + exit 0 + fi + + git config --local user.email "60093411+ory-bot@users.noreply.github.com" + git config --local user.name "ory-bot" + git add -- "$OUTPUT_DIR" + git stash + git pull --rebase origin "$DOCS_BRANCH" + git stash apply + git add -- "$OUTPUT_DIR" + git commit -m "autogen(docs): generate cli docs" + echo "changed=true" >> "$GITHUB_OUTPUT" + - name: Push generated docs + if: ${{ steps.commit.outputs.changed == 'true' }} + working-directory: docs + env: + DOCS_BRANCH: ${{ inputs.docs-branch }} + DOCS_TOKEN: ${{ secrets.token }} + run: | + git push "https://x-access-token:${DOCS_TOKEN}@github.com/ory/docs.git" \ + "HEAD:${DOCS_BRANCH}" diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index b83f2c3..e79ad59 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -7,18 +7,56 @@ on: - reopened push: +permissions: + contents: read + jobs: test: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7 + with: + persist-credentials: false - id: cache-node - uses: actions/cache@v4 + uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4 with: path: conventional_commit_config/node_modules key: ${{ runner.os }}-cococo-node-${{ hashFiles('conventional_commit_config/package-lock.json') }} + - name: Check immutable action dependencies + shell: bash + run: | + set -euo pipefail + files=( + checkout/action.yml + releaser/action.yml + newsletter/action.yml + newsletter/slack-notify/action.yml + .github/workflows/docs-cli-next.yml + ) + failed=0 + while IFS=: read -r file line contents; do + [[ "$contents" =~ uses:[[:space:]]+([^[:space:]#]+) ]] || continue + target=${BASH_REMATCH[1]} + if [[ "$target" == ./* ]]; then + continue + elif [[ "$target" == docker://* ]]; then + if [[ ! "$target" =~ @sha256:[0-9a-f]{64}$ ]]; then + echo "${file}:${line}: ${target} must use an OCI digest" >&2 + failed=1 + fi + elif [[ ! "$target" =~ @[0-9a-f]{40}$ ]]; then + echo "${file}:${line}: ${target} must use a full commit SHA" >&2 + failed=1 + fi + done < <(grep -nHE '^[[:space:]]*(-[[:space:]]+)?uses:' "${files[@]}") + if grep -nE \ + 'raw\.githubusercontent\.com/.+/(master|main)/|oryd/xgoreleaser:latest' \ + "${files[@]}"; then + failed=1 + fi + exit "$failed" - run: cd authors && make test - run: cd conventional_commit_config && make test - run: cd changelog && make test diff --git a/checkout/action.yml b/checkout/action.yml index 2c1115e..b8c7710 100644 --- a/checkout/action.yml +++ b/checkout/action.yml @@ -74,7 +74,7 @@ runs: using: "composite" steps: - if: ${{ github.event_name == 'pull_request' }} - uses: actions/checkout@v2 + uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7 with: repository: ${{ inputs.repository }} ref: ${{ github.event.pull_request.head.sha }} @@ -89,7 +89,7 @@ runs: lfs: ${{ inputs.lfs }} submodules: ${{ inputs.submodules }} - if: ${{ github.event_name != 'pull_request' }} - uses: actions/checkout@v2 + uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7 with: repository: ${{ inputs.repository }} ref: ${{ inputs.ref }} @@ -104,4 +104,3 @@ runs: lfs: ${{ inputs.lfs }} submodules: ${{ inputs.submodules }} - diff --git a/newsletter/action.yml b/newsletter/action.yml index 7568e54..08d94ab 100644 --- a/newsletter/action.yml +++ b/newsletter/action.yml @@ -17,38 +17,58 @@ inputs: default: 'true' ssh_key: description: SSH private key used to fetch the repository - required: true + required: false runs: using: "composite" steps: - - uses: ory/ci/checkout@master - - run: | - git fetch origin +refs/tags/*:refs/tags/* + - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7 + with: + fetch-depth: 0 + persist-credentials: false + - name: Install the Ory CLI shell: bash - - env: + run: | + set -euo pipefail + version=1.3.1 + archive="ory_${version}-linux_sqlite_64bit.tar.gz" + checksum=ef416258ed224ebe32e84b04f1b58bff2406eb2032b254d78a7045e808b427a2 + workdir=$(mktemp -d) + trap 'rm -rf "${workdir}"' EXIT + + curl --fail --silent --show-error --location --retry 7 \ + --output "${workdir}/${archive}" \ + "https://github.com/ory/cli/releases/download/v${version}/${archive}" + echo "${checksum} ${workdir}/${archive}" | sha256sum --check --strict + tar --no-same-owner -xzf "${workdir}/${archive}" -C "${workdir}" ory + install -m 0755 "${workdir}/ory" ./ory + ./ory version + - if: ${{ inputs.ssh_key != '' }} + env: + SSH_KEY: ${{ inputs.ssh_key }} SSH_AUTH_SOCK: /tmp/ssh_agent.sock run: | + set -euo pipefail mkdir -p /home/runner/.ssh ssh-keyscan github.com >> /home/runner/.ssh/known_hosts - echo "${{ inputs.ssh_key }}" > /home/runner/.ssh/github_actions + echo "${SSH_KEY}" > /home/runner/.ssh/github_actions chmod 600 /home/runner/.ssh/github_actions - ssh-agent -a $SSH_AUTH_SOCK > /dev/null + ssh-agent -a "$SSH_AUTH_SOCK" > /dev/null ssh-add /home/runner/.ssh/github_actions git config --global core.sshCommand "ssh -i /home/runner/.ssh/github_actions" shell: bash - - env: + - name: Draft or send the newsletter + env: + DRAFT: ${{ inputs.draft }} MAILCHIMP_LIST_ID: ${{ inputs.mailchimp_list_id }} MAILCHIMP_SEGMENT_ID: ${{ inputs.mailchmip_segment_id }} MAILCHIMP_API_KEY: ${{ inputs.mailchimp_api_key }} - SSH_AUTH_SOCK: /tmp/ssh_agent.sock run: | - git fetch origin +refs/tags/*:refs/tags/* - bash <(curl https://raw.githubusercontent.com/ory/meta/master/install.sh) -b . ory - if [[ "${{ inputs.draft }}" == "false" ]]; then + set -euo pipefail + if [[ "${DRAFT}" == "false" ]]; then # production run ./ory dev release notify send "${MAILCHIMP_LIST_ID}" - elif [[ "${{ inputs.draft }}" == "true" ]]; then + elif [[ "${DRAFT}" == "true" ]]; then # draft run ./ory dev release notify draft --segment "${MAILCHIMP_SEGMENT_ID}" "${MAILCHIMP_LIST_ID}" ./ory dev release notify send --dry "${MAILCHIMP_LIST_ID}" diff --git a/newsletter/slack-notify/action.yml b/newsletter/slack-notify/action.yml index 791c38f..98c3d3b 100644 --- a/newsletter/slack-notify/action.yml +++ b/newsletter/slack-notify/action.yml @@ -8,7 +8,7 @@ inputs: runs: using: "composite" steps: - - uses: slackapi/slack-github-action@v1.16.0 + - uses: slackapi/slack-github-action@410ae57cff5c6b682b106440be0e6c7eb8c98c9d # v1.16.0 with: payload: | { @@ -35,4 +35,3 @@ runs: env: SLACK_WEBHOOK_URL: ${{ inputs.slack-webhook-url }} SLACK_WEBHOOK_TYPE: INCOMING_WEBHOOK - diff --git a/releaser/action.yml b/releaser/action.yml index 41a3156..a700bea 100644 --- a/releaser/action.yml +++ b/releaser/action.yml @@ -22,37 +22,37 @@ runs: using: "composite" steps: - name: Free Disk Space (Ubuntu) - uses: jlumbroso/free-disk-space@main + uses: jlumbroso/free-disk-space@54081f138730dfa15788a46383842cd2f914a1be # main@2025-07-31 with: - # this might remove tools that are actually needed, - # if set to "true" but frees about 6 GB tool-cache: false - - # all of these default to true, but feel free to set to - # "false" if necessary for your workflow android: true dotnet: true haskell: true large-packages: true docker-images: true swap-storage: true - - uses: ory/ci/checkout@master + - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7 with: token: ${{ inputs.token }} fetch-depth: 0 - - uses: actions/setup-node@v6 + persist-credentials: false + - uses: actions/setup-node@249970729cb0ef3589644e2896645e5dc5ba9c38 # v6 with: - node-version: "16" - - uses: actions/setup-go@v6 + node-version: "24" + - uses: actions/setup-go@924ae3a1cded613372ab5595356fb5720e22ba16 # v6 with: go-version: "1.25" - - run: | + - name: Configure the release author + run: | git config --global user.email "60093411+ory-bot@users.noreply.github.com" git config --global user.name "ory-bot" shell: bash - - run: echo 'GOPATH='"$(go env GOPATH)" >> $GITHUB_ENV + - name: Configure Go environment + run: echo 'GOPATH='"$(go env GOPATH)" >> "$GITHUB_ENV" shell: bash - - run: | + - name: Prepare release-note paths + run: | + set -euo pipefail if [[ ! -e package.json ]]; then echo '{"private": true, "version": "0.0.0"}' > package.json git add package.json @@ -60,31 +60,24 @@ runs: echo "package.json exists and needs not be written" fi - echo 'notes='"$(mktemp).md" >> $GITHUB_ENV - shell: bash - - name: Install moreutils (for sponge) + echo "notes=${RUNNER_TEMP}/release-notes.md" >> "$GITHUB_ENV" shell: bash - run: | - sudo apt install -y moreutils - - uses: actions/checkout@v5 + - name: Checkout changelog renderer + uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7 with: repository: ory/changelog + ref: a084a3aeb57e581ad46f61f14f03889ece64d2f8 # master@2025-10-22 path: changelog - token: ${{ inputs.token }} - - - env: + persist-credentials: false + - name: Render release notes + env: CURRENT_TAG: ${{ github.ref_name }} run: | + set -euo pipefail npm --no-git-tag-version version "$CURRENT_TAG" - - ( - cd "$GITHUB_WORKSPACE/changelog"; - npm i - ) - - git fetch origin +refs/tags/*:refs/tags/* - - npx conventional-changelog-cli@v2.1.1 --config "changelog/index.js" -r 2 -o "$notes" + (cd "$GITHUB_WORKSPACE/changelog" && npm ci) + npx --yes conventional-changelog-cli@2.1.1 \ + --config "changelog/index.js" -r 2 -o "$notes" if [[ "$OSTYPE" == "darwin"* ]]; then sed -i '' '/^# /d' "$notes" @@ -94,13 +87,13 @@ runs: sed -i '/^[[:space:]]*GitOrigin-RevId:/ {N; d;}' "$notes" fi - npx prettier -w "$notes" + npx --yes prettier@3.8.2 --write "$notes" git reset --hard HEAD shell: bash - - - uses: docker/setup-qemu-action@v3 - - uses: docker/setup-buildx-action@v3 - - env: + - uses: docker/setup-qemu-action@96fe6ef7f33517b61c61be40b68a1882f3264fb8 # v4 + - uses: docker/setup-buildx-action@bb05f3f5519dd87d3ba754cc423b652a5edd6d2c # v4 + - name: Build, sign, and publish the release + env: GORELEASER_CURRENT_TAG: ${{ github.ref_name }} GORELEASER_KEY: ${{ inputs.goreleaser_key }} GITHUB_TOKEN: ${{ inputs.token }} @@ -108,53 +101,71 @@ runs: DOCKER_USERNAME: ${{ inputs.docker_username }} DOCKER_PASSWORD: ${{ inputs.docker_password }} run: | + set -euo pipefail cat "$notes" - # clean up ory/changelog checkout rm -rf changelog - docker pull --platform linux/amd64 oryd/xgoreleaser:latest - docker run --privileged --mount type=bind,source="$(pwd)",target=/project \ - --mount type=bind,source="$notes",target=/notes.md \ - --platform linux/amd64 \ - -e GORELEASER_KEY \ - -e GITHUB_TOKEN \ - -e COSIGN_PWD \ - -e DOCKER_USERNAME \ - -e DOCKER_PASSWORD \ - -e GORELEASER_CURRENT_TAG \ - -v /var/run/docker.sock:/var/run/docker.sock \ - oryd/xgoreleaser:latest release --release-header "/notes.md" --clean --timeout 60m - + docker run --privileged \ + --mount type=bind,source="$(pwd)",target=/project \ + --mount type=bind,source="$notes",target=/notes.md \ + --platform linux/amd64 \ + -e GORELEASER_KEY \ + -e GITHUB_TOKEN \ + -e COSIGN_PWD \ + -e DOCKER_USERNAME \ + -e DOCKER_PASSWORD \ + -e GORELEASER_CURRENT_TAG \ + -v /var/run/docker.sock:/var/run/docker.sock \ + oryd/xgoreleaser:1.26.0-2.14.1@sha256:635fdea1104f933c13298228601ceeda725eb7ce3ed3c1757aae712f44bdd773 \ + release --release-header "/notes.md" --clean --timeout 60m + shell: bash + - name: Commit release artifacts + env: + ORY_BOT_PAT: ${{ inputs.token }} + run: | git add -A git stash || true git checkout master || true git stash pop || true git commit -a -m "autogen: update release artifacts" -m "[skip ci]" || true - git pull origin master --rebase || true + git pull "https://x-access-token:${ORY_BOT_PAT}@github.com/${GITHUB_REPOSITORY}.git" \ + master --rebase || true if [[ "$GITHUB_REF_TYPE" == "branch" ]]; then - git push origin "${GITHUB_HEAD_REF:-$GITHUB_REF_NAME}" || true + git push "https://x-access-token:${ORY_BOT_PAT}@github.com/${GITHUB_REPOSITORY}.git" \ + "${GITHUB_HEAD_REF:-$GITHUB_REF_NAME}" || true fi shell: bash - - run: | + - name: Configure documentation version + run: | docs_version="$(echo "$GITHUB_REF_NAME" | awk -F'.' '{ printf("%s.%s", $1, $2) }')" - echo 'DOCS_VERSION='"$docs_version" >> $GITHUB_ENV + echo "DOCS_VERSION=${docs_version}" >> "$GITHUB_ENV" shell: bash - - run: | + - name: Run post-release tasks + id: post_release + env: + DOCKER_TAG: ${{ github.ref_name }} + run: | + set -euo pipefail if [[ $(git describe --tags) == *"pre"* ]]; then echo "This is a pre-release, skipping docs publishing." exit 0 fi make post-release - + echo "publish=true" >> "$GITHUB_OUTPUT" + shell: bash + - name: Commit post-release artifacts + if: ${{ steps.post_release.outputs.publish == 'true' }} + env: + ORY_BOT_PAT: ${{ inputs.token }} + run: | git add -A git stash || true git checkout master || true - git pull -ff || true + git pull "https://x-access-token:${ORY_BOT_PAT}@github.com/${GITHUB_REPOSITORY}.git" \ + master --ff-only || true git stash pop || true git commit --allow-empty -a -m "autogen(docs): generate and bump docs" -m "[skip ci]" || true - git push origin HEAD:master || true - env: - GITHUB_TOKEN: ${{ inputs.token }} - DOCKER_TAG: ${{ github.ref_name }} + git push "https://x-access-token:${ORY_BOT_PAT}@github.com/${GITHUB_REPOSITORY}.git" \ + HEAD:master || true shell: bash From 255d0b3362c842330a6c14787d037bebe9517d00 Mon Sep 17 00:00:00 2001 From: aeneasr <3372410+aeneasr@users.noreply.github.com> Date: Thu, 13 Aug 2026 08:05:17 +0200 Subject: [PATCH 2/2] fix: preserve shared action compatibility --- .github/workflows/docs-cli-next.yml | 185 ---------------------------- .github/workflows/test.yml | 40 +----- checkout/action.yml | 4 +- newsletter/action.yml | 46 ++----- releaser/action.yml | 130 +++++++++---------- 5 files changed, 76 insertions(+), 329 deletions(-) delete mode 100644 .github/workflows/docs-cli-next.yml diff --git a/.github/workflows/docs-cli-next.yml b/.github/workflows/docs-cli-next.yml deleted file mode 100644 index ba2af9e..0000000 --- a/.github/workflows/docs-cli-next.yml +++ /dev/null @@ -1,185 +0,0 @@ -name: Build and publish CLI docs - -on: - workflow_call: - inputs: - output-dir: - description: Directory in ory/docs that receives the generated Markdown. - required: true - type: string - docs-branch: - description: Branch in ory/docs to update. - required: false - default: master - type: string - arg: - description: Optional arguments passed to the CLI documentation generator. - required: false - default: "" - type: string - secrets: - token: - description: Token used only to push the generated documentation. - required: true - -permissions: {} - -jobs: - generate: - name: Generate CLI docs - runs-on: ubuntu-latest - permissions: - contents: read - steps: - - name: Validate output directory - env: - OUTPUT_DIR: ${{ inputs.output-dir }} - run: | - set -euo pipefail - [[ "$OUTPUT_DIR" =~ ^[A-Za-z0-9._/-]+$ ]] - [[ "$OUTPUT_DIR" != /* ]] - [[ "$OUTPUT_DIR" != -* ]] - [[ "/$OUTPUT_DIR/" != *"/../"* ]] - [[ "/$OUTPUT_DIR/" != *"/./"* ]] - [[ "$OUTPUT_DIR" != *"//"* ]] - - name: Checkout source repository - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7 - with: - path: current-repo - fetch-depth: 0 - persist-credentials: false - - name: Checkout documentation repository - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7 - with: - repository: ory/docs - ref: ${{ inputs.docs-branch }} - path: docs - persist-credentials: false - - uses: actions/setup-go@924ae3a1cded613372ab5595356fb5720e22ba16 # v6 - with: - check-latest: true - go-version-file: current-repo/go.mod - - uses: actions/setup-node@249970729cb0ef3589644e2896645e5dc5ba9c38 # v6 - with: - node-version: "24" - - name: Generate CLI docs - working-directory: current-repo - env: - CLI_DOC_ARG: ${{ inputs.arg }} - OUTPUT_DIR: ${{ inputs.output-dir }} - run: | - set -euo pipefail - args=() - if [[ -n "$CLI_DOC_ARG" ]]; then - read -r -a args <<< "$CLI_DOC_ARG" - fi - make .bin/clidoc - .bin/clidoc "${args[@]}" "../docs/${OUTPUT_DIR}" - - name: Format generated docs - working-directory: docs - env: - OUTPUT_DIR: ${{ inputs.output-dir }} - run: | - set -euo pipefail - mkdir -p node_modules/ory-prettier-styles - tarball=$(npm pack ory-prettier-styles@1.3.0 --silent) - tar -xf "$tarball" -C node_modules/ory-prettier-styles --strip-components=1 - npm install --global prettier@3.2.5 - rm "$tarball" - npx --no-install prettier --write "$OUTPUT_DIR" - - name: Validate generated docs - env: - OUTPUT_DIR: ${{ inputs.output-dir }} - run: | - set -euo pipefail - generated="docs/${OUTPUT_DIR}" - if find "$generated" -type l | grep -q .; then - echo "generated documentation contains symlinks" >&2 - exit 1 - fi - if find "$generated" -type f ! -name '*.md' | grep -q .; then - echo "generated documentation contains non-Markdown files" >&2 - exit 1 - fi - test -n "$(find "$generated" -type f -name '*.md' -print -quit)" - - uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7 - with: - name: cli-docs - path: docs/${{ inputs.output-dir }} - if-no-files-found: error - retention-days: 1 - - publish: - name: Publish CLI docs - if: ${{ github.ref_name == 'master' || github.ref_type == 'tag' }} - needs: - - generate - runs-on: ubuntu-latest - permissions: {} - steps: - - name: Checkout documentation repository - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7 - with: - repository: ory/docs - ref: ${{ inputs.docs-branch }} - path: docs - fetch-depth: 0 - persist-credentials: false - - uses: actions/download-artifact@37930b1c2abaa49bbe596cd826c3c89aef350131 # v7 - with: - name: cli-docs - path: generated - - name: Validate generated docs - env: - OUTPUT_DIR: ${{ inputs.output-dir }} - run: | - set -euo pipefail - [[ "$OUTPUT_DIR" =~ ^[A-Za-z0-9._/-]+$ ]] - [[ "$OUTPUT_DIR" != /* ]] - [[ "$OUTPUT_DIR" != -* ]] - [[ "/$OUTPUT_DIR/" != *"/../"* ]] - [[ "/$OUTPUT_DIR/" != *"/./"* ]] - [[ "$OUTPUT_DIR" != *"//"* ]] - if find generated -type l | grep -q .; then - echo "generated documentation contains symlinks" >&2 - exit 1 - fi - if find generated -type f ! -name '*.md' | grep -q .; then - echo "generated documentation contains non-Markdown files" >&2 - exit 1 - fi - test -n "$(find generated -type f -name '*.md' -print -quit)" - - name: Commit generated docs - id: commit - working-directory: docs - env: - DOCS_BRANCH: ${{ inputs.docs-branch }} - OUTPUT_DIR: ${{ inputs.output-dir }} - run: | - set -euo pipefail - rm -rf -- "$OUTPUT_DIR" - mkdir -p -- "$OUTPUT_DIR" - cp -R ../generated/. "$OUTPUT_DIR/" - if [[ -z "$(git status --porcelain -- "$OUTPUT_DIR")" ]]; then - echo "Nothing to commit" - exit 0 - fi - - git config --local user.email "60093411+ory-bot@users.noreply.github.com" - git config --local user.name "ory-bot" - git add -- "$OUTPUT_DIR" - git stash - git pull --rebase origin "$DOCS_BRANCH" - git stash apply - git add -- "$OUTPUT_DIR" - git commit -m "autogen(docs): generate cli docs" - echo "changed=true" >> "$GITHUB_OUTPUT" - - name: Push generated docs - if: ${{ steps.commit.outputs.changed == 'true' }} - working-directory: docs - env: - DOCS_BRANCH: ${{ inputs.docs-branch }} - DOCS_TOKEN: ${{ secrets.token }} - run: | - git push "https://x-access-token:${DOCS_TOKEN}@github.com/ory/docs.git" \ - "HEAD:${DOCS_BRANCH}" diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index e79ad59..71cd345 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -7,16 +7,11 @@ on: - reopened push: -permissions: - contents: read - jobs: test: runs-on: ubuntu-latest steps: - - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7 - with: - persist-credentials: false + - uses: actions/checkout@a37ce9120846195fa4ece8f58b268e6043cb2f26 # v3 - id: cache-node uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4 with: @@ -24,39 +19,6 @@ jobs: key: ${{ runner.os }}-cococo-node-${{ hashFiles('conventional_commit_config/package-lock.json') }} - - name: Check immutable action dependencies - shell: bash - run: | - set -euo pipefail - files=( - checkout/action.yml - releaser/action.yml - newsletter/action.yml - newsletter/slack-notify/action.yml - .github/workflows/docs-cli-next.yml - ) - failed=0 - while IFS=: read -r file line contents; do - [[ "$contents" =~ uses:[[:space:]]+([^[:space:]#]+) ]] || continue - target=${BASH_REMATCH[1]} - if [[ "$target" == ./* ]]; then - continue - elif [[ "$target" == docker://* ]]; then - if [[ ! "$target" =~ @sha256:[0-9a-f]{64}$ ]]; then - echo "${file}:${line}: ${target} must use an OCI digest" >&2 - failed=1 - fi - elif [[ ! "$target" =~ @[0-9a-f]{40}$ ]]; then - echo "${file}:${line}: ${target} must use a full commit SHA" >&2 - failed=1 - fi - done < <(grep -nHE '^[[:space:]]*(-[[:space:]]+)?uses:' "${files[@]}") - if grep -nE \ - 'raw\.githubusercontent\.com/.+/(master|main)/|oryd/xgoreleaser:latest' \ - "${files[@]}"; then - failed=1 - fi - exit "$failed" - run: cd authors && make test - run: cd conventional_commit_config && make test - run: cd changelog && make test diff --git a/checkout/action.yml b/checkout/action.yml index b8c7710..e91e476 100644 --- a/checkout/action.yml +++ b/checkout/action.yml @@ -74,7 +74,7 @@ runs: using: "composite" steps: - if: ${{ github.event_name == 'pull_request' }} - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7 + uses: actions/checkout@0717577d45739eb3c851188b29f50ed6c0b2194e # v2 with: repository: ${{ inputs.repository }} ref: ${{ github.event.pull_request.head.sha }} @@ -89,7 +89,7 @@ runs: lfs: ${{ inputs.lfs }} submodules: ${{ inputs.submodules }} - if: ${{ github.event_name != 'pull_request' }} - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7 + uses: actions/checkout@0717577d45739eb3c851188b29f50ed6c0b2194e # v2 with: repository: ${{ inputs.repository }} ref: ${{ inputs.ref }} diff --git a/newsletter/action.yml b/newsletter/action.yml index 08d94ab..b953841 100644 --- a/newsletter/action.yml +++ b/newsletter/action.yml @@ -17,58 +17,38 @@ inputs: default: 'true' ssh_key: description: SSH private key used to fetch the repository - required: false + required: true runs: using: "composite" steps: - - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7 - with: - fetch-depth: 0 - persist-credentials: false - - name: Install the Ory CLI + - uses: ory/ci/checkout@53206fb2760d6580b0e3fa4e4d7547f5d7a0c109 # master + - run: | + git fetch origin +refs/tags/*:refs/tags/* shell: bash - run: | - set -euo pipefail - version=1.3.1 - archive="ory_${version}-linux_sqlite_64bit.tar.gz" - checksum=ef416258ed224ebe32e84b04f1b58bff2406eb2032b254d78a7045e808b427a2 - workdir=$(mktemp -d) - trap 'rm -rf "${workdir}"' EXIT - - curl --fail --silent --show-error --location --retry 7 \ - --output "${workdir}/${archive}" \ - "https://github.com/ory/cli/releases/download/v${version}/${archive}" - echo "${checksum} ${workdir}/${archive}" | sha256sum --check --strict - tar --no-same-owner -xzf "${workdir}/${archive}" -C "${workdir}" ory - install -m 0755 "${workdir}/ory" ./ory - ./ory version - - if: ${{ inputs.ssh_key != '' }} - env: - SSH_KEY: ${{ inputs.ssh_key }} + - env: SSH_AUTH_SOCK: /tmp/ssh_agent.sock run: | - set -euo pipefail mkdir -p /home/runner/.ssh ssh-keyscan github.com >> /home/runner/.ssh/known_hosts - echo "${SSH_KEY}" > /home/runner/.ssh/github_actions + echo "${{ inputs.ssh_key }}" > /home/runner/.ssh/github_actions chmod 600 /home/runner/.ssh/github_actions - ssh-agent -a "$SSH_AUTH_SOCK" > /dev/null + ssh-agent -a $SSH_AUTH_SOCK > /dev/null ssh-add /home/runner/.ssh/github_actions git config --global core.sshCommand "ssh -i /home/runner/.ssh/github_actions" shell: bash - - name: Draft or send the newsletter - env: - DRAFT: ${{ inputs.draft }} + - env: MAILCHIMP_LIST_ID: ${{ inputs.mailchimp_list_id }} MAILCHIMP_SEGMENT_ID: ${{ inputs.mailchmip_segment_id }} MAILCHIMP_API_KEY: ${{ inputs.mailchimp_api_key }} + SSH_AUTH_SOCK: /tmp/ssh_agent.sock run: | - set -euo pipefail - if [[ "${DRAFT}" == "false" ]]; then + git fetch origin +refs/tags/*:refs/tags/* + bash <(curl https://raw.githubusercontent.com/ory/meta/fe7e8f7035692eca99f919f7a99e103fc03f29eb/install.sh) -b . ory + if [[ "${{ inputs.draft }}" == "false" ]]; then # production run ./ory dev release notify send "${MAILCHIMP_LIST_ID}" - elif [[ "${DRAFT}" == "true" ]]; then + elif [[ "${{ inputs.draft }}" == "true" ]]; then # draft run ./ory dev release notify draft --segment "${MAILCHIMP_SEGMENT_ID}" "${MAILCHIMP_LIST_ID}" ./ory dev release notify send --dry "${MAILCHIMP_LIST_ID}" diff --git a/releaser/action.yml b/releaser/action.yml index a700bea..b3cf36e 100644 --- a/releaser/action.yml +++ b/releaser/action.yml @@ -22,37 +22,37 @@ runs: using: "composite" steps: - name: Free Disk Space (Ubuntu) - uses: jlumbroso/free-disk-space@54081f138730dfa15788a46383842cd2f914a1be # main@2025-07-31 + uses: jlumbroso/free-disk-space@54081f138730dfa15788a46383842cd2f914a1be # main with: + # this might remove tools that are actually needed, + # if set to "true" but frees about 6 GB tool-cache: false + + # all of these default to true, but feel free to set to + # "false" if necessary for your workflow android: true dotnet: true haskell: true large-packages: true docker-images: true swap-storage: true - - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7 + - uses: ory/ci/checkout@53206fb2760d6580b0e3fa4e4d7547f5d7a0c109 # master with: token: ${{ inputs.token }} fetch-depth: 0 - persist-credentials: false - uses: actions/setup-node@249970729cb0ef3589644e2896645e5dc5ba9c38 # v6 with: - node-version: "24" + node-version: "16" - uses: actions/setup-go@924ae3a1cded613372ab5595356fb5720e22ba16 # v6 with: go-version: "1.25" - - name: Configure the release author - run: | + - run: | git config --global user.email "60093411+ory-bot@users.noreply.github.com" git config --global user.name "ory-bot" shell: bash - - name: Configure Go environment - run: echo 'GOPATH='"$(go env GOPATH)" >> "$GITHUB_ENV" + - run: echo 'GOPATH='"$(go env GOPATH)" >> $GITHUB_ENV shell: bash - - name: Prepare release-note paths - run: | - set -euo pipefail + - run: | if [[ ! -e package.json ]]; then echo '{"private": true, "version": "0.0.0"}' > package.json git add package.json @@ -60,24 +60,32 @@ runs: echo "package.json exists and needs not be written" fi - echo "notes=${RUNNER_TEMP}/release-notes.md" >> "$GITHUB_ENV" + echo 'notes='"$(mktemp).md" >> $GITHUB_ENV + shell: bash + - name: Install moreutils (for sponge) shell: bash - - name: Checkout changelog renderer - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7 + run: | + sudo apt install -y moreutils + - uses: actions/checkout@fbc6f3992d24b796d5a048ff273f7fcc4a7b6c09 # v5 with: repository: ory/changelog - ref: a084a3aeb57e581ad46f61f14f03889ece64d2f8 # master@2025-10-22 + ref: a084a3aeb57e581ad46f61f14f03889ece64d2f8 # master path: changelog - persist-credentials: false - - name: Render release notes - env: + token: ${{ inputs.token }} + + - env: CURRENT_TAG: ${{ github.ref_name }} run: | - set -euo pipefail npm --no-git-tag-version version "$CURRENT_TAG" - (cd "$GITHUB_WORKSPACE/changelog" && npm ci) - npx --yes conventional-changelog-cli@2.1.1 \ - --config "changelog/index.js" -r 2 -o "$notes" + + ( + cd "$GITHUB_WORKSPACE/changelog"; + npm i + ) + + git fetch origin +refs/tags/*:refs/tags/* + + npx conventional-changelog-cli@v2.1.1 --config "changelog/index.js" -r 2 -o "$notes" if [[ "$OSTYPE" == "darwin"* ]]; then sed -i '' '/^# /d' "$notes" @@ -87,13 +95,13 @@ runs: sed -i '/^[[:space:]]*GitOrigin-RevId:/ {N; d;}' "$notes" fi - npx --yes prettier@3.8.2 --write "$notes" + npx prettier -w "$notes" git reset --hard HEAD shell: bash - - uses: docker/setup-qemu-action@96fe6ef7f33517b61c61be40b68a1882f3264fb8 # v4 - - uses: docker/setup-buildx-action@bb05f3f5519dd87d3ba754cc423b652a5edd6d2c # v4 - - name: Build, sign, and publish the release - env: + + - uses: docker/setup-qemu-action@c7c53464625b32c7a7e944ae62b3e17d2b600130 # v3 + - uses: docker/setup-buildx-action@8d2750c68a42422c14e847fe6c8ac0403b4cbd6f # v3 + - env: GORELEASER_CURRENT_TAG: ${{ github.ref_name }} GORELEASER_KEY: ${{ inputs.goreleaser_key }} GITHUB_TOKEN: ${{ inputs.token }} @@ -101,71 +109,53 @@ runs: DOCKER_USERNAME: ${{ inputs.docker_username }} DOCKER_PASSWORD: ${{ inputs.docker_password }} run: | - set -euo pipefail cat "$notes" + # clean up ory/changelog checkout rm -rf changelog - docker run --privileged \ - --mount type=bind,source="$(pwd)",target=/project \ - --mount type=bind,source="$notes",target=/notes.md \ - --platform linux/amd64 \ - -e GORELEASER_KEY \ - -e GITHUB_TOKEN \ - -e COSIGN_PWD \ - -e DOCKER_USERNAME \ - -e DOCKER_PASSWORD \ - -e GORELEASER_CURRENT_TAG \ - -v /var/run/docker.sock:/var/run/docker.sock \ - oryd/xgoreleaser:1.26.0-2.14.1@sha256:635fdea1104f933c13298228601ceeda725eb7ce3ed3c1757aae712f44bdd773 \ - release --release-header "/notes.md" --clean --timeout 60m - shell: bash - - name: Commit release artifacts - env: - ORY_BOT_PAT: ${{ inputs.token }} - run: | + docker pull --platform linux/amd64 oryd/xgoreleaser:1.26.0-2.14.1@sha256:635fdea1104f933c13298228601ceeda725eb7ce3ed3c1757aae712f44bdd773 + docker run --privileged --mount type=bind,source="$(pwd)",target=/project \ + --mount type=bind,source="$notes",target=/notes.md \ + --platform linux/amd64 \ + -e GORELEASER_KEY \ + -e GITHUB_TOKEN \ + -e COSIGN_PWD \ + -e DOCKER_USERNAME \ + -e DOCKER_PASSWORD \ + -e GORELEASER_CURRENT_TAG \ + -v /var/run/docker.sock:/var/run/docker.sock \ + oryd/xgoreleaser:1.26.0-2.14.1@sha256:635fdea1104f933c13298228601ceeda725eb7ce3ed3c1757aae712f44bdd773 release --release-header "/notes.md" --clean --timeout 60m + git add -A git stash || true git checkout master || true git stash pop || true git commit -a -m "autogen: update release artifacts" -m "[skip ci]" || true - git pull "https://x-access-token:${ORY_BOT_PAT}@github.com/${GITHUB_REPOSITORY}.git" \ - master --rebase || true + git pull origin master --rebase || true if [[ "$GITHUB_REF_TYPE" == "branch" ]]; then - git push "https://x-access-token:${ORY_BOT_PAT}@github.com/${GITHUB_REPOSITORY}.git" \ - "${GITHUB_HEAD_REF:-$GITHUB_REF_NAME}" || true + git push origin "${GITHUB_HEAD_REF:-$GITHUB_REF_NAME}" || true fi shell: bash - - name: Configure documentation version - run: | + - run: | docs_version="$(echo "$GITHUB_REF_NAME" | awk -F'.' '{ printf("%s.%s", $1, $2) }')" - echo "DOCS_VERSION=${docs_version}" >> "$GITHUB_ENV" + echo 'DOCS_VERSION='"$docs_version" >> $GITHUB_ENV shell: bash - - name: Run post-release tasks - id: post_release - env: - DOCKER_TAG: ${{ github.ref_name }} - run: | - set -euo pipefail + - run: | if [[ $(git describe --tags) == *"pre"* ]]; then echo "This is a pre-release, skipping docs publishing." exit 0 fi make post-release - echo "publish=true" >> "$GITHUB_OUTPUT" - shell: bash - - name: Commit post-release artifacts - if: ${{ steps.post_release.outputs.publish == 'true' }} - env: - ORY_BOT_PAT: ${{ inputs.token }} - run: | + git add -A git stash || true git checkout master || true - git pull "https://x-access-token:${ORY_BOT_PAT}@github.com/${GITHUB_REPOSITORY}.git" \ - master --ff-only || true + git pull -ff || true git stash pop || true git commit --allow-empty -a -m "autogen(docs): generate and bump docs" -m "[skip ci]" || true - git push "https://x-access-token:${ORY_BOT_PAT}@github.com/${GITHUB_REPOSITORY}.git" \ - HEAD:master || true + git push origin HEAD:master || true + env: + GITHUB_TOKEN: ${{ inputs.token }} + DOCKER_TAG: ${{ github.ref_name }} shell: bash