Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .devcontainer/post-create.sh
Original file line number Diff line number Diff line change
Expand Up @@ -24,13 +24,13 @@ echo "Configuring pnpm store directory..."
pnpm config set store-dir /tmp/.pnpm-store

# Install the binary form of golangci-lint into the Go bin directory (on PATH in
# the dev container). Pinned version + checksums live in build/tools.mk.
# the dev container). Pinned version + checksums live in build/tools.yaml.
echo "Installing golangci-lint..."
GOLANGCI_LINT_INSTALL_DIR="$(go env GOPATH)/bin" make install-golangci-lint

# Install the binary form of shellcheck into the Go bin directory (on PATH in the
# dev container) so 'make lint-shell' works out of the box. Pinned version +
# checksums live in build/tools.mk.
# checksums live in build/tools.yaml.
echo "Installing shellcheck..."
SHELLCHECK_INSTALL_DIR="$(go env GOPATH)/bin" make install-shellcheck

Expand Down
2 changes: 1 addition & 1 deletion .github/actions/create-kind-cluster/action.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ runs:
using: composite
steps:
- name: Install KinD
# Installs the version pinned in build/tools.mk (KIND_VERSION) and adds the
# Installs the version pinned in build/tools.yaml (KIND_VERSION) and adds the
# install dir to the job PATH, so the cluster-create steps below find kind.
shell: bash
run: make install-kind
Expand Down
79 changes: 79 additions & 0 deletions .github/scripts/update-tools-pr.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
#!/bin/bash

# ------------------------------------------------------------
# Copyright 2026 The Radius Authors.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# ------------------------------------------------------------

set -euo pipefail

readonly REPO_ROOT="${REPO_ROOT:-$(git rev-parse --show-toplevel)}"
readonly PR_BASE="${PR_BASE:-main}"

require_environment() {
local name
for name in GH_TOKEN GIT_USER_EMAIL GIT_USER_NAME PR_BRANCH PR_TITLE; do
if [[ -z "${!name:-}" ]]; then
echo "Error: ${name} is required" >&2
return 1
fi
done
}

pull_request_body() {
cat <<'EOF'
This automated PR refreshes the pinned command-line tool versions and SHA-256
checksums from the release sources declared in `build/tools.yaml`.

`build/tools.generated.mk` is generated from the manifest and committed with
it. Bicep remains intentionally held at its compatibility-pinned version until
local `br:localhost` functional tests support a newer release.
EOF
}

# The workflow checks out only the base branch, so there is no remote-tracking
# ref to lease against. Read the destination SHA from the remote instead; an
# empty value leases on the branch not existing yet.
push_branch() {
local expected
expected="$(
git ls-remote origin "refs/heads/${PR_BRANCH}" | awk '{print $1}'
)"
git push --force-with-lease="refs/heads/${PR_BRANCH}:${expected}" \
origin "HEAD:${PR_BRANCH}"
}

require_environment
cd "${REPO_ROOT}"

git config user.name "${GIT_USER_NAME}"
git config user.email "${GIT_USER_EMAIL}"
git checkout -B "${PR_BRANCH}"
git add -A
git commit --signoff -m "${PR_TITLE}"
gh auth setup-git
push_branch

existing_pr="$(
gh pr list --state open --head "${PR_BRANCH}" \
--json number --jq '.[0].number'
)"
body="$(pull_request_body)"
if [[ -n "${existing_pr}" ]]; then
gh pr edit "${existing_pr}" --title "${PR_TITLE}" --body "${body}"
echo "Updated PR #${existing_pr}"
else
gh pr create --base "${PR_BASE}" --head "${PR_BRANCH}" \
--title "${PR_TITLE}" --body "${body}"
fi
121 changes: 121 additions & 0 deletions .github/scripts/update-tools-pr_test.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
#!/bin/bash

# ------------------------------------------------------------
# Copyright 2026 The Radius Authors.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# ------------------------------------------------------------

set -euo pipefail

SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
readonly SCRIPT_DIR
TEST_ROOT="$(mktemp -d)"
readonly TEST_ROOT
trap 'rm -rf "${TEST_ROOT}"' EXIT

fail() {
echo "FAIL: $*" >&2
exit 1
}

assert_contains() {
local actual="$1"
local expected="$2"
[[ "${actual}" == *"${expected}"* ]] ||
fail "expected '${actual}' to contain '${expected}'"
}

readonly REPOSITORY="${TEST_ROOT}/repository"
readonly REMOTE="${TEST_ROOT}/remote.git"
readonly SEED="${TEST_ROOT}/seed"
readonly FAKE_BIN="${TEST_ROOT}/bin"
readonly GH_LOG_PATH="${TEST_ROOT}/gh.log"

git init -q --bare "${REMOTE}"
git init -q -b main "${SEED}"
git -C "${SEED}" config user.name "Test User"
Comment thread
lakshmimsft marked this conversation as resolved.
git -C "${SEED}" config user.email "test@example.com"
# A contributor's global commit.gpgsign makes git commit block on a signing
# prompt. DCO --signoff is unrelated and still applies.
git -C "${SEED}" config commit.gpgsign false
echo "original" >"${SEED}/tools.yaml"
git -C "${SEED}" add tools.yaml
git -C "${SEED}" commit -q -m "initial"
git -C "${SEED}" remote add origin "${REMOTE}"
git -C "${SEED}" push -q origin main

# The workflow checks out the base branch only, so the automation branch never
# gains a remote-tracking ref. Mirror that here or the pushes below lease
# against a ref that CI does not have.
git clone -q --single-branch --branch main "${REMOTE}" "${REPOSITORY}"
# The script under test commits here, so it needs the same protection.
git -C "${REPOSITORY}" config commit.gpgsign false

mkdir -p "${FAKE_BIN}"
cat >"${FAKE_BIN}/gh" <<'EOF'
Comment thread
DariuszPorowski marked this conversation as resolved.
#!/bin/bash
set -euo pipefail
printf '%s\n' "$*" >>"${GH_LOG}"
if [[ "$1 $2" == "pr list" ]]; then
printf '%s\n' "${EXISTING_PR:-}"
fi
EOF
chmod +x "${FAKE_BIN}/gh"

run_script() {
local existing_pr="$1"
PATH="${FAKE_BIN}:${PATH}" \
REPO_ROOT="${REPOSITORY}" \
GH_LOG="${GH_LOG_PATH}" \
EXISTING_PR="${existing_pr}" \
GH_TOKEN="test-token" \
GIT_USER_EMAIL="automation@example.com" \
GIT_USER_NAME="Automation Bot" \
PR_BRANCH="automation/update-tools" \
PR_TITLE="chore: update pinned tool versions" \
bash "${SCRIPT_DIR}/update-tools-pr.sh" >/dev/null
}

echo "first update" >>"${REPOSITORY}/tools.yaml"
run_script ""

commit_message="$(
git --git-dir="${REMOTE}" log -1 --format=%B \
refs/heads/automation/update-tools
)"
assert_contains "${commit_message}" "chore: update pinned tool versions"
assert_contains \
"${commit_message}" \
"Signed-off-by: Automation Bot <automation@example.com>"
assert_contains "$(cat "${GH_LOG_PATH}")" "pr create"

if git -C "${REPOSITORY}" show-ref --quiet \
refs/remotes/origin/automation/update-tools; then
fail "fixture drifted from CI: the automation branch is now tracked"
fi

before="$(
git --git-dir="${REMOTE}" rev-parse refs/heads/automation/update-tools
)"
git -C "${REPOSITORY}" checkout -q main
echo "second update" >>"${REPOSITORY}/tools.yaml"
run_script "42"
after="$(
git --git-dir="${REMOTE}" rev-parse refs/heads/automation/update-tools
)"
assert_contains "$(cat "${GH_LOG_PATH}")" "pr edit 42"
[[ "${before}" != "${after}" ]] ||
fail "expected the remote automation branch to be updated"

echo "update-tools-pr tests passed"
4 changes: 2 additions & 2 deletions .github/workflows/build.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -159,7 +159,7 @@ jobs:

- name: Install oras
if: needs.changes.outputs.only_changed != 'true'
# Version pinned in build/tools.mk (ORAS_VERSION).
# Version pinned in build/tools.yaml (ORAS_VERSION).
run: make install-oras

- name: Push latest rad cli binary to GHCR (unix-like)
Expand Down Expand Up @@ -328,7 +328,7 @@ jobs:
persist-credentials: false

- name: Install helm
# Version pinned in build/tools.mk (HELM_VERSION).
# Version pinned in build/tools.yaml (HELM_VERSION).
run: make install-helm

- name: Setup Python
Expand Down
30 changes: 18 additions & 12 deletions .github/workflows/copilot-setup-steps.yml
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@
# functional-test-noncloud.yaml). Language runtime versions are read from the
# repo's version files (go.mod, .node-version, .python-version, .terraform-version)
# so a version bump flows here automatically; CLI tool versions and checksums are
# pinned in build/tools.mk and installed via the shared `make install-<tool>`
# pinned in build/tools.yaml and installed via the shared `make install-<tool>`
# targets. Versions are NOT declared in a workflow-level `env:`
# block because the Copilot coding agent replays these steps in a harness that
# does not provide that context.
Expand All @@ -41,15 +41,21 @@ on:
- .node-version
- .python-version
- .terraform-version
- build/tools.yaml
- build/tools.mk
- cmd/tool-updater/**
- internal/tooling/**
- build/scripts/install-*.sh
pull_request:
paths:
- .github/workflows/copilot-setup-steps.yml
- .node-version
- .python-version
- .terraform-version
- build/tools.yaml
- build/tools.mk
- cmd/tool-updater/**
- internal/tooling/**
- build/scripts/install-*.sh

permissions: {}
Expand All @@ -64,7 +70,7 @@ permissions: {}
# See: https://docs.github.com/en/copilot/how-tos/use-copilot-agents/coding-agent/customize-the-agent-environment
# Language runtime versions read from repo version files (go.mod, .node-version,
# .python-version, .terraform-version) still work because the steps read the files
# directly; CLI tool versions come from build/tools.mk via `make install-<tool>`.
# directly; CLI tool versions come from build/tools.yaml via `make install-<tool>`.

jobs:
# The job MUST be named `copilot-setup-steps` for the Copilot coding agent to
Expand Down Expand Up @@ -103,11 +109,11 @@ jobs:
python-version-file: .python-version

- name: Install helm
# Version pinned in build/tools.mk (HELM_VERSION).
# Version pinned in build/tools.yaml (HELM_VERSION).
run: make install-helm

- name: Install kubectl
# Version pinned in build/tools.mk (KUBECTL_VERSION).
# Version pinned in build/tools.yaml (KUBECTL_VERSION).
run: make install-kubectl

- name: Install pnpm and TypeSpec tooling
Expand Down Expand Up @@ -136,14 +142,14 @@ jobs:
cspell --version

- name: Install golangci-lint
# Pinned version + checksums live in build/tools.mk (GOLANGCI_LINT_VERSION).
# Pinned version + checksums live in build/tools.yaml (GOLANGCI_LINT_VERSION).
run: make install-golangci-lint

- name: Install Delve (dlv)
# controller-gen, mockgen, and gotestsum are managed as Go tool dependencies
# (the 'tool' directives in go.mod) and run via `go tool`, so they need no
# separate install. dlv (Delve) is used by the process-debugging workflow
# (make debug-*). Version pinned in build/tools.mk (DLV_VERSION).
# (make debug-*). Version pinned in build/tools.yaml (DLV_VERSION).
run: make install-dlv

- name: Install yq
Expand All @@ -152,31 +158,31 @@ jobs:

- name: Install KinD
# Lets the agent create a local Kubernetes cluster for integration and
# functional tests. Version pinned in build/tools.mk (KIND_VERSION).
# functional tests. Version pinned in build/tools.yaml (KIND_VERSION).
run: make install-kind

- name: Install k3d
# Used by the local debug environment (make debug-start) to create a
# lightweight Kubernetes cluster. Version pinned in build/tools.mk (K3D_VERSION).
# lightweight Kubernetes cluster. Version pinned in build/tools.yaml (K3D_VERSION).
run: make install-k3d

- name: Install stern
# Multi-pod log tailing for debugging Kubernetes output across the
# radius-system components. Version pinned in build/tools.mk (STERN_VERSION).
# radius-system components. Version pinned in build/tools.yaml (STERN_VERSION).
run: make install-stern

- name: Install Dapr CLI
# Version pinned in build/tools.mk (DAPR_VERSION).
# Version pinned in build/tools.yaml (DAPR_VERSION).
run: make install-dapr

- name: Install Terraform
# Version defaults to .terraform-version (overridable via TERRAFORM_VERSION)
# and is compiled into the rad binary; checksums pinned in build/tools.mk.
# and is compiled into the rad binary; checksums pinned in build/tools.yaml.
run: make install-terraform

- name: Install Bicep CLI
# Required by Bicep type publishing (make publish-bicep-extension) and
# rad bicep flows. Pinned version + checksum live in build/tools.mk.
# rad bicep flows. Pinned version + checksum live in build/tools.yaml.
run: make install-bicep

- name: Install PostgreSQL client
Expand Down
6 changes: 3 additions & 3 deletions .github/workflows/functional-test-cloud.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -507,7 +507,7 @@ jobs:
make generate-bicep-types VERSION="${BICEP_TYPES_VERSION}"

- name: Install bicep CLI
# Pinned version + checksum live in build/tools.mk (previously installed
# Pinned version + checksum live in build/tools.yaml (previously installed
# the unpinned 'latest', which could pull v0.43+).
run: make install-bicep

Expand Down Expand Up @@ -745,7 +745,7 @@ jobs:
AZURE_SUBSCRIPTIONID_TESTS: ${{ secrets.AZURE_SUBSCRIPTIONID_TESTS }}

- name: Install helm
# Version pinned in build/tools.mk (HELM_VERSION).
# Version pinned in build/tools.yaml (HELM_VERSION).
run: make install-helm

# The role-to-assume is the role that the github action will assume to execute aws commands and
Expand All @@ -758,7 +758,7 @@ jobs:
aws-region: ${{ env.AWS_REGION }}

- name: Install KinD
# Installs the version pinned in build/tools.mk (KIND_VERSION) and adds
# Installs the version pinned in build/tools.yaml (KIND_VERSION) and adds
# the install dir to the job PATH for the cluster-create step below.
run: make install-kind

Expand Down
Loading
Loading