Skip to content

build image via go-m-m#6

Merged
defo89 merged 2 commits intomasterfrom
enable-image-publish
Mar 19, 2026
Merged

build image via go-m-m#6
defo89 merged 2 commits intomasterfrom
enable-image-publish

Conversation

@defo89
Copy link
Contributor

@defo89 defo89 commented Mar 18, 2026

Summary by CodeRabbit

  • Chores
    • Upgraded Go toolchain from version 1.25 to 1.26 across build environments.
    • Updated build action versions for enhanced coverage reporting and artifact handling.
    • Migrated spell-checking tool with updated configuration.
    • Added automated Docker image builds and publishing to container registry.
    • Updated license scanning and linter configurations.

@coderabbitai
Copy link

coderabbitai bot commented Mar 18, 2026

📝 Walkthrough

Walkthrough

This pull request upgrades the Go toolchain from version 1.25 to 1.26 across multiple configuration files, introduces a new container registry workflow for GitHub Container Registry (ghcr.io), migrates spelling checks from the misspell tool to typos, and adds associated configuration and development tooling updates.

Changes

Cohort / File(s) Summary
Go Toolchain Upgrade (1.25 → 1.26)
go.mod, Dockerfile, .github/renovate.json, .github/workflows/checks.yaml, .github/workflows/ci.yaml, .github/workflows/codeql.yaml, shell.nix
Updated Go version constraint from 1.25 to 1.26 across go.mod, container image, workflows, and nix environment; renovate.json also reflects new constraint.
Spelling Tool Migration (misspell → typos)
.github/workflows/checks.yaml, .golangci.yaml, .typos.toml, Makefile, shell.nix
Replaced reviewdog misspell action with crate-ci typos action; removed misspell linter from golangci config; added new .typos.toml configuration and typos Makefile targets; added typos package to nix development environment.
Workflow and Action Upgrades
.github/workflows/ci.yaml, .github/workflows/checks.yaml
Upgraded go-coverage-report action from v1.2.0 to v1.3.0, upload-artifact action from v5 to v7, and removed pull-requests read permission from checks workflow.
Container Registry Deployment
.github/workflows/container-registry-ghcr.yaml, Makefile.maker.yaml
Introduced new GitHub Actions workflow to build and push Docker images to ghcr.io on master pushes and manual dispatch; added pushContainerToGhcr configuration in Makefile.maker.yaml with support for linux/amd64 platform.
Build System Enhancements
Makefile
Added install-typos and run-typos targets; updated prepare-static-check to depend on install-typos; refactored Darwin detection to use unified UNAME_S variable; improved license-annotation filtering logic.
Linting & Security Configuration
.golangci.yaml
Removed misspell linter; added GoSEC exclusions (G117, G120, G701–G706) for false positives; corrected typo in modernize.disable comment.
Local Configuration & Licensing
.claude/settings.local.json, .license-scan-overrides.jsonl
Added local Claude settings file with explicit bash and web fetch permissions; added BSD-3-Clause license override for pgxmock/v5 dependency.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~12 minutes

Poem

A rabbit hops through Go one-two-six,
With typos tamed and workflows fixed,
To ghcr we push containers bright,
Build systems shimmer with new delight! 🐰✨

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 inconclusive)

Check name Status Explanation Resolution
Title check ❓ Inconclusive The title 'build image via go-m-m' is vague and does not clearly convey what changes are being made. The term 'go-m-m' is unclear without context, and the title doesn't describe the main changes: upgrading Go from 1.25 to 1.26, switching from misspell to typos linting, and adding container registry workflow. Clarify the title to describe the primary change more explicitly, such as 'Upgrade Go to 1.26 and add container registry workflow' or 'Upgrade Go toolchain and add GitHub Container Registry support'.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch enable-image-publish
📝 Coding Plan
  • Generate coding plan for human review comments

Comment @coderabbitai help to get the list of available commands and usage tips.

Tip

CodeRabbit can use Trivy to scan for security misconfigurations and secrets in Infrastructure as Code files.

Add a .trivyignore file to your project to customize which findings Trivy reports.

@github-advanced-security
Copy link

You are seeing this message because GitHub Code Scanning has recently been set up for this repository, or this pull request contains the workflow file for the Code Scanning tool.

What Enabling Code Scanning Means:

  • The 'Security' tab will display more code scanning analysis results (e.g., for the default branch).
  • Depending on your configuration and choice of analysis tool, future pull requests will be annotated with code scanning analysis results.
  • You will be able to see the analysis results for the pull request's branch on this overview once the scans have completed and the checks have passed.

For more information about GitHub Code Scanning, check out the documentation.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 7

🧹 Nitpick comments (2)
Dockerfile (1)

6-6: Unify Go patch version policy between local builds and CI.

Dockerfile (line 6) and go.mod (line 3) use floating patch versions (1.26-alpine and 1.26), while all CI workflows pin to 1.26.1. This versioning mismatch creates potential build drift where local builds could pull future 1.26.x releases while CI remains on 1.26.1.

