Просмотр исходного кода

Merge branch 'develop' into claude/patch-CVE-2026-33252-Go0UF

Warwick 1 месяц назад
Родитель
Сommit
d8b4f49c9c
4 измененных файлов с 193 добавлено и 92 удалено
  1. 193 0
      .github/workflows/update-go-version.yaml
  2. 0 61
      Dockerfile
  3. 0 30
      Dockerfile.debug
  4. 0 1
      pkg/cloud/provider/providerconfig.go

+ 193 - 0
.github/workflows/update-go-version.yaml

@@ -0,0 +1,193 @@
+name: Update Go Version in "go.mod"
+
+on:
+  schedule:
+    - cron: '0 14 * * 1'  # Run every Monday at 2 PM UTC
+  workflow_dispatch:  # Allow manual triggering
+
+
+concurrency:
+  group: golang-ver-bump
+  cancel-in-progress: true
+
+jobs:
+  check-and-update-go:
+    name: Check and Update Go Version
+    runs-on: ubuntu-latest
+    permissions:
+      pull-requests: write
+      contents: write
+    steps:
+    - uses: actions/checkout@v6
+      with:
+        repository: 'opencost/opencost'
+        ref: 'develop'
+        fetch-depth: 0
+        path: ./opencost 
+
+    - name: Setup Go
+      uses: actions/setup-go@v6
+      with:
+         go-version: 'stable'
+
+    - name: Check for existing open PRs
+      id: check-existing-prs
+      run: |
+        # Check if there are any open PRs with the go-version-update label
+        EXISTING_PRS=$(gh pr list --label "go-version-update" --state open --json number,title,url)
+        if [ "$(echo "$EXISTING_PRS" | jq 'length')" -gt 0 ]; then
+          echo "Found existing open PR(s) with go-version-update label:"
+          echo "$EXISTING_PRS" | jq -r '.[] | "  - #\(.number): \(.title) (\(.url))"'
+          echo "skip_update=true" >> $GITHUB_OUTPUT
+        else
+          echo "No existing open PRs found, proceeding with update check"
+          echo "skip_update=false" >> $GITHUB_OUTPUT
+        fi
+      env:
+        GH_TOKEN: ${{ secrets.GITHUB_TOKEN}}
+        GH_REPO: ${{ github.repository }}
+
+    - name: Get current Go version from go.mod
+      id: current-version
+      working-directory: ./opencost
+      if: steps.check-existing-prs.outputs.skip_update == 'false'
+      run: |
+        CURRENT_VERSION=$(grep '^go ' go.mod | awk '{print $2}')
+        echo "current_version=$CURRENT_VERSION" >> $GITHUB_OUTPUT
+        echo "Current Go version: $CURRENT_VERSION"
+
+    - name: Get latest Go version
+      id: latest-version
+      working-directory: ./opencost
+      if: steps.check-existing-prs.outputs.skip_update == 'false'
+      run: |
+        # Get the latest Go version from golang.org/dl
+        LATEST_VERSION=$(curl -sS https://go.dev/VERSION?m=text | grep -o 'go[0-9]\+\.[0-9]\+\.[0-9]\+' | head -1)
+        echo "latest_version=$LATEST_VERSION" >> $GITHUB_OUTPUT
+        echo "Latest Go version: $LATEST_VERSION"
+
+    - name: Compare versions
+      id: version-check
+      working-directory: ./opencost
+      if: steps.check-existing-prs.outputs.skip_update == 'false'
+      run: |
+        CURRENT_VERSION="${{ steps.current-version.outputs.current_version }}"
+        LATEST_VERSION="${{ steps.latest-version.outputs.latest_version }}"
+
+        # Remove 'go' prefix for comparison
+        CURRENT_NUM=$(echo "$CURRENT_VERSION" | sed 's/^go//')
+        LATEST_NUM=$(echo "$LATEST_VERSION" | sed 's/^go//')
+
+        echo "Raw current version: $CURRENT_VERSION"
+        echo "Raw latest version: $LATEST_VERSION"
+        echo "Current version number: $CURRENT_NUM"
+        echo "Latest version number: $LATEST_NUM"
+
+        # Validate that both versions are non-empty and match an expected pattern (e.g., 1.22.1)
+        VERSION_REGEX='^[0-9]+\.[0-9]+(\.[0-9]+)?$'
+
+        if ! echo "$CURRENT_NUM" | grep -Eq "$VERSION_REGEX"; then
+          echo "Error: CURRENT_VERSION '$CURRENT_VERSION' (normalized: '$CURRENT_NUM') is invalid or empty."
+          exit 1
+        fi
+
+        if ! echo "$LATEST_NUM" | grep -Eq "$VERSION_REGEX"; then
+          echo "Error: LATEST_VERSION '$LATEST_VERSION' (normalized: '$LATEST_NUM') is invalid or empty."
+          exit 1
+        fi
+
+        if [ "$CURRENT_NUM" = "$LATEST_NUM" ]; then
+          echo "Go version is up to date"
+          echo "update_needed=false" >> $GITHUB_OUTPUT
+        else
+          # Use version-aware sorting to determine which version is greater
+          HIGHEST_VERSION=$(printf '%s\n' "$CURRENT_NUM" "$LATEST_NUM" | sort -V | tail -n1)
+
+          if [ "$HIGHEST_VERSION" = "$LATEST_NUM" ]; then
+            echo "Newer Go version available: $LATEST_VERSION (current: $CURRENT_VERSION)"
+            echo "update_needed=true" >> $GITHUB_OUTPUT
+            echo "new_version=$LATEST_VERSION" >> $GITHUB_OUTPUT
+          else
+            echo "Current Go version ($CURRENT_VERSION) is newer than or equal to latest reported version ($LATEST_VERSION); no update needed."
+            echo "update_needed=false" >> $GITHUB_OUTPUT
+          fi
+        fi
+
+    - name: Update go.mod with new Go version
+      if: steps.check-existing-prs.outputs.skip_update == 'false' && steps.version-check.outputs.update_needed == 'true'
+      working-directory: ./opencost
+      run: |
+        NEW_VERSION="$(echo '${{ steps.version-check.outputs.new_version }}' | tr -d 'go')"
+        echo "Updating all go.mod files under $(pwd) to use Go version: $NEW_VERSION"
+
+        # Recursively update every go.mod we find under the working directory.
+        # (Skip vendor directories to avoid accidental edits of vendored content.)
+        while IFS= read -r go_mod_file; do
+          echo "Updating: $go_mod_file"
+          sed -i -E "s/^go[[:space:]].*/go ${NEW_VERSION}/" "$go_mod_file"
+        done < <(find . -name go.mod -type f -not -path "*/vendor/*")
+        
+
+    - name: Run go mod tidy
+      if: steps.check-existing-prs.outputs.skip_update == 'false' && steps.version-check.outputs.update_needed == 'true'
+      working-directory: ./opencost
+      run: |
+        echo "Running go mod tidy for every module found under $(pwd)"
+
+        # Tidy once per module directory (dirname of each go.mod we find).
+        # Skip vendor directories to avoid editing vendored content.
+        mapfile -t tidy_dirs < <(find . -name go.mod -type f -not -path "*/vendor/*" -exec dirname {} \; | sort -u)
+        for d in "${tidy_dirs[@]}"; do
+          echo "Tidying: $d"
+          (cd "$d" && go mod tidy)
+        done
+
+    - name: Check for changes
+      id: changes
+      if: steps.check-existing-prs.outputs.skip_update == 'false' && steps.version-check.outputs.update_needed == 'true'
+      working-directory: ./opencost
+      run: |
+        if [ -z "$(git status --porcelain)" ]; then
+          echo "No changes detected, skipping PR creation"
+          echo "skip_pr=true" >> $GITHUB_OUTPUT
+        else
+          echo "Changes detected, will create PR" 
+          echo "skip_pr=false" >> $GITHUB_OUTPUT
+          # Generate a unique branch name with timestamp
+          branch_name="update-go-version-$(date +%Y%m%d-%H%M%S)"
+          echo "branch_name=$branch_name" >> $GITHUB_OUTPUT
+        fi
+
+    - name: Create Pull Request
+      if: steps.check-existing-prs.outputs.skip_update == 'false' && steps.version-check.outputs.update_needed == 'true' && steps.changes.outputs.skip_pr == 'false'
+      id: create-pr
+      uses: peter-evans/create-pull-request@v8
+      with:
+        path: ./opencost
+        token: ${{ secrets.GITHUB_TOKEN }}
+        branch: ${{ steps.changes.outputs.branch_name }}
+        title: 'chore: update Go version to ${{ steps.version-check.outputs.new_version }}'
+        commit-message: 'chore: update Go version to ${{ steps.version-check.outputs.new_version }}'
+        delete-branch: true
+        add-paths: |
+          go.mod
+          go.sum
+          **/go.mod
+          **/go.sum
+        body: |
+          Automated PR to update Go version from ${{ steps.current-version.outputs.current_version }} to ${{ steps.version-check.outputs.new_version }}.
+          
+          This PR was automatically generated after detecting a newer Go version is available.
+        base: develop
+        labels: automated,go-version-update
+    
+
+    - name: Skip message - no update needed
+      if: steps.check-existing-prs.outputs.skip_update == 'false' && steps.version-check.outputs.update_needed == 'false'
+      run: |
+        echo "No Go version update needed. Current version is up to date."
+
+    - name: Skip message - existing PR
+      if: steps.check-existing-prs.outputs.skip_update == 'true'
+      run: |
+        echo "Skipping Go version update because an existing PR with go-version-update label is already open." 

+ 0 - 61
Dockerfile

@@ -1,61 +0,0 @@
-FROM --platform=$BUILDPLATFORM golang:1.25.5-alpine3.21 AS build-env
-
-WORKDIR /app
-
-# This ensures that CGO is disabled for go test running AND for the build
-# step. This prevents a build failure when building an ARM64 image with
-# docker buildx. I believe this is because the ARM64 version of the
-# golang:latest image does not contain GCC, while the AMD64 version does.
-ARG CGO_ENABLED=0
-
-# Get dependencies - will also be cached if we won't change mod/sum
-COPY go.* .
-COPY core/go.* core/
-COPY modules/collector-source/go.* modules/collector-source/
-COPY modules/prometheus-source/go.* modules/prometheus-source/
-RUN go mod download
-
-ARG version=dev
-ARG	commit=HEAD
-
-ARG TARGETOS
-ARG TARGETARCH
-ENV GOOS=$TARGETOS
-ENV GOARCH=$TARGETARCH
-
-# COPY the source code as the last step
-COPY . .
-
-# Build the binary
-RUN set -e ;\
-    cd cmd/costmodel;\
-    go build -a -installsuffix cgo \
-    -ldflags \
-    "-X github.com/opencost/opencost/core/pkg/version.Version=${version} \
-    -X github.com/opencost/opencost/core/pkg/version.GitCommit=${commit}" \
-    -o /go/bin/app
-
-FROM alpine:latest
-
-LABEL org.opencontainers.image.description="Cross-cloud cost allocation models for Kubernetes workloads"
-LABEL org.opencontainers.image.documentation=https://opencost.io/docs/
-LABEL org.opencontainers.image.licenses=Apache-2.0
-LABEL org.opencontainers.image.source=https://github.com/opencost/opencost
-LABEL org.opencontainers.image.title=kubecost-cost-model
-LABEL org.opencontainers.image.url=https://opencost.io
-
-RUN apk add --update --no-cache ca-certificates
-
-COPY --from=build-env /go/bin/app /go/bin/app
-ADD --chmod=400 ./THIRD_PARTY_LICENSES.txt /THIRD_PARTY_LICENSES.txt
-ADD --chmod=500 ./configs/default.json /models/default.json
-ADD --chmod=500 ./configs/azure.json /models/azure.json
-ADD --chmod=500 ./configs/aws.json /models/aws.json
-ADD --chmod=500 ./configs/gcp.json /models/gcp.json
-ADD --chmod=500 ./configs/alibaba.json /models/alibaba.json
-ADD --chmod=500 ./configs/oracle.json /models/oracle.json
-ADD --chmod=500 ./configs/otc.json /models/otc.json
-RUN chown -R 1001:1001 /models
-
-USER 1001
-ENTRYPOINT ["/go/bin/app"]

+ 0 - 30
Dockerfile.debug

@@ -1,30 +0,0 @@
-# This dockerfile is for development purposes only; do not use this for production deployments
-FROM golang:alpine
-# The prebuilt binary path. This Dockerfile assumes the binary will be built
-# outside of Docker.
-ARG binary_path
-
-LABEL org.opencontainers.image.description="Cross-cloud cost allocation models for Kubernetes workloads"
-LABEL org.opencontainers.image.documentation=https://opencost.io/docs/
-LABEL org.opencontainers.image.licenses=Apache-2.0
-LABEL org.opencontainers.image.source=https://github.com/opencost/opencost
-LABEL org.opencontainers.image.title=kubecost-cost-model
-LABEL org.opencontainers.image.url=https://opencost.io
-
-WORKDIR /app
-RUN apk add --update --no-cache ca-certificates
-RUN go install github.com/go-delve/delve/cmd/dlv@latest
-
-ADD --chmod=644 ./THIRD_PARTY_LICENSES.txt /THIRD_PARTY_LICENSES.txt
-ADD --chmod=644 ./configs/default.json /models/default.json
-ADD --chmod=644 ./configs/azure.json /models/azure.json
-ADD --chmod=644 ./configs/aws.json /models/aws.json
-ADD --chmod=644 ./configs/gcp.json /models/gcp.json
-ADD --chmod=644 ./configs/alibaba.json /models/alibaba.json
-ADD --chmod=644 ./configs/oracle.json /models/oracle.json
-ADD --chmod=644 ./configs/otc.json /models/otc.json
-
-COPY ${binary_path} main
-
-ENTRYPOINT ["/go/bin/dlv exec --listen=:40000 --api-version=2 --headless=true --accept-multiclient --log --continue /app/main"]
-EXPOSE 9003 40000

+ 0 - 1
pkg/cloud/provider/providerconfig.go

@@ -88,7 +88,6 @@ func (pc *ProviderConfig) loadConfig(writeIfNotExists bool) (*models.CustomPrici
 
 	// File Doesn't Exist
 	if !exists {
-		log.Infof("Could not find Custom Pricing file at path '%s'", pc.configFile.Path())
 		pc.customPricing = DefaultPricing()
 		// If config file is not present use the contents from mount models/ as pricing data
 		// in closed source rather than from from  DefaultPricing as first source of truth.