diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 817ee6bc..685b47aa 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -124,7 +124,7 @@ jobs: - name: Install Cross if: matrix.cross run: | - cargo install cross + cargo install --locked "cross@0.2.5" echo "CARGO=cross" >> $GITHUB_ENV - name: Add Target diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 0eff0eab..1daf7d8f 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -62,10 +62,10 @@ jobs: rustflags: "" - name: Install cargo-quickinstall - run: cargo install cargo-quickinstall + run: cargo install --locked "cargo-quickinstall@0.3.53" - name: Install cargo-edit - run: cargo quickinstall --force cargo-edit + run: cargo quickinstall --force "cargo-edit@0.13.13" - name: Update version in Cargo.toml id: update-version diff --git a/.github/workflows/update-themes.yml b/.github/workflows/update-themes.yml index 9ed167c1..913a5043 100644 --- a/.github/workflows/update-themes.yml +++ b/.github/workflows/update-themes.yml @@ -62,7 +62,7 @@ jobs: - name: Install cargo-edit if: steps.update-themes.outputs.updated == 'true' - run: cargo install cargo-edit + run: cargo install --locked "cargo-edit@0.13.13" - name: Update version in Cargo.toml if: steps.update-themes.outputs.updated == 'true' diff --git a/.github/workflows/update-tools.yml b/.github/workflows/update-tools.yml new file mode 100644 index 00000000..f5db0311 --- /dev/null +++ b/.github/workflows/update-tools.yml @@ -0,0 +1,128 @@ +name: Update pinned tool versions + +on: + schedule: + - cron: "00 05 * * MON" # Every Monday at 05:00 UTC + workflow_dispatch: + +permissions: + contents: write + pull-requests: write + actions: write + +defaults: + run: + shell: bash -euo pipefail {0} + +jobs: + update-tools: + name: Update pinned tool versions + runs-on: ubuntu-latest + steps: + - name: Generate GitHub App Token + id: generate-token + uses: actions/create-github-app-token@bcd2ba49218906704ab6c1aa796996da409d3eb1 # v3.2.0 + with: + app-id: ${{ secrets.APP_ID }} + private-key: ${{ secrets.APP_PRIVATE_KEY }} + owner: ${{ github.repository_owner }} + repositories: ${{ github.event.repository.name }} + + - name: Generate Auto-Merge GitHub App Token + id: generate-automerge-token + uses: actions/create-github-app-token@bcd2ba49218906704ab6c1aa796996da409d3eb1 # v3.2.0 + with: + app-id: ${{ secrets.AUTOMERGE_APP_ID }} + private-key: ${{ secrets.AUTOMERGE_APP_PRIVATE_KEY }} + owner: ${{ github.repository_owner }} + repositories: ${{ github.event.repository.name }} + + - name: Checkout repository + uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 + with: + token: ${{ steps.generate-token.outputs.token }} + + - name: Check for tool updates + id: check-updates + run: | + updates="" + summary="" + + check_crate() { + local crate="$1" + local current="$2" + local latest + latest=$(curl -sf -H "User-Agent: ${GITHUB_REPOSITORY} CI (https://github.com/${GITHUB_REPOSITORY})" "https://crates.io/api/v1/crates/${crate}" | jq -r '.crate.max_stable_version') + if [ -z "${latest}" ] || [ "${latest}" = "null" ]; then + echo "::warning::Failed to fetch latest version for ${crate}" + return + fi + if [ "${current}" != "${latest}" ]; then + updates="${updates}${crate}:${current}:${latest}\n" + summary="${summary}- ${crate}: ${current} → ${latest}\n" + fi + } + + # Extract pinned versions from workflow files + declare -A tool_versions + + while IFS= read -r line; do + if [[ "${line}" =~ \"([a-z0-9_-]+)@([0-9]+\.[0-9]+\.[0-9]+)\" ]]; then + crate="${BASH_REMATCH[1]}" + version="${BASH_REMATCH[2]}" + tool_versions["${crate}"]="${version}" + fi + done < <(grep -rh '"[a-z0-9_-]*@[0-9]' .github/workflows/ | grep -v 'uses:') + + for crate in "${!tool_versions[@]}"; do + check_crate "${crate}" "${tool_versions[${crate}]}" + done + + if [ -n "${updates}" ]; then + echo "has-updates=true" >> "${GITHUB_OUTPUT}" + { + echo 'summary<> "${GITHUB_OUTPUT}" + echo -e "${summary}" > /tmp/update-summary.txt + echo -e "${updates}" > /tmp/updates.txt + else + echo "has-updates=false" >> "${GITHUB_OUTPUT}" + fi + + - name: Apply updates + if: steps.check-updates.outputs.has-updates == 'true' + run: | + while IFS=: read -r crate current latest; do + [ -z "${crate}" ] && continue + echo "Updating ${crate}: ${current} → ${latest}" + find .github/workflows/ -name '*.yml' -exec \ + sed -i "s|\"${crate}@${current}\"|\"${crate}@${latest}\"|g" {} + + done < /tmp/updates.txt + + - name: Create pull request + if: steps.check-updates.outputs.has-updates == 'true' + id: create-pr + uses: peter-evans/create-pull-request@5f6978faf089d4d20b00c7766989d076bb2fc7f1 # v8.1.1 + with: + token: ${{ steps.generate-token.outputs.token }} + commit-message: | + build(deps): update pinned tool versions + + ${{ steps.check-updates.outputs.summary }} + branch: update-tools-${{ github.run_number }}-${{ github.run_id }} + title: "build(deps): update pinned tool versions" + body-path: /tmp/update-summary.txt + author: "missionis[bot] <234988995+missionis[bot]@users.noreply.github.com>" + committer: "missionis[bot] <234988995+missionis[bot]@users.noreply.github.com>" + labels: | + dependencies + delete-branch: true + + - name: Enable auto-merge + if: steps.create-pr.outputs.pull-request-number + run: | + gh pr merge --auto -ds ${{ steps.create-pr.outputs.pull-request-number }} + env: + GH_TOKEN: ${{ steps.generate-automerge-token.outputs.token }} diff --git a/contrib/bin/setup.sh b/contrib/bin/setup.sh index a033aad1..eb3347c9 100755 --- a/contrib/bin/setup.sh +++ b/contrib/bin/setup.sh @@ -75,8 +75,10 @@ setup_cargo_binstall() { true elif [ -x "$(command -v scoop)" ]; then scoop install cargo-binstall + elif [ -x "$(command -v curl)" ]; then + curl -L --proto '=https' --tlsv1.2 -sSf https://raw.githubusercontent.com/cargo-bins/cargo-binstall/main/install-from-binstall-release.sh | bash elif [ -x "$(command -v cargo)" ]; then - cargo install cargo-binstall + cargo install --locked cargo-binstall else echo "Please install cargo-binstall" exit 1