diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 1f2a7d6..ad92b65 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -18,6 +18,7 @@ env: # step 'if env.XXX' != ""', so we copy these to succinctly test whether # credentials have been provided before trying to run steps that need them. UPBOUND_MARKETPLACE_PUSH_ROBOT_USR: ${{ secrets.UPBOUND_MARKETPLACE_PUSH_ROBOT_USR }} + AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }} jobs: detect-noop: runs-on: ubuntu-22.04 @@ -211,3 +212,19 @@ jobs: with: name: output path: _output/** + + - name: Publish Artifacts to S3 + run: make -j2 publish BRANCH_NAME=${GITHUB_REF##*/} + if: env.AWS_ACCESS_KEY_ID != '' + env: + AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }} + AWS_DEFAULT_REGION: us-east-1 + + - name: Promote Artifacts in S3 + if: github.ref == 'refs/heads/main' && env.AWS_ACCESS_KEY_ID != '' + run: make -j2 promote + env: + BRANCH_NAME: main + CHANNEL: main + AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }} + AWS_DEFAULT_REGION: us-east-1 diff --git a/.github/workflows/promote.yaml b/.github/workflows/promote.yaml new file mode 100644 index 0000000..7c6ca96 --- /dev/null +++ b/.github/workflows/promote.yaml @@ -0,0 +1,48 @@ +name: Promote + +on: + workflow_dispatch: + inputs: + version: + description: 'Release version (e.g. v0.1.0)' + required: true + channel: + description: 'Release channel' + required: true + default: 'alpha' + +env: + # Common versions + GO_VERSION: '1.19' + + # Common users. We can't run a step 'if secrets.XXX != ""' but we can run + # a step 'if env.XXX' != ""', so we copy these to succinctly test whether + # credentials have been provided before trying to run steps that need them. + AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }} + +jobs: + promote-artifacts: + runs-on: ubuntu-22.04 + + steps: + - name: Checkout + uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 # v4 + with: + submodules: true + + - name: Setup Go + uses: actions/setup-go@6edd4406fa81c3da01a34fa6f6343087c207a568 # v3 + with: + go-version: ${{ env.GO_VERSION }} + + - name: Fetch History + run: git fetch --prune --unshallow + + - name: Promote Artifacts in S3 + if: env.AWS_ACCESS_KEY_ID != '' + run: make -j2 promote BRANCH_NAME=${GITHUB_REF##*/} + env: + VERSION: ${{ github.event.inputs.version }} + CHANNEL: ${{ github.event.inputs.channel }} + AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }} + AWS_DEFAULT_REGION: us-east-1 diff --git a/Makefile b/Makefile index 512b7f2..3585f1a 100644 --- a/Makefile +++ b/Makefile @@ -12,6 +12,7 @@ PLATFORMS ?= linux_amd64 linux_arm64 darwin_amd64 darwin_arm64 # ==================================================================================== # Setup Output +S3_BUCKET ?= upbound.official-providers-ci.releases -include build/makelib/output.mk # ==================================================================================== @@ -21,7 +22,7 @@ GO_REQUIRED_VERSION = 1.19 # Uncomment below if you need to override the version. # GOLANGCILINT_VERSION ?= 1.54.0 -GO_STATIC_PACKAGES = $(GO_PROJECT)/cmd/uptest $(GO_PROJECT)/cmd/updoc $(GO_PROJECT)/cmd/ttr $(GO_PROJECT)/cmd/perf $(GO_PROJECT)/cmd/linter/lint-provider-family +GO_STATIC_PACKAGES = $(GO_PROJECT)/cmd/uptest $(GO_PROJECT)/cmd/crddiff $(GO_PROJECT)/cmd/updoc $(GO_PROJECT)/cmd/ttr $(GO_PROJECT)/cmd/perf $(GO_PROJECT)/cmd/linter/lint-provider-family GO_LDFLAGS += -X $(GO_PROJECT)/internal/version.Version=$(VERSION) GO_SUBDIRS += cmd internal GO111MODULE = on diff --git a/cmd/crddiff/main.go b/cmd/crddiff/main.go new file mode 100644 index 0000000..bad120e --- /dev/null +++ b/cmd/crddiff/main.go @@ -0,0 +1,94 @@ +// Copyright 2024 Upbound Inc. +// +// 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. + +// main package for the uptest tooling. +package main + +import ( + "log" + "os" + "syscall" + + "gopkg.in/alecthomas/kingpin.v2" + + "github.com/upbound/uptest/internal/crdschema" +) + +var ( + app = kingpin.New("crddiff", "A tool for checking breaking API changes between two CRD OpenAPI v3 schemas. The schemas can come from either two revisions of a CRD, or from the versions declared in a single CRD.").DefaultEnvars() + // crddiff sub-commands + cmdRevision = app.Command("revision", "Compare the first schema available in a base CRD against the first schema from a revision CRD") + cmdSelf = app.Command("self", "Use OpenAPI v3 schemas from a single CRD") +) + +var ( + revisionDiffOptions = getCRDdiffCommonOptions(cmdRevision) + selfDiffOptions = getCRDdiffCommonOptions(cmdSelf) +) + +func getCRDdiffCommonOptions(cmd *kingpin.CmdClause) *crdschema.CommonOptions { + opts := &crdschema.CommonOptions{} + cmd.Flag("enable-upjet-extensions", "Enables diff extensions for the CRDs generated by upjet. "+ + "An example extension is the processing of the x-kubernetes-validations CEL rules generated by upjet.").Default("false").BoolVar(&opts.EnableUpjetExtensions) + return opts +} + +func main() { + switch kingpin.MustParse(app.Parse(os.Args[1:])) { + case cmdRevision.FullCommand(): + crdDiffRevision() + case cmdSelf.FullCommand(): + crdDiffSelf() + } +} + +var ( + baseCRDPath = cmdRevision.Arg("base", "The manifest file path of the CRD to be used as the base").Required().ExistingFile() + revisionCRDPath = cmdRevision.Arg("revision", "The manifest file path of the CRD to be used as a revision to the base").Required().ExistingFile() +) + +func crdDiffRevision() { + crdDiff, err := crdschema.NewRevisionDiff(*baseCRDPath, *revisionCRDPath, crdschema.WithRevisionDiffCommonOptions(revisionDiffOptions)) + kingpin.FatalIfError(err, "Failed to load CRDs") + reportDiff(crdDiff) +} + +var ( + crdPath = cmdSelf.Arg("crd", "The manifest file path of the CRD whose versions are to be checked for breaking changes").Required().ExistingFile() +) + +func crdDiffSelf() { + crdDiff, err := crdschema.NewSelfDiff(*crdPath, crdschema.WithSelfDiffCommonOptions(selfDiffOptions)) + kingpin.FatalIfError(err, "Failed to load CRDs") + reportDiff(crdDiff) +} + +func reportDiff(crdDiff crdschema.SchemaCheck) { + versionMap, err := crdDiff.GetBreakingChanges() + kingpin.FatalIfError(err, "Failed to compute CRD breaking API changes") + + l := log.New(os.Stderr, "", 0) + breakingDetected := false + for v, d := range versionMap { + if d.Empty() { + continue + } + breakingDetected = true + l.Printf("Version %q:\n", v) + l.Println(crdschema.GetDiffReport(d)) + } + if breakingDetected { + syscall.Exit(1) + } +} diff --git a/cmd/uptest/main.go b/cmd/uptest/main.go index 076fd6c..5dac2d6 100644 --- a/cmd/uptest/main.go +++ b/cmd/uptest/main.go @@ -16,27 +16,21 @@ package main import ( - "log" "os" "path/filepath" "strings" - "syscall" "gopkg.in/alecthomas/kingpin.v2" "github.com/upbound/uptest/internal" "github.com/upbound/uptest/internal/config" - "github.com/upbound/uptest/internal/crdschema" ) var ( app = kingpin.New("uptest", "Automated Test Tool for Upbound Official Providers").DefaultEnvars() - // e2e command + // e2e command (single command is preserved for backward compatibility) + // and we may have further commands in the future. e2e = app.Command("e2e", "Run e2e tests for manifests by applying them to a control plane and waiting until a given condition is met.") - // crddiff command and sub-commands - cmdCRDDiff = app.Command("crddiff", "A tool for checking breaking API changes between two CRD OpenAPI v3 schemas. The schemas can come from either two revisions of a CRD, or from the versions declared in a single CRD.") - cmdRevision = cmdCRDDiff.Command("revision", "Compare the first schema available in a base CRD against the first schema from a revision CRD") - cmdSelf = cmdCRDDiff.Command("self", "Use OpenAPI v3 schemas from a single CRD") ) var ( @@ -59,26 +53,9 @@ var ( onlyCleanUptestResources = e2e.Flag("only-clean-uptest-resources", "While deletion step, only clean resources that were created by uptest").Default("false").Bool() ) -var ( - revisionDiffOptions = getCRDdiffCommonOptions(cmdRevision) - selfDiffOptions = getCRDdiffCommonOptions(cmdSelf) -) - -func getCRDdiffCommonOptions(cmd *kingpin.CmdClause) *crdschema.CommonOptions { - opts := &crdschema.CommonOptions{} - cmd.Flag("enable-upjet-extensions", "Enables diff extensions for the CRDs generated by upjet. "+ - "An example extension is the processing of the x-kubernetes-validations CEL rules generated by upjet.").Default("false").BoolVar(&opts.EnableUpjetExtensions) - return opts -} - func main() { - switch kingpin.MustParse(app.Parse(os.Args[1:])) { - case e2e.FullCommand(): + if kingpin.MustParse(app.Parse(os.Args[1:])) == e2e.FullCommand() { e2eTests() - case cmdRevision.FullCommand(): - crdDiffRevision() - case cmdSelf.FullCommand(): - crdDiffSelf() } } @@ -129,43 +106,3 @@ func e2eTests() { kingpin.FatalIfError(internal.RunTest(o), "cannot run e2e tests successfully") } - -var ( - baseCRDPath = cmdRevision.Arg("base", "The manifest file path of the CRD to be used as the base").Required().ExistingFile() - revisionCRDPath = cmdRevision.Arg("revision", "The manifest file path of the CRD to be used as a revision to the base").Required().ExistingFile() -) - -func crdDiffRevision() { - crdDiff, err := crdschema.NewRevisionDiff(*baseCRDPath, *revisionCRDPath, crdschema.WithRevisionDiffCommonOptions(revisionDiffOptions)) - kingpin.FatalIfError(err, "Failed to load CRDs") - reportDiff(crdDiff) -} - -var ( - crdPath = cmdSelf.Arg("crd", "The manifest file path of the CRD whose versions are to be checked for breaking changes").Required().ExistingFile() -) - -func crdDiffSelf() { - crdDiff, err := crdschema.NewSelfDiff(*crdPath, crdschema.WithSelfDiffCommonOptions(selfDiffOptions)) - kingpin.FatalIfError(err, "Failed to load CRDs") - reportDiff(crdDiff) -} - -func reportDiff(crdDiff crdschema.SchemaCheck) { - versionMap, err := crdDiff.GetBreakingChanges() - kingpin.FatalIfError(err, "Failed to compute CRD breaking API changes") - - l := log.New(os.Stderr, "", 0) - breakingDetected := false - for v, d := range versionMap { - if d.Empty() { - continue - } - breakingDetected = true - l.Printf("Version %q:\n", v) - l.Println(crdschema.GetDiffReport(d)) - } - if breakingDetected { - syscall.Exit(1) - } -}