diff --git a/.github/workflows/update-cloud-spanner-emulator-version.yml b/.github/workflows/update-cloud-spanner-emulator-version.yml new file mode 100644 index 0000000000..0716444cb4 --- /dev/null +++ b/.github/workflows/update-cloud-spanner-emulator-version.yml @@ -0,0 +1,48 @@ +name: "update-cloud-spanner-emulator-version" +on: + workflow_dispatch: + schedule: + # every Monday at around 3 am pacific/10 am UTC + - cron: "0 10 * * 1" +env: + GOPROXY: https://proxy.golang.org + GO_VERSION: '1.20' +permissions: + contents: read + +jobs: + bump-cloud-spanner-emulator-version: + runs-on: ubuntu-20.04 + steps: + - uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c + - uses: actions/setup-go@6edd4406fa81c3da01a34fa6f6343087c207a568 + with: + go-version: ${{env.GO_VERSION}} + cache: true + cache-dependency-path: ./go.sum + - name: Bump cloud-spanner-emulator version + id: bumpCloudSpannerEmulator + run: | + make update-cloud-spanner-emulator-version + # The following is to support multiline with GITHUB_OUTPUT, see https://docs.github.com/en/actions/using-workflows/workflow-commands-for-github-actions#multiline-strings + echo "changes<> $GITHUB_OUTPUT + echo "$(git status --porcelain)" >> $GITHUB_OUTPUT + echo "EOF" >> $GITHUB_OUTPUT + - name: Create PR + if: ${{ steps.bumpCloudSpannerEmulator.outputs.changes != '' }} + uses: peter-evans/create-pull-request@2b011faafdcbc9ceb11414d64d0573f37c774b04 + with: + token: ${{ secrets.MINIKUBE_BOT_PAT }} + commit-message: bump cloud-spanner-emulator version + committer: minikube-bot + author: minikube-bot + branch: auto_bump_cloud_spanner_emulator_version + push-to-fork: minikube-bot/minikube + base: master + delete-branch: true + title: 'bump cloud-spanner-emulator version' + labels: ok-to-test + body: | + cloud-spanner-emulator project released a [new version](https://github.com/GoogleCloudPlatform/cloud-spanner-emulator), + + This PR was auto-generated by `make update-cloud-spanner-emulator-version` using [update-cloud-spanner-emulator-version.yml](https://github.com/kubernetes/minikube/tree/master/.github/workflows/update-cloud-spanner-emulator-version.yml) CI Workflow. diff --git a/Makefile b/Makefile index e082425804..d933bded87 100644 --- a/Makefile +++ b/Makefile @@ -1067,11 +1067,16 @@ update-docsy-version: (cd hack/update/docsy_version && \ go run update_docsy_version.go) -.Phony: update-hugo-version +.PHONY: update-hugo-version update-hugo-version: (cd hack/update/hugo_version && \ go run update_hugo_version.go) +.PHONY: update-cloud-spanner-emulator-version +update-cloud-spanner-emulator-version: + (cd hack/update/cloud_spanner_emulator_version && \ + go run update_cloud_spanner_emulator_version.go) + .PHONY: generate-licenses generate-licenses: ./hack/generate_licenses.sh diff --git a/hack/update/cloud_spanner_emulator_version/update_cloud_spanner_emulator_version.go b/hack/update/cloud_spanner_emulator_version/update_cloud_spanner_emulator_version.go new file mode 100644 index 0000000000..2dc0090893 --- /dev/null +++ b/hack/update/cloud_spanner_emulator_version/update_cloud_spanner_emulator_version.go @@ -0,0 +1,80 @@ +/* +Copyright 2023 The Kubernetes Authors All rights reserved. + +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. +*/ + +package main + +import ( + "context" + "fmt" + "strings" + "time" + + "golang.org/x/mod/semver" + "k8s.io/klog/v2" + + "k8s.io/minikube/hack/update" +) + +const ( + // default context timeout + cxTimeout = 5 * time.Minute +) + +var schema = map[string]update.Item{ + "pkg/minikube/assets/addons.go": { + Replace: map[string]string{ + `cloud-spanner-emulator/emulator:.*`: `cloud-spanner-emulator/emulator:{{.Version}}@{{.SHA}}",`, + }, + }, +} + +// Data holds stable cloud-spanner-emulator version in semver format. +type Data struct { + Version string + SHA string +} + +func main() { + // set a context with defined timeout + ctx, cancel := context.WithTimeout(context.Background(), cxTimeout) + defer cancel() + + // get cloud-spanner-emulator stable version + stable, err := cloudSpannerEmulatorVersion(ctx, "GoogleCloudPlatform", "cloud-spanner-emulator") + if err != nil { + klog.Fatalf("Unable to get cloud-spanner-emulator stable version: %v", err) + } + stable = strings.TrimPrefix(stable, "v") + sha, err := update.GetImageSHA(fmt.Sprintf("gcr.io/cloud-spanner-emulator/emulator:%s", stable)) + if err != nil { + klog.Fatalf("failed to get image SHA: %v", err) + } + + data := Data{Version: stable, SHA: sha} + klog.Infof("cloud-spanner-emulator stable version: %s", data.Version) + + update.Apply(schema, data) +} + +// cloudSpannerEmulatorVersion returns stable version in semver format. +func cloudSpannerEmulatorVersion(ctx context.Context, owner, repo string) (string, error) { + // get Golint version from GitHub Releases + stable, _, _, err := update.GHReleases(ctx, owner, repo) + if err != nil || !semver.IsValid(stable.Tag) { + return "", err + } + return stable.Tag, nil +} diff --git a/hack/update/golang_version/update_golang_version.go b/hack/update/golang_version/update_golang_version.go index 06698c4d1d..f60584d98e 100644 --- a/hack/update/golang_version/update_golang_version.go +++ b/hack/update/golang_version/update_golang_version.go @@ -110,6 +110,11 @@ var ( `GO_VERSION: .*`: `GO_VERSION: '{{.StableVersion}}'`, }, }, + ".github/workflows/update-cloud-spanner-emulator-version.yml": { + Replace: map[string]string{ + `GO_VERSION: .*`: `GO_VERSION: '{{.StableVersion}}'`, + }, + }, ".github/workflows/time-to-k8s-public-chart.yml": { Replace: map[string]string{ `GO_VERSION: .*`: `GO_VERSION: '{{.StableVersion}}'`, diff --git a/hack/update/image.go b/hack/update/image.go new file mode 100644 index 0000000000..5cf8533664 --- /dev/null +++ b/hack/update/image.go @@ -0,0 +1,39 @@ +/* +Copyright 2023 The Kubernetes Authors All rights reserved. + +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. +*/ + +package update + +import ( + "fmt" + "os/exec" + "strings" +) + +// GetImageSHA gets the SHA of the provided image +func GetImageSHA(image string) (string, error) { + if o, err := exec.Command("docker", "pull", image).CombinedOutput(); err != nil { + return "", fmt.Errorf("failed to pull image: %v: %s", err, o) + } + o, err := exec.Command("docker", "inspect", "--format={{index .RepoDigests 0}}", image).Output() + if err != nil { + return "", fmt.Errorf("failed to inspect image: %v: %s", err, o) + } + digest := strings.TrimSpace(string(o)) + if !strings.Contains(digest, "@") { + return "", fmt.Errorf("digest doesn't contain a SHA: %s", digest) + } + return strings.Split(digest, "@")[1], nil +}