Establish a single, intentional policy: either pin patch versions everywhere or explicitly document a floating patch strategy.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@Dockerfile` at line 6, The Dockerfile's base image tag "FROM
golang:1.26-alpine" and the go.mod "go 1.26" use floating patch versions while
CI pins 1.26.1; update both to the exact patch used in CI (change the Dockerfile
FROM tag to "golang:1.26.1-alpine" and set the go version in go.mod to "1.26.1")
so local builds and CI use the same Go patch, or alternatively adjust CI to
match a documented floating-patch policy—ensure the Dockerfile FROM and the
go.mod "go" directive are consistent.
Makefile (1)

48-49: Use the release tag instead of the display name.

The download URL is built from the GitHub release tag, but this code reads .[0].name from the releases list. That couples the install logic to a human-readable field and list ordering; a renamed release title or prerelease at the top of the array will break downloads. Query releases/latest and use .tag_name here.

Suggested fix
-	`@set` -eou pipefail;  if ! hash typos 2>/dev/null; then printf "\e[1;36m>> Installing typos...\e[0m\n"; TYPOS_ARCH=$$(uname -m); if [[ "$$TYPOS_ARCH" == "arm64" ]]; then TYPOS_ARCH=aarch64; fi; if command -v curl >/dev/null 2>&1; then GET="curl $${GITHUB_TOKEN:+" -u \":$$GITHUB_TOKEN\""} -sLo-"; elif command -v wget >/dev/null 2>&1; then GET="wget $${GITHUB_TOKEN:+" --password \"$$GITHUB_TOKEN\""} -O-"; else echo "Didn't find curl or wget to download typos"; exit 2; fi; if command -v gh >/dev/null; then TYPOS_GET_RELEASE_JSON="gh api /repos/crate-ci/typos/releases"; else TYPOS_GET_RELEASE_JSON="$$GET https://api.github.com/repos/crate-ci/typos/releases"; fi; TYPOS_VERSION=$$($$TYPOS_GET_RELEASE_JSON | jq -r '.[0].name' ); if [[ $(UNAME_S) == Darwin ]]; then TYPOS_FILE="typos-$$TYPOS_VERSION-$$TYPOS_ARCH-apple-darwin.tar.gz"; elif [[ $(UNAME_S) == Linux ]]; then TYPOS_FILE="typos-$$TYPOS_VERSION-$$TYPOS_ARCH-unknown-linux-musl.tar.gz"; fi; mkdir -p typos; $$GET ""https://github.com/crate-ci/typos/releases/download/$$TYPOS_VERSION/$$TYPOS_FILE"" | tar -C typos -zxf -; BIN=$$(go env GOBIN); if [[ -z $$BIN ]]; then BIN=$$(go env GOPATH)/bin; fi; install -Dm755 typos/typos -t "$$BIN"; rm -rf typos/; fi
+	`@set` -eou pipefail;  if ! hash typos 2>/dev/null; then printf "\e[1;36m>> Installing typos...\e[0m\n"; TYPOS_ARCH=$$(uname -m); if [[ "$$TYPOS_ARCH" == "arm64" ]]; then TYPOS_ARCH=aarch64; fi; if command -v curl >/dev/null 2>&1; then GET="curl $${GITHUB_TOKEN:+" -u \":$$GITHUB_TOKEN\""} -sLo-"; elif command -v wget >/dev/null 2>&1; then GET="wget $${GITHUB_TOKEN:+" --password \"$$GITHUB_TOKEN\""} -O-"; else echo "Didn't find curl or wget to download typos"; exit 2; fi; if command -v gh >/dev/null; then TYPOS_GET_RELEASE_JSON="gh api /repos/crate-ci/typos/releases/latest"; else TYPOS_GET_RELEASE_JSON="$$GET https://api.github.com/repos/crate-ci/typos/releases/latest"; fi; TYPOS_VERSION=$$($$TYPOS_GET_RELEASE_JSON | jq -r '.tag_name' ); if [[ $(UNAME_S) == Darwin ]]; then TYPOS_FILE="typos-$$TYPOS_VERSION-$$TYPOS_ARCH-apple-darwin.tar.gz"; elif [[ $(UNAME_S) == Linux ]]; then TYPOS_FILE="typos-$$TYPOS_VERSION-$$TYPOS_ARCH-unknown-linux-musl.tar.gz"; fi; mkdir -p typos; $$GET ""https://github.com/crate-ci/typos/releases/download/$$TYPOS_VERSION/$$TYPOS_FILE"" | tar -C typos -zxf -; BIN=$$(go env GOBIN); if [[ -z $$BIN ]]; then BIN=$$(go env GOPATH)/bin; fi; install -Dm755 typos/typos -t "$$BIN"; rm -rf typos/; fi
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@Makefile` around lines 48 - 49, The install-typos Makefile target currently
sets TYPOS_VERSION by querying the releases list and using jq -r '.[0].name';
change the logic in the install-typos target so TYPOS_GET_RELEASE_JSON queries
the GitHub "releases/latest" endpoint (use "gh api
/repos/crate-ci/typos/releases/latest" when gh is available or the GET URL
https://api.github.com/repos/crate-ci/typos/releases/latest otherwise) and set
TYPOS_VERSION by extracting the release tag with jq -r '.tag_name' instead of
'.[0].name' so the download URL uses the stable tag rather than the
human-readable name or array ordering.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In @.claude/settings.local.json:
- Around line 3-8: The tracked .claude/settings.local.json contains an
overly-permissive "allow" array (notably "Bash(gh pr:*)" and "Bash(curl:*)")
which should not be committed; either add .claude/settings.local.json to
.gitignore and remove it from the repo, or tighten the "allow" entries to the
minimum necessary specific commands (replace wildcards like "Bash(gh pr:*)" and
"Bash(curl:*)" with explicit command strings or restrict domains), then commit
the narrowed settings so the file can remain shared safely.

In @.github/workflows/checks.yaml:
- Around line 47-48: The "Delete typos binary" cleanup step uses a brittle
command `rm typos` that will fail if the `typos` binary is missing; update that
command to be non-failing by using the force flag (replace `rm typos` with `rm
-f typos`) so the step will not error when the file is absent, ensuring the
workflow remains robust against changes in the crate-ci/typos action.

In @.github/workflows/container-registry-ghcr.yaml:
- Around line 11-14: The workflow currently triggers only on pushes to branch
master so semver tag-based builds (the type=semver tag templates used for image
tags) never run; update the workflow trigger by adding a push.tags pattern
(e.g., add a push: tags: entry that matches your semver tags) so that pushing a
tag like v1.2.3 will invoke the job and produce the semver-derived tags, or
alternatively remove the semver tag templates if you do not intend to trigger on
tags; look for the push: block and the workflow_dispatch: {} entry to add the
tags: configuration or remove the semver templates accordingly.
- Around line 23-52: The workflow currently pins actions with floating tags
(actions/checkout@v6, docker/login-action@v4, docker/metadata-action@v6,
docker/setup-qemu-action@v4, docker/setup-buildx-action@v4,
docker/build-push-action@v7) which is unsafe; fix by either updating the
generator configuration (Makefile.maker.yaml / go-makefile-maker) to emit
workflows that pin each uses: reference to a full commit SHA, or stop
regenerating this file and add a new non-autogenerated workflow that replaces
each floating tag with the corresponding action@<full-commit-sha> (for
actions/checkout, docker/login-action, docker/metadata-action,
docker/setup-qemu-action, docker/setup-buildx-action, docker/build-push-action)
and retain the existing inputs (password, registry, username, images, tags, ids)
and permissions; ensure the autogenerated file is not overwritten (or adjust
generator) so the pinned SHAs persist.

In @.golangci.yaml:
- Around line 139-152: The global gosec excludes list is too broad—remove or
narrow G117, G120 and G306 from settings.gosec.excludes and instead apply
targeted suppressions: remove G120 and G306 entirely since there are no
net/http.ParseForm()/FormValue() calls and no file-permission ops; for G117,
remove the global exclusion and add a local `#nosec` annotation only where the
OCIParams struct (or any other struct with a password/json tag) is actually
serialized, or delete it if OCIParams is never marshaled; keep the upstream
false-positive group (G701–G706) if desired but prefer local `#nosec` comments on
the specific functions/types that need them rather than a global disable.

In `@Makefile`:
- Line 60: The static-check flow is missing the run-typos step: update the
Makefile so the existing prepare-static-check (which installs typos) is actually
exercised by adding the run-typos target into the static-check chain (or add
run-typos as a prerequisite of the static-check target); specifically modify the
static-check target to depend on or invoke run-typos (referencing targets
prepare-static-check, static-check, and run-typos) so local make static-check
matches CI and catches typos earlier.
- Line 161: Replace the hardcoded sed invocation in the Makefile rule with the
SED abstraction: change "sed '/\<vendor\>/d'" to "$(SED) '/\<vendor\>/d'" so the
Darwin override (gsed) is used; keep the existing regex and quoting as-is and
preserve the surrounding pipeline into $(XARGS) reuse annotate -c 'SAP SE or an
SAP affiliate company' -l Apache-2.0 --skip-unrecognised.

---

Nitpick comments:
In `@Dockerfile`:
- Line 6: The Dockerfile's base image tag "FROM golang:1.26-alpine" and the
go.mod "go 1.26" use floating patch versions while CI pins 1.26.1; update both
to the exact patch used in CI (change the Dockerfile FROM tag to
"golang:1.26.1-alpine" and set the go version in go.mod to "1.26.1") so local
builds and CI use the same Go patch, or alternatively adjust CI to match a
documented floating-patch policy—ensure the Dockerfile FROM and the go.mod "go"
directive are consistent.

In `@Makefile`:
- Around line 48-49: The install-typos Makefile target currently sets
TYPOS_VERSION by querying the releases list and using jq -r '.[0].name'; change
the logic in the install-typos target so TYPOS_GET_RELEASE_JSON queries the
GitHub "releases/latest" endpoint (use "gh api
/repos/crate-ci/typos/releases/latest" when gh is available or the GET URL
https://api.github.com/repos/crate-ci/typos/releases/latest otherwise) and set
TYPOS_VERSION by extracting the release tag with jq -r '.tag_name' instead of
'.[0].name' so the download URL uses the stable tag rather than the
human-readable name or array ordering.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 434031d5-ee77-4586-8595-d5a0b17e66b8

📥 Commits

Reviewing files that changed from the base of the PR and between 72e3dc9 and 38ebcaa.

📒 Files selected for processing (14)
  • .claude/settings.local.json
  • .github/renovate.json
  • .github/workflows/checks.yaml
  • .github/workflows/ci.yaml
  • .github/workflows/codeql.yaml
  • .github/workflows/container-registry-ghcr.yaml
  • .golangci.yaml
  • .license-scan-overrides.jsonl
  • .typos.toml
  • Dockerfile
  • Makefile
  • Makefile.maker.yaml
  • go.mod
  • shell.nix

Comment on lines +3 to +8
"allow": [
"Bash(gh pr:*)",
"WebFetch(domain:github.com)",
"WebFetch(domain:raw.githubusercontent.com)",
"Bash(curl:*)"
]
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "Check whether local Claude settings are intentionally tracked:"
fd -H '^settings\.local\.json$' .claude || true

echo "Check ignore rules for local Claude settings:"
if [ -f .gitignore ]; then
  rg -n '\.claude|settings\.local\.json' .gitignore || true
fi

echo "Find references to broad permissions:"
rg -n 'Bash\(gh pr:\*\)|Bash\(curl:\*\)|settings\.local\.json' -g '!**/.git/**'

Repository: cobaltcore-dev/cloud-profile-sync

Length of output: 251


Add .claude/settings.local.json to .gitignore or narrow the overly permissive permissions.

The file is currently tracked in the repository with broad wildcard shell access (Bash(gh pr:*) and Bash(curl:*)). If this is a local-only setting, it should be ignored. If intentionally shared, these permissions exceed least privilege and create unnecessary exfiltration/misuse risk—narrow them to specific commands instead.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @.claude/settings.local.json around lines 3 - 8, The tracked
.claude/settings.local.json contains an overly-permissive "allow" array (notably
"Bash(gh pr:*)" and "Bash(curl:*)") which should not be committed; either add
.claude/settings.local.json to .gitignore and remove it from the repo, or
tighten the "allow" entries to the minimum necessary specific commands (replace
wildcards like "Bash(gh pr:*)" and "Bash(curl:*)" with explicit command strings
or restrict domains), then commit the narrowed settings so the file can remain
shared safely.

Comment on lines +47 to +48
- name: Delete typos binary
run: rm typos
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

🧩 Analysis chain

🏁 Script executed:

find . -name "checks.yaml" -path "*/.github/workflows/*" -type f

Repository: cobaltcore-dev/cloud-profile-sync

Length of output: 108


🏁 Script executed:

cat -n .github/workflows/checks.yaml | head -60

Repository: cobaltcore-dev/cloud-profile-sync

Length of output: 2192


🌐 Web query:

crate-ci/typos@v1 github action binary extraction behavior

💡 Result:

crate-ci/typos@v1 is a composite action that runs action/entrypoint.sh and (if needed) downloads a prebuilt typos release asset and extracts just the binary into the install directory. [1] [2]

Binary install / extraction behavior:

  • Install location: the action sets INSTALL_DIR: ., so it installs to the workspace root and expects to run ./typos (i.e., COMMAND="${INSTALL_DIR}/typos"). [2] [1]
  • Skips download if already present: it only downloads when ${COMMAND} is not executable ([[ ! -x ${COMMAND} ]]). [1]
  • Which asset it downloads: it picks an OS/arch-specific asset name and downloads from GitHub Releases via wget (Linux uses *-unknown-linux-musl.tar.gz, macOS uses *.tar.gz, Windows uses *.zip). [1]
  • Extraction:
    • For tar.gz: tar -xzvf "${FILE_NAME}" -C ${INSTALL_DIR} ./${CMD_NAME} → extracts only ./typos from the archive into INSTALL_DIR (not the full archive contents). [1]
    • For zip (Windows): unzip -o "${FILE_NAME}" -d ${INSTALL_DIR} typos.exe → extracts only typos.exe, overwriting if present (-o). [1]
  • Pinned typos version (inside the script): the script currently hardcodes VERSION=1.44.0, so @v1 will keep installing that until the tag/script is updated. [1]

Sources: [1] [2]


Make this cleanup step non-failing.

The crate-ci/typos@v1 action extracts a ./typos binary to the workspace root, but using rm typos without the -f flag causes the step to fail if the binary is ever missing. Use rm -f typos to make it non-failing and protect against future action changes.

Suggested fix
       - name: Delete typos binary
-        run: rm typos
+        run: rm -f typos
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
- name: Delete typos binary
run: rm typos
- name: Delete typos binary
run: rm -f typos
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @.github/workflows/checks.yaml around lines 47 - 48, The "Delete typos
binary" cleanup step uses a brittle command `rm typos` that will fail if the
`typos` binary is missing; update that command to be non-failing by using the
force flag (replace `rm typos` with `rm -f typos`) so the step will not error
when the file is absent, ensuring the workflow remains robust against changes in
the crate-ci/typos action.

Comment on lines +11 to +14
push:
branches:
- master
workflow_dispatch: {}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

find . -name "container-registry-ghcr.yaml" -type f

Repository: cobaltcore-dev/cloud-profile-sync

Length of output: 125


🏁 Script executed:

cat -n ./.github/workflows/container-registry-ghcr.yaml

Repository: cobaltcore-dev/cloud-profile-sync

Length of output: 2570


🏁 Script executed:

# Let me search for any documentation or comments about how docker/metadata-action behaves with semver
web_search "docker/metadata-action type=semver git tags trigger"

Repository: cobaltcore-dev/cloud-profile-sync

Length of output: 127


🏁 Script executed:

web_search "docker metadata-action semver pattern git tag ref"

Repository: cobaltcore-dev/cloud-profile-sync

Length of output: 127


🌐 Web query:

docker/metadata-action type=semver how git tags trigger works

💡 Result:

How Git tags trigger docker/metadata-action with type=semver

  1. A GitHub Actions workflow must be triggered by a tag push
  • Your workflow needs a tag trigger, e.g.:
    on:
      push:
        tags:
          - 'v*'
  • The workflow run happens when the tag is pushed to the remote (not when it’s only created locally). GitHub exposes the pushed tag as GITHUB_REF=refs/tags/<tag>. [3]
  1. type=semver runs (by design) on “push tag” events and parses the tag
  • docker/metadata-action says type=semver “will be used on a push tag event” and it requires a valid SemVer Git tag (unless you provide a custom value=). [1]
  • It parses the tag into template fields you can use in pattern=..., such as:
    • {{raw}} (the tag text, e.g. v1.2.3)
    • {{version}} (e.g. 1.2.3, including prerelease like 2.0.8-beta.67)
    • {{major}}, {{minor}}, {{patch}} [1]
  1. What tags it generates (common setup)
  • Example config:
    - uses: docker/metadata-action@v6
      with:
        tags: |
          type=semver,pattern={{version}}
          type=semver,pattern={{major}}.{{minor}}
          type=semver,pattern={{major}}
  • If you push Git tag v1.2.3, it will generate Docker tags like 1.2.3, 1.2, 1 (based on your patterns). [1]
  1. Where the “version” comes from
  • On a tag-triggered run, type=semver uses the Git tag that triggered the workflow as its input (unless overridden with value=). [1]
  • If you omit pattern, docs/discussions indicate it effectively defaults to using the tag value (so you normally set pattern to control what gets emitted). [2]

Mental model: git tag v1.2.3 && git push origin v1.2.3 → workflow triggers on refs/tags/v1.2.3metadata-action parses v1.2.3 as SemVer → outputs the Docker tags you described with pattern=. [1][3]


type=semver tags never run with the current trigger.

This workflow only fires on pushes to master, but the semver templates are populated from tag refs. As written, pushing v1.2.3 will not publish v1.2.3, v1.2, or v1 images. Either add a push.tags trigger or drop the semver tag templates.

Suggested fix
 "on":
   push:
     branches:
       - master
+    tags:
+      - 'v*'
   workflow_dispatch: {}

Also applies to: 36-44

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @.github/workflows/container-registry-ghcr.yaml around lines 11 - 14, The
workflow currently triggers only on pushes to branch master so semver tag-based
builds (the type=semver tag templates used for image tags) never run; update the
workflow trigger by adding a push.tags pattern (e.g., add a push: tags: entry
that matches your semver tags) so that pushing a tag like v1.2.3 will invoke the
job and produce the semver-derived tags, or alternatively remove the semver tag
templates if you do not intend to trigger on tags; look for the push: block and
the workflow_dispatch: {} entry to add the tags: configuration or remove the
semver templates accordingly.

Comment on lines +23 to +52
- name: Check out code
uses: actions/checkout@v6
- name: Log in to the Container registry
uses: docker/login-action@v4
with:
password: ${{ secrets.GITHUB_TOKEN }}
registry: ghcr.io
username: ${{ github.actor }}
- name: Extract metadata (tags, labels) for Docker
id: meta
uses: docker/metadata-action@v6
with:
images: ghcr.io/${{ github.repository }}
tags: |
# https://github.com/docker/metadata-action#typeedge
type=edge
# https://github.com/docker/metadata-action#latest-tag
type=raw,value=latest,enable={{is_default_branch}}
# https://github.com/docker/metadata-action#typesemver
type=semver,pattern={{raw}}
type=semver,pattern=v{{major}}.{{minor}}
type=semver,pattern=v{{major}}
# https://github.com/docker/metadata-action#typesha
type=sha,format=long
- name: Set up QEMU
uses: docker/setup-qemu-action@v4
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v4
- name: Build and push Docker image
uses: docker/build-push-action@v7
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

cat -n .github/workflows/container-registry-ghcr.yaml | head -60

Repository: cobaltcore-dev/cloud-profile-sync

Length of output: 2570


🏁 Script executed:

fd Makefile.maker.yaml

Repository: cobaltcore-dev/cloud-profile-sync

Length of output: 96


🏁 Script executed:

cat -n Makefile.maker.yaml

Repository: cobaltcore-dev/cloud-profile-sync

Length of output: 1392


🏁 Script executed:

web_search
Query: go-makefile-maker action pinning SHA github workflows

Repository: cobaltcore-dev/cloud-profile-sync

Length of output: 172


🌐 Web query:

go-makefile-maker github actions pinning commit SHA security

💡 Result:

If you use go-makefile-maker in GitHub Actions, treat it like any other third‑party dependency and aim for immutable pinning:

  • Pin GitHub Actions to a full 40‑char commit SHA (not @main, not @v1). GitHub explicitly recommends this as the primary way to make an action reference immutable and reduce supply‑chain risk (tags can be moved) [1]. GitHub org/repo policies can also require SHA pinning so workflows fail if actions aren’t pinned [2], and GitHub added policy support specifically for SHA pinning/blocking [3].
  • If you’re installing the tool as a Go module (typical for go-makefile-maker), also pin the module version (tag or Go pseudo‑version) instead of @latest, e.g. go install github.com/SuperSandro2000/go-makefile-maker@<version> [4].

Example (what “pin to SHA” looks like):

- uses: OWNER/REPO@0123456789abcdef0123456789abcdef01234567  # v1.2.3

Sources

  1. GitHub Docs – Security hardening for GitHub Actions (pin actions to full-length commit SHA) [1]
  2. GitHub Docs – repo/org settings: Require actions to be pinned to a full-length commit SHA [2]
  3. GitHub Changelog – Actions policy supports SHA pinning/blocking [3]
  4. pkg.go.dev – github.com/SuperSandro2000/go-makefile-maker module reference [4]

Pin GitHub Actions to commit SHAs instead of floating version tags.

This workflow pushes container images with packages: write permission, but all uses: references use floating major version tags (@v4, @v6, @v7). If an upstream action is retagged or compromised, a malicious image could be published from this repository. However, since .github/workflows/container-registry-ghcr.yaml is autogenerated by go-makefile-maker (see file header), manually editing this file will not persist. You need to either:

  • Update Makefile.maker.yaml to configure action pinning if go-makefile-maker supports it, or
  • Create a non-autogenerated workflow file with actions pinned to full commit SHAs (GitHub's recommended security hardening)
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @.github/workflows/container-registry-ghcr.yaml around lines 23 - 52, The
workflow currently pins actions with floating tags (actions/checkout@v6,
docker/login-action@v4, docker/metadata-action@v6, docker/setup-qemu-action@v4,
docker/setup-buildx-action@v4, docker/build-push-action@v7) which is unsafe; fix
by either updating the generator configuration (Makefile.maker.yaml /
go-makefile-maker) to emit workflows that pin each uses: reference to a full
commit SHA, or stop regenerating this file and add a new non-autogenerated
workflow that replaces each floating tag with the corresponding
action@<full-commit-sha> (for actions/checkout, docker/login-action,
docker/metadata-action, docker/setup-qemu-action, docker/setup-buildx-action,
docker/build-push-action) and retain the existing inputs (password, registry,
username, images, tags, ids) and permissions; ensure the autogenerated file is
not overwritten (or adjust generator) so the pinned SHAs persist.

Comment on lines +139 to +152
# if we put a password or token into a serialized payload, guess what, we probably did that on purpose
- G117
# this triggers on net/http.Request.ParseForm() and its callers, e.g. net/http.Request.FormValue(), complaining about potential memory exhaustion from unbounded form parsing;
# but that is incorrect, ParseForm() by default never parses more than 10 MiB for this specific reason
- G120
# created file permissions are restricted by umask if necessary
- G306
# the following lints cause false-positives in many repositories, should be fixed with the next release. (see https://github.com/securego/gosec/issues/1500)
- G701
- G702
- G703
- G704
- G705
- G706
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

# First, locate and examine the .golangci.yaml file
find . -name ".golangci.yaml" -o -name ".golangci.yml" | head -20

Repository: cobaltcore-dev/cloud-profile-sync

Length of output: 93


🏁 Script executed:

# Read the .golangci.yaml file with context around lines 139-152
wc -l .golangci.yaml

Repository: cobaltcore-dev/cloud-profile-sync

Length of output: 95


🏁 Script executed:

# Show the relevant section with surrounding context
head -160 .golangci.yaml | tail -30

Repository: cobaltcore-dev/cloud-profile-sync

Length of output: 1404


🏁 Script executed:

# Check if there are any `#nosec` or //nolint:gosec annotations in the codebase currently
rg "#nosec|//nolint.*gosec" --type go | head -20

Repository: cobaltcore-dev/cloud-profile-sync

Length of output: 59


🏁 Script executed:

# Search for specific code patterns that would match the excluded rules
# G120: net/http.Request.ParseForm() or FormValue()
rg "ParseForm|FormValue" --type go -n

Repository: cobaltcore-dev/cloud-profile-sync

Length of output: 59


🏁 Script executed:

# Search for patterns related to G117 (hardcoded credentials) and G306 (file permissions)
rg "os.Create|os.OpenFile|NewFile|chmod" --type go -n | head -30

Repository: cobaltcore-dev/cloud-profile-sync

Length of output: 59


🏁 Script executed:

# Check if golangci-lint documentation is available locally
find . -name "*.md" -type f | xargs grep -l "gosec\|excludes" 2>/dev/null | head -5

Repository: cobaltcore-dev/cloud-profile-sync

Length of output: 59


🏁 Script executed:

# Get an overview of the codebase structure
find . -type f -name "*.go" | wc -l
ls -la | head -20

Repository: cobaltcore-dev/cloud-profile-sync

Length of output: 1281


🏁 Script executed:

# Check git history or comments to understand why these rules were excluded
git log --oneline -n 20 -- .golangci.yaml 2>/dev/null | head -10

Repository: cobaltcore-dev/cloud-profile-sync

Length of output: 106


🏁 Script executed:

# Search for any code that might involve password/token handling (related to G117)
rg "password|token|secret|credential" --type go -i -l | head -10

Repository: cobaltcore-dev/cloud-profile-sync

Length of output: 274


🏁 Script executed:

# Check the content of files that mention password/token/secret
cat cloudprofilesync/source.go | head -100

Repository: cobaltcore-dev/cloud-profile-sync

Length of output: 2352


🏁 Script executed:

# Check the controller files for password/token handling
rg "password|token|secret" --type go -B 2 -A 2

Repository: cobaltcore-dev/cloud-profile-sync

Length of output: 4930


🏁 Script executed:

# Check if there are any comments in the code mentioning gosec or nosec
rg "gosec|nosec|nolint" --type go | head -20

Repository: cobaltcore-dev/cloud-profile-sync

Length of output: 59


🏁 Script executed:

# Look for the issue mentioned in the comment (https://github.com/securego/gosec/issues/1500)
# to understand the context of G701-G706 exclusions
rg "G701|G702|G703|G704|G705|G706" .

Repository: cobaltcore-dev/cloud-profile-sync

Length of output: 59


🏁 Script executed:

# Verify the exact usage of OCIParams to understand if password serialization is truly necessary
rg "OCIParams" --type go -B 2 -A 2

Repository: cobaltcore-dev/cloud-profile-sync

Length of output: 1341


🏁 Script executed:

# Check if there's any marshaling/serialization of OCIParams or similar structures
rg "json\.Marshal|json\.Unmarshal|MarshalJSON|UnmarshalJSON" --type go

Repository: cobaltcore-dev/cloud-profile-sync

Length of output: 914


🏁 Script executed:

# Check if OCIParams is ever marshaled or serialized
rg "NewOCI" --type go -A 5 | head -40

Repository: cobaltcore-dev/cloud-profile-sync

Length of output: 1344


🏁 Script executed:

# Look at the full controller code to see if the password ends up in serialized form
sed -n '1,100p' controllers/managedcloudprofile_controller.go

Repository: cobaltcore-dev/cloud-profile-sync

Length of output: 3670


🏁 Script executed:

# Check if OCIParams json tags are actually used anywhere (marshaled/unmarshaled)
rg "OCIParams" --type go -A 10 -B 2 | grep -A 10 -B 2 "Marshal\|Unmarshal"

Repository: cobaltcore-dev/cloud-profile-sync

Length of output: 59


🏁 Script executed:

# Verify the complete picture: is OCIParams ever serialized?
ast-grep --pattern 'json.Marshal($$_OCIParams)' || true
ast-grep --pattern 'json.Unmarshal($$_, $$_OCIParams)' || true

Repository: cobaltcore-dev/cloud-profile-sync

Length of output: 59


🏁 Script executed:

# Check if there are any http.Request.ParseForm or FormValue calls
rg "ParseForm|FormValue" --type go -n

Repository: cobaltcore-dev/cloud-profile-sync

Length of output: 59


Remove unnecessary gosec exclusions or narrow their scope.

The settings.gosec.excludes disables these rules globally, but many aren't actually needed: there are no ParseForm() or FormValue() calls (G120), no file permission operations (G306), and OCIParams is never marshaled to JSON despite the password field having json tags (undermining the G117 justification). Only G701–G706 have clear justification as known upstream false-positives. Remove or localize G120 and G306; for the rest, consider scoping suppressions using local #nosec annotations on the specific lines that genuinely need them, or wait for the upstream gosec fixes referenced in the configuration.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @.golangci.yaml around lines 139 - 152, The global gosec excludes list is too
broad—remove or narrow G117, G120 and G306 from settings.gosec.excludes and
instead apply targeted suppressions: remove G120 and G306 entirely since there
are no net/http.ParseForm()/FormValue() calls and no file-permission ops; for
G117, remove the global exclusion and add a local `#nosec` annotation only where
the OCIParams struct (or any other struct with a password/json tag) is actually
serialized, or delete it if OCIParams is never marshaled; keep the upstream
false-positive group (G701–G706) if desired but prefer local `#nosec` comments on
the specific functions/types that need them rather than a global disable.

@if ! hash reuse 2>/dev/null; then if ! hash pipx 2>/dev/null; then printf "\e[1;31m>> You are required to manually intervene to install reuse as go-makefile-maker cannot automatically resolve installing reuse on all setups.\e[0m\n"; printf "\e[1;31m>> The preferred way for go-makefile-maker to install python tools after nix-shell is pipx which could not be found. Either install pipx using your package manager or install reuse using your package manager if at least version 6 is available.\e[0m\n"; printf "\e[1;31m>> As your Python was likely installed by your package manager, just doing pip install --user sadly does no longer work as pip issues a warning about breaking your system. Generally running --break-system-packages with --user is safe to do but you should only run this command if you can resolve issues with it yourself: pip3 install --user --break-system-packages reuse\e[0m\n"; else printf "\e[1;36m>> Installing reuse...\e[0m\n"; pipx install reuse; fi; fi

prepare-static-check: FORCE install-goimports install-golangci-lint install-shellcheck install-go-licence-detector install-addlicense install-reuse
prepare-static-check: FORCE install-goimports install-golangci-lint install-shellcheck install-typos install-go-licence-detector install-addlicense install-reuse
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

run-typos is still missing from make static-check.

prepare-static-check now installs typos, but the standard static-check chain never invokes this new target. That leaves local make static-check out of sync with CI and pushes typo failures to PR time instead of dev time.

Suggested fix
-__static-check: FORCE run-shellcheck run-golangci-lint check-dependency-licenses check-license-headers
+__static-check: FORCE run-shellcheck run-typos run-golangci-lint check-dependency-licenses check-license-headers

Also applies to: 122-124

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@Makefile` at line 60, The static-check flow is missing the run-typos step:
update the Makefile so the existing prepare-static-check (which installs typos)
is actually exercised by adding the run-typos target into the static-check chain
(or add run-typos as a prerequisite of the static-check target); specifically
modify the static-check target to depend on or invoke run-typos (referencing
targets prepare-static-check, static-check, and run-typos) so local make
static-check matches CI and catches typos earlier.

@printf "%s\0" $(patsubst $(shell awk '$$1 == "module" {print $$2}' go.mod)%,.%/*.go,$(shell go list ./...)) | $(XARGS) -0 -I{} bash -c 'year="$$(grep 'Copyright' {} | head -n1 | grep -E -o '"'"'[0-9]{4}(-[0-9]{4})?'"'"')"; if [[ -z "$$year" ]]; then year=$$(date +%Y); fi; gawk -i inplace '"'"'{if (display) {print} else {!/^\/\*/ && !/^\*/}}; {if (!display && $$0 ~ /^(package |$$)/) {display=1} else { }}'"'"' {}; addlicense -c "SAP SE or an SAP affiliate company" -s=only -y "$$year" -- {}; $(SED) -i '"'"'1s+// Copyright +// SPDX-FileCopyrightText: +'"'"' {}; '
@printf "\e[1;36m>> reuse annotate (for license headers on other files)\e[0m\n"
@reuse lint -j | jq -r '.non_compliant.missing_licensing_info[]' | grep -vw vendor | $(XARGS) reuse annotate -c 'SAP SE or an SAP affiliate company' -l Apache-2.0 --skip-unrecognised
@reuse lint -j | jq -r '.non_compliant.missing_licensing_info[]' | sed '/\<vendor\>/d' | $(XARGS) reuse annotate -c 'SAP SE or an SAP affiliate company' -l Apache-2.0 --skip-unrecognised
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Reuse the $(SED) abstraction here.

This hardcodes sed again and bypasses the Darwin gsed override above. On macOS that reopens the portability problem you already accounted for, and \<vendor\> is exactly the sort of regex that differs.

Suggested fix
-	`@reuse` lint -j | jq -r '.non_compliant.missing_licensing_info[]' | sed '/\<vendor\>/d' | $(XARGS) reuse annotate -c 'SAP SE or an SAP affiliate company' -l Apache-2.0 --skip-unrecognised
+	`@reuse` lint -j | jq -r '.non_compliant.missing_licensing_info[]' | $(SED) '/\<vendor\>/d' | $(XARGS) reuse annotate -c 'SAP SE or an SAP affiliate company' -l Apache-2.0 --skip-unrecognised
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
@reuse lint -j | jq -r '.non_compliant.missing_licensing_info[]' | sed '/\<vendor\>/d' | $(XARGS) reuse annotate -c 'SAP SE or an SAP affiliate company' -l Apache-2.0 --skip-unrecognised
`@reuse` lint -j | jq -r '.non_compliant.missing_licensing_info[]' | $(SED) '/\<vendor\>/d' | $(XARGS) reuse annotate -c 'SAP SE or an SAP affiliate company' -l Apache-2.0 --skip-unrecognised
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@Makefile` at line 161, Replace the hardcoded sed invocation in the Makefile
rule with the SED abstraction: change "sed '/\<vendor\>/d'" to "$(SED)
'/\<vendor\>/d'" so the Darwin override (gsed) is used; keep the existing regex
and quoting as-is and preserve the surrounding pipeline into $(XARGS) reuse
annotate -c 'SAP SE or an SAP affiliate company' -l Apache-2.0
--skip-unrecognised.

@defo89 defo89 merged commit 36b651e into master Mar 19, 2026
6 of 7 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant