From 17289c52df9c495cb033c20a836c7f0130e343f6 Mon Sep 17 00:00:00 2001 From: "giantswarm-align-files[bot]" <288255335+giantswarm-align-files[bot]@users.noreply.github.com> Date: Wed, 11 Nov 2026 22:13:33 +0000 Subject: [PATCH] chore: align files according to platform standards --- .cursor/rules/zz_generated.base-llm-rules.mdc | 52 --------- .../zz_generated.add-to-project-board.yaml | 100 +++++++++++++++++- AGENTS.md | 38 +++++++ Makefile.gen.app.mk | 18 +++- 4 files changed, 148 insertions(+), 60 deletions(-) delete mode 100644 .cursor/rules/zz_generated.base-llm-rules.mdc create mode 100644 AGENTS.md diff --git a/.cursor/rules/zz_generated.base-llm-rules.mdc b/.cursor/rules/zz_generated.base-llm-rules.mdc deleted file mode 100644 index 4b7ae429..00000000 --- a/.cursor/rules/zz_generated.base-llm-rules.mdc +++ /dev/null @@ -1,52 +0,0 @@ ---- -description: Instructions for AI/LLM assistants -alwaysApply: true ---- - -# Instructions for AI/LLM assistants - -You are an AI assistant acting as an expert software developer and platform engineer working on Giant Swarm platform components. Your task is to act as a pair programmer and help others working in this codebase to keep the code delightful to work with. This includes ensuring that the code adheres to Giant Swarm's quality standards, keeping the project well-architected and organized, and maintaining supporting documentation, diagrams, and rules for other AI assistants. - -# Persona: Senior Giant Swarm Platform Engineer - -- **Technical Depth**: You are a domain expert in Go (formerly, golang), Helm, Kubernetes APIs and development, software design patterns, software architecture, Go application security, software testing, and software performance optimization, -- **Problem-Solver**: You approach issues methodically, prioritizing safety and stability. You first investigate deeply with the tools provided to you, before suggesting changes. You find and fix the root cause, not the symptoms. -- **Clear Communicator**: You explain complex topics clearly and provide actionable steps. -- **Collaborative**: You guide users, suggest diagnostic paths, and help them think through problems. -- **Best Practices**: You adhere to Giant Swarm operational and technical standards. - -# Reviewer Guidelines - -## Core Behaviors - -- Unless directed by the user, never use or recommend external linters, code analysis, or other tooling which isn't already recommended in Giant Swarm agent rules or style guides. -- Always adhere to the central coding guidelines and best practices maintained at: @https://github.com/giantswarm/fmt/ -- Prioritize readability, maintainability, and security. -- Write comprehensive tests and documentation. -- If documentation is available in the `docs` folder, keep this up-to-date when changing code. -- Maintain the main README.md file for correctness. -- If a changelog is available as CHANGELOG.md, add your changes to it, unless the repository has `.github/workflows/zz_generated.auto_release.yaml`: there GitHub Releases are the changelog, written from the pull request titles, and CHANGELOG.md only points at them, so a pull request does not edit it. - -## Release Management - -- Follow the changelog and release guidelines from @https://github.com/giantswarm/fmt/tree/main/releases -- Use semantic versioning and conventional commits - - -## Language-Specific Guidelines - -Additional language-specific rules can be found in the general style guide and in the other rules files in this repository. - - - ---- - -For detailed guidelines and examples, always refer to: @https://github.com/giantswarm/fmt/ - - - diff --git a/.github/workflows/zz_generated.add-to-project-board.yaml b/.github/workflows/zz_generated.add-to-project-board.yaml index 4e49a8ab..74d76721 100644 --- a/.github/workflows/zz_generated.add-to-project-board.yaml +++ b/.github/workflows/zz_generated.add-to-project-board.yaml @@ -121,19 +121,113 @@ jobs: permission-issues: read permission-organization-projects: write - name: Add issue to team board + id: add-to-board if: ${{ env.BOARD != 'null' && env.BOARD != '' && env.BOARD != null }} uses: actions/add-to-project@f2c1f1fa649a891be84948ea89b5dfba1526ef05 # v2.0.1 with: project-url: ${{ env.BOARD }} github-token: ${{ steps.app-token.outputs.token }} + # The roadmap board's Team field is a single select whose options carry + # emoji ("Honey Badger 🦡"); a label matches the option with the same + # letters, so team/honeybadger and team/honey-badger both match. + - name: Set the roadmap Team field from the team label + if: >- + steps.add-to-board.outputs.itemId != '' && + env.BOARD == 'https://github.com/orgs/giantswarm/projects/273' && + startsWith(github.event.label.name, 'team/') && + github.event.label.name != 'team/null' + env: + GH_TOKEN: ${{ steps.app-token.outputs.token }} + ITEM_ID: ${{ steps.add-to-board.outputs.itemId }} + LABEL: ${{ github.event.label.name }} + run: | + set -euo pipefail + team=$(printf '%s' "${LABEL#team/}" | tr -cd '[:alpha:]' | tr '[:upper:]' '[:lower:]') + read -r project field option < <(gh api graphql -F number=273 -f query=' + query($number: Int!) { + organization(login: "giantswarm") { + projectV2(number: $number) { + id + field(name: "Team") { ... on ProjectV2SingleSelectField { id options { id name } } } + } + } + }' | jq -r --arg team "$team" '.data.organization.projectV2 as $p + | ($p.field.options[] | select((.name | ascii_downcase | gsub("[^a-z]"; "")) == $team) | .id) as $o + | [$p.id, $p.field.id, $o] | @tsv') || true + if [ -z "${option:-}" ]; then + echo "::warning::No roadmap Team option matches ${LABEL}" + exit 0 + fi + gh api graphql -f project="$project" -f item="$ITEM_ID" -f field="$field" -f option="$option" -f query=' + mutation($project: ID!, $item: ID!, $field: ID!, $option: String!) { + updateProjectV2ItemFieldValue(input: {projectId: $project, itemId: $item, fieldId: $field, value: {singleSelectOptionId: $option}}) { + projectV2Item { id } + } + }' > /dev/null + echo "Team set from ${LABEL}" + + # The repository's owning team is the single team of the CODEOWNERS default + # rule, which align-files writes from the team file that declares it. Its + # label, added as the App, fires `labeled`, and add_to_team_board puts the + # issue on the team's board. An issue opened with a team label keeps it. + add_owner_team_label: + name: Add the owning team's label to a new issue + runs-on: ubuntu-latest + if: >- + github.event.action == 'opened' && + !contains(join(github.event.issue.labels.*.name, ' '), 'team/') + permissions: + contents: read + outputs: + team: ${{ steps.owner.outputs.team }} + steps: + - name: Find the owning team in CODEOWNERS + id: owner + env: + GH_TOKEN: ${{ github.token }} + run: | + set -euo pipefail + codeowners="" + for path in .github/CODEOWNERS CODEOWNERS docs/CODEOWNERS; do + if codeowners=$(gh api -H "Accept: application/vnd.github.raw" "repos/${GITHUB_REPOSITORY}/contents/${path}" 2>/dev/null); then + break + fi + codeowners="" + done + # The last matching rule wins, as GitHub reads CODEOWNERS. + rule=$(printf '%s\n' "$codeowners" | sed 's/#.*//' | awk '$1 == "*"' | tail -n 1) + teams=$(printf '%s\n' "$rule" | grep -oE '@giantswarm/team-[a-z0-9-]+' | sed 's|@giantswarm/team-||' | sort -u || true) + if [ "$(printf '%s' "$teams" | grep -c .)" = 1 ]; then + echo "Owning team: ${teams}" + echo "team=${teams}" >> "$GITHUB_OUTPUT" + else + echo "No single owning team in CODEOWNERS" + fi + - name: Mint App token for the label + id: app-token + if: steps.owner.outputs.team != '' + uses: actions/create-github-app-token@64ab729a6294000f5aa4a4bc0b73d1f32bc45510 # v3.3.0 + with: + client-id: ${{ secrets.PROJECT_AUTOMATION_CLIENT_ID }} + private-key: ${{ secrets.PROJECT_AUTOMATION_PRIVATE_KEY }} + permission-issues: write + - name: Apply the owning team's label + if: steps.owner.outputs.team != '' + env: + GH_TOKEN: ${{ steps.app-token.outputs.token }} + LABEL: team/${{ steps.owner.outputs.team }} + ISSUE: ${{ github.event.issue.number }} + run: gh api "repos/${GITHUB_REPOSITORY}/issues/${ISSUE}/labels" -f "labels[]=${LABEL}" > /dev/null - # An issue opened with a label or an assignee also fires `labeled` or - # `assigned`, which add it above; only a bare one is added here. + # A repository without a single owning team: a bare issue still reaches the + # roadmap board's inbox. An issue opened with a label or an assignee also + # fires `labeled` or `assigned`, which add it above. add_unlabelled_to_roadmap_board: name: Add unlabelled, unassigned issue to roadmap board runs-on: ubuntu-latest + needs: add_owner_team_label if: >- - github.event.action == 'opened' && + needs.add_owner_team_label.outputs.team == '' && join(github.event.issue.labels.*.name, '') == '' && join(github.event.issue.assignees.*.login, '') == '' steps: diff --git a/AGENTS.md b/AGENTS.md new file mode 100644 index 00000000..ec31fc14 --- /dev/null +++ b/AGENTS.md @@ -0,0 +1,38 @@ + + + +## Giant Swarm conventions + +devctl maintains this block from [its template][devctl-agents-block] and +overwrites changes to it. Instructions for this repository go in the section +below. Where they differ from this block, they take precedence. + +[devctl-agents-block]: https://github.com/giantswarm/devctl/blob/main/pkg/gen/input/llm/internal/file/agents_block.md.template + +- Never put customer names or other customer information in code, commit + messages, issues or pull requests. Most Giant Swarm repositories are public, + and private ones are kept ready to become public. +- Giant Swarm's style guides are in , one + directory per topic (go, helm, kubernetes, prometheus, …). Read the relevant + guide before you write or review that kind of code. +- Use conventional commits for commit messages and pull request titles. +- If `.github/workflows/zz_generated.auto_release.yaml` exists, GitHub Releases + are written from pull request titles: do not edit CHANGELOG.md. Otherwise, + add your change to CHANGELOG.md as described in + . +- If `.pre-commit-config.yaml` exists, run + `pre-commit run --files ` before committing; not every clone + has the hooks installed. +- Do not add linters, formatters or other tooling unless asked; use what the + repository already has. +- Put documentation in `docs/` rather than growing README.md, which gives an + overview and links into `docs/`. When a change affects documented behaviour, + update the documentation in the same pull request. +- If the skills of the `giantswarm/claude-code` plugin marketplace are not + available to you and the user works at Giant Swarm, tell them once that + they can install the `gs-base`, `gs-dev` and `gs-appdev` + plugins from it. + + + +## This repository diff --git a/Makefile.gen.app.mk b/Makefile.gen.app.mk index 313f0e8d..fa82f5c0 100644 --- a/Makefile.gen.app.mk +++ b/Makefile.gen.app.mk @@ -2,7 +2,7 @@ # # devctl # -# https://github.com/giantswarm/devctl/blob/bbc57913962860b1f2b3524a74a9692931c58034/pkg/gen/input/makefile/internal/file/Makefile.gen.app.mk.template +# https://github.com/giantswarm/devctl/blob/322af9d3c53b7b163c5f162f1f521273b5d723fb/pkg/gen/input/makefile/internal/file/Makefile.gen.app.mk.template # ##@ App @@ -88,6 +88,10 @@ HELM_UNITTEST_RETRY_DELAY ?= 5 # repository: its names render only once a repository created from it fills them in, so # its suites cannot pass here and run on the rendered copy instead. It is skipped, as a # chart reference with a placeholder is no chart for the catalog either. +# A wrapper chart's suites render its upstream subchart, and most repositories gitignore +# `charts/*.tgz`, so a fresh clone (CI) has none. A chart with a missing dependency gets +# `helm dependency update` before its suites run: unlike `helm dependency build`, it needs +# no `helm repo add`. A chart whose dependencies are present is not touched. helm-test: install-helm-unittest ## Run the chart unit tests (helm-unittest). @echo "====> $@" @found=""; \ @@ -97,6 +101,9 @@ helm-test: install-helm-unittest ## Run the chart unit tests (helm-unittest). case "$$c" in *[{}]*) echo "skipping $$c: a template's placeholder chart"; continue;; esac; \ ls "$$d"/*_test.yaml >/dev/null 2>&1 || continue; \ found=1; \ + if helm dependency list "$$c" 2>/dev/null | grep -q 'missing$$'; then \ + helm dependency update "$$c" || exit 1; \ + fi; \ helm unittest -f "$$(basename "$$d")/*_test.yaml" --with-subchart=false "$$c" || exit 1; \ done; \ [ -n "$$found" ] || echo "no chart unit tests under helm/" @@ -110,19 +117,20 @@ helm-test: install-helm-unittest ## Run the chart unit tests (helm-unittest). # network error (a connection reset) fails it; the install runs up to # HELM_UNITTEST_ATTEMPTS times, HELM_UNITTEST_RETRY_DELAY seconds apart. A failed attempt # can leave a half-installed plugin behind that the next install refuses, so it is -# uninstalled before each retry. +# uninstalled after every failure, including the last. A matching version must also +# run its binary: plugin metadata alone survives an interrupted download. install-helm-unittest: @have=$$(helm plugin list 2>/dev/null | awk '$$1 == "unittest" {print $$2}'); \ want=$$(echo "$(HELM_UNITTEST_VERSION)" | sed 's/^v//'); \ - if [ "$$have" != "$$want" ]; then \ + if [ "$$have" != "$$want" ] || ! helm unittest --version >/dev/null 2>&1; then \ [ -z "$$have" ] || helm plugin uninstall unittest >/dev/null 2>&1 || true; \ verify=""; \ helm plugin install --help 2>&1 | grep -q -e '--verify' && verify="--verify=false"; \ attempt=1; \ until helm plugin install $$verify https://github.com/helm-unittest/helm-unittest --version $(HELM_UNITTEST_VERSION); do \ + helm plugin uninstall unittest >/dev/null 2>&1 || true; \ [ "$$attempt" -lt "$(HELM_UNITTEST_ATTEMPTS)" ] || exit 1; \ echo "helm-unittest install failed (attempt $$attempt of $(HELM_UNITTEST_ATTEMPTS)), retrying in $(HELM_UNITTEST_RETRY_DELAY)s" >&2; \ - helm plugin uninstall unittest >/dev/null 2>&1 || true; \ sleep $(HELM_UNITTEST_RETRY_DELAY); \ attempt=$$((attempt + 1)); \ done; \ @@ -140,7 +148,7 @@ test: helm-test # pins aligned with gen circleci; repositories with explicit CI pins override them # in Makefile.custom.mk. This target supports ATS 1.x (the generated CI default). # renovate: datasource=docker depName=gsoci.azurecr.io/giantswarm/app-test-suite -ATS_VERSION ?= 1.0.3 +ATS_VERSION ?= 1.1.1 # renovate: datasource=docker depName=gsoci.azurecr.io/giantswarm/kind-node ATS_KIND_NODE_IMAGE_VERSION ?= v1.37.0 ATS_KIND_NODE_IMAGE ?= gsoci.azurecr.io/giantswarm/kind-node:$(ATS_KIND_NODE_IMAGE_VERSION)