diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index edcdd36c..1b1fe086 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -135,16 +135,6 @@ jobs: secrets: earthly_token: ${{ secrets.earthly_token }} - docs: - uses: input-output-hk/catalyst-forge/.github/workflows/docs.yml@master - needs: [discover, check, build, test] - if: (fromJson(needs.discover.outputs.earthfiles)['^docs(-.*)?$'] != null) && !failure() && !cancelled() - with: - earthfiles: ${{ toJson(fromJson(needs.discover.outputs.earthfiles)['^docs(-.*)?$']) }} - forge_version: ${{ inputs.forge_version }} - secrets: - earthly_token: ${{ secrets.earthly_token }} - release: uses: input-output-hk/catalyst-forge/.github/workflows/release.yml@master needs: [discover, check, build, test] diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml deleted file mode 100644 index 80361cee..00000000 --- a/.github/workflows/docs.yml +++ /dev/null @@ -1,104 +0,0 @@ -on: - workflow_call: - inputs: - earthfiles: - description: | - A JSON list of Earthfile paths+targets to use for publishing - required: true - type: string - forge_version: - description: | - The version of the forge CLI to install (use 'local' for testing) - required: true - type: string - local: - description: Forces local mode - required: false - type: string - default: "false" - target_args: - description: Extra arguments to pass to the target (if command is "run") - required: false - type: string - default: "" - verbosity: - description: The verbosity level to use - required: false - type: string - default: "info" - secrets: - earthly_token: - description: Optional Earthly token used to login to Earthly cloud during local builds of Forge CLI - required: false -env: - OUTPUT: ${{ github.workspace }}/output - -jobs: - run: - name: ${{ matrix.earthfile }} - runs-on: ubuntu-latest - strategy: - fail-fast: false - matrix: - earthfile: ${{ fromJson(inputs.earthfiles) }} - steps: - - uses: actions/checkout@v4 - - name: Install Forge - uses: input-output-hk/catalyst-forge/actions/install@master - if: ${{ inputs.forge_version != 'local' }} - with: - version: ${{ inputs.forge_version }} - - name: Install Local Forge - uses: input-output-hk/catalyst-forge/actions/install-local@master - if: ${{ inputs.forge_version == 'local' }} - with: - earthly_token: ${{ secrets.earthly_token }} - - name: Check forge version - id: local - run: | - forge version - - if [[ "${{ inputs.forge_version }}" == "local" ]]; then - echo "skip=true" >> $GITHUB_OUTPUT - else - echo "skip=false" >> $GITHUB_OUTPUT - fi - - name: Setup CI - uses: input-output-hk/catalyst-forge/actions/setup@master - with: - skip_earthly: ${{ steps.local.outputs.skip }} - - name: Run - uses: input-output-hk/catalyst-forge/actions/run@master - with: - command: run - args: --artifact ${{ env.OUTPUT }} ${{ matrix.earthfile }} - local: ${{ inputs.local }} - verbosity: ${{ inputs.verbosity }} - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - - name: Set env - run: | - GIT_BRANCH=${GITHUB_HEAD_REF:-${GITHUB_REF#refs/heads/}} - if [[ $GIT_BRANCH == "${{ github.event.repository.default_branch }}" ]]; then - DEST_DIR="/" - { - echo 'CLEAN_EXCLUDE<> "$GITHUB_ENV" - else - DEST_DIR="/branch/${GIT_BRANCH//[^a-zA-Z0-9_]/_}" - echo "CLEAN_EXCLUDE="/nothing"" >> $GITHUB_ENV - fi - echo "GIT_BRANCH=$GIT_BRANCH" >> $GITHUB_ENV - echo "DEST_DIR=$DEST_DIR" >> $GITHUB_ENV - - name: Publish docs - uses: JamesIves/github-pages-deploy-action@v4.6.4 - with: - clean: true - clean-exclude: | - ${{ env.CLEAN_EXCLUDE }} - single-commit: true - target-folder: ${{ env.DEST_DIR }} - folder: ${{ env.OUTPUT }}/linux/amd64 \ No newline at end of file diff --git a/.github/workflows/dogfood.yml b/.github/workflows/dogfood.yml index b2c9900b..8ec384f6 100644 --- a/.github/workflows/dogfood.yml +++ b/.github/workflows/dogfood.yml @@ -10,6 +10,7 @@ permissions: id-token: write contents: write packages: write + pull-requests: write jobs: ci: diff --git a/blueprint.cue b/blueprint.cue index 7455ad63..a3a18f73 100644 --- a/blueprint.cue +++ b/blueprint.cue @@ -10,6 +10,10 @@ global: { registries: [ "ghcr.io/input-output-hk/catalyst-forge", ] + release: docs: { + bucket: "docs.dev.projectcatalyst.io" + url: "https://docs.dev.projectcatalyst.io/" + } providers: { aws: { ecr: { diff --git a/cli/Earthfile b/cli/Earthfile index 605a25fe..58d7b59b 100644 --- a/cli/Earthfile +++ b/cli/Earthfile @@ -1,7 +1,7 @@ VERSION 0.8 deps: - FROM golang:1.24.0-bookworm + FROM golang:1.24.2-bookworm WORKDIR /work @@ -13,6 +13,7 @@ deps: CACHE --persist --sharing shared /go COPY ../lib/project+src/src /lib/project + COPY ../lib/providers+src/src /lib/providers COPY ../lib/schema+src/src /lib/schema COPY ../lib/tools+src/src /lib/tools diff --git a/cli/cmd/cmds/configure_satellite.go b/cli/cmd/cmds/configure_satellite.go index 37f19147..fce76b9b 100644 --- a/cli/cmd/cmds/configure_satellite.go +++ b/cli/cmd/cmds/configure_satellite.go @@ -7,8 +7,8 @@ import ( "github.com/input-output-hk/catalyst-forge/cli/pkg/earthly/satellite" "github.com/input-output-hk/catalyst-forge/cli/pkg/run" + "github.com/input-output-hk/catalyst-forge/lib/providers/git" "github.com/input-output-hk/catalyst-forge/lib/tools/fs/billy" - "github.com/input-output-hk/catalyst-forge/lib/tools/git" "github.com/input-output-hk/catalyst-forge/lib/tools/walker" ) diff --git a/cli/cmd/cmds/secret.go b/cli/cmd/cmds/secret.go index 15231cdd..53ab405d 100644 --- a/cli/cmd/cmds/secret.go +++ b/cli/cmd/cmds/secret.go @@ -7,7 +7,7 @@ import ( "github.com/input-output-hk/catalyst-forge/cli/pkg/run" "github.com/input-output-hk/catalyst-forge/cli/pkg/utils" - "github.com/input-output-hk/catalyst-forge/lib/project/secrets" + "github.com/input-output-hk/catalyst-forge/lib/providers/secrets" sc "github.com/input-output-hk/catalyst-forge/lib/schema/blueprint/common" "github.com/input-output-hk/catalyst-forge/lib/tools/fs" ) diff --git a/cli/cmd/main.go b/cli/cmd/main.go index a99ac0e6..625f790f 100644 --- a/cli/cmd/main.go +++ b/cli/cmd/main.go @@ -14,7 +14,7 @@ import ( "github.com/input-output-hk/catalyst-forge/cli/pkg/run" "github.com/input-output-hk/catalyst-forge/lib/project/deployment" "github.com/input-output-hk/catalyst-forge/lib/project/project" - "github.com/input-output-hk/catalyst-forge/lib/project/secrets" + "github.com/input-output-hk/catalyst-forge/lib/providers/secrets" schema "github.com/input-output-hk/catalyst-forge/lib/schema" "github.com/input-output-hk/catalyst-forge/lib/tools/walker" "github.com/posener/complete" diff --git a/cli/go.mod b/cli/go.mod index bb4bcf55..e0efeb3b 100644 --- a/cli/go.mod +++ b/cli/go.mod @@ -1,29 +1,27 @@ module github.com/input-output-hk/catalyst-forge/cli -go 1.23.0 +go 1.24.2 require ( cuelang.org/go v0.12.0 github.com/alecthomas/kong v0.9.0 - github.com/aws/aws-sdk-go v1.55.5 - github.com/aws/aws-sdk-go-v2 v1.32.6 - github.com/aws/aws-sdk-go-v2/config v1.27.40 - github.com/aws/aws-sdk-go-v2/service/ecr v1.36.7 + github.com/aws/aws-sdk-go-v2/service/ecr v1.46.0 + github.com/aws/aws-sdk-go-v2/service/s3 v1.84.1 github.com/charmbracelet/bubbles v0.20.0 github.com/charmbracelet/bubbletea v1.1.1 github.com/charmbracelet/lipgloss v0.13.0 github.com/charmbracelet/log v0.4.0 github.com/google/go-github/v66 v66.0.0 github.com/input-output-hk/catalyst-forge/lib/project v0.0.0 + github.com/input-output-hk/catalyst-forge/lib/providers v0.0.0-00010101000000-000000000000 github.com/input-output-hk/catalyst-forge/lib/schema v0.0.0 github.com/input-output-hk/catalyst-forge/lib/tools v0.0.0 - github.com/migueleliasweb/go-github-mock v1.0.1 github.com/posener/complete v1.2.3 github.com/rogpeppe/go-internal v1.13.2-0.20241226121412-a5dc8ff20d0a github.com/stretchr/testify v1.10.0 github.com/willabides/kongplete v0.4.0 golang.org/x/exp v0.0.0-20241009180824-f66d83c29e7c - kcl-lang.io/kpm v0.11.0 + gopkg.in/yaml.v3 v3.0.1 ) require ( @@ -46,18 +44,25 @@ require ( github.com/adrg/xdg v0.5.3 // indirect github.com/antlr/antlr4/runtime/Go/antlr/v4 v4.0.0-20230219212500-1f9a474cc2dc // indirect github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2 // indirect - github.com/aws/aws-sdk-go-v2/credentials v1.17.38 // indirect - github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.14 // indirect - github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.25 // indirect - github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.25 // indirect - github.com/aws/aws-sdk-go-v2/internal/ini v1.8.1 // indirect - github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.11.5 // indirect - github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.11.20 // indirect - github.com/aws/aws-sdk-go-v2/service/secretsmanager v1.33.4 // indirect - github.com/aws/aws-sdk-go-v2/service/sso v1.23.4 // indirect - github.com/aws/aws-sdk-go-v2/service/ssooidc v1.27.4 // indirect - github.com/aws/aws-sdk-go-v2/service/sts v1.31.4 // indirect - github.com/aws/smithy-go v1.22.1 // indirect + github.com/aws/aws-sdk-go v1.55.7 // indirect + github.com/aws/aws-sdk-go-v2 v1.36.6 // indirect + github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.6.11 // indirect + github.com/aws/aws-sdk-go-v2/config v1.29.18 // indirect + github.com/aws/aws-sdk-go-v2/credentials v1.17.71 // indirect + github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.33 // indirect + github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.37 // indirect + github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.37 // indirect + github.com/aws/aws-sdk-go-v2/internal/ini v1.8.3 // indirect + github.com/aws/aws-sdk-go-v2/internal/v4a v1.3.37 // indirect + github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.12.4 // indirect + github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.7.5 // indirect + github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.12.18 // indirect + github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.18.18 // indirect + github.com/aws/aws-sdk-go-v2/service/secretsmanager v1.35.8 // indirect + github.com/aws/aws-sdk-go-v2/service/sso v1.25.6 // indirect + github.com/aws/aws-sdk-go-v2/service/ssooidc v1.30.4 // indirect + github.com/aws/aws-sdk-go-v2/service/sts v1.34.1 // indirect + github.com/aws/smithy-go v1.22.4 // indirect github.com/aymanbagabas/go-osc52/v2 v2.0.1 // indirect github.com/beorn7/perks v1.0.1 // indirect github.com/bgentry/go-netrc v0.0.0-20140422174119-9fd32a8b3d3d // indirect @@ -125,7 +130,6 @@ require ( github.com/google/btree v1.0.1 // indirect github.com/google/gnostic-models v0.6.8 // indirect github.com/google/go-cmp v0.6.0 // indirect - github.com/google/go-github/v64 v64.0.0 // indirect github.com/google/go-querystring v1.1.0 // indirect github.com/google/gofuzz v1.2.0 // indirect github.com/google/s2a-go v0.1.7 // indirect @@ -242,7 +246,6 @@ require ( gopkg.in/evanphx/json-patch.v4 v4.12.0 // indirect gopkg.in/inf.v0 v0.9.1 // indirect gopkg.in/warnings.v0 v0.1.2 // indirect - gopkg.in/yaml.v3 v3.0.1 // indirect helm.sh/helm/v3 v3.17.0 // indirect k8s.io/api v0.32.2 // indirect k8s.io/apiextensions-apiserver v0.32.2 // indirect @@ -256,6 +259,7 @@ require ( k8s.io/kubectl v0.32.0 // indirect k8s.io/utils v0.0.0-20241104100929-3ea5e8cea738 // indirect kcl-lang.io/kcl-go v0.11.0 // indirect + kcl-lang.io/kpm v0.11.0 // indirect kcl-lang.io/lib v0.11.0 // indirect oras.land/oras-go v1.2.6 // indirect oras.land/oras-go/v2 v2.5.0 // indirect @@ -268,6 +272,8 @@ require ( replace github.com/input-output-hk/catalyst-forge/lib/project => ../lib/project +replace github.com/input-output-hk/catalyst-forge/lib/providers => ../lib/providers + replace github.com/input-output-hk/catalyst-forge/lib/schema => ../lib/schema replace github.com/input-output-hk/catalyst-forge/lib/tools => ../lib/tools diff --git a/cli/go.sum b/cli/go.sum index dcfef905..f6435af2 100644 --- a/cli/go.sum +++ b/cli/go.sum @@ -239,38 +239,48 @@ github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkY github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2 h1:DklsrG3dyBCFEj5IhUbnKptjxatkF07cF2ak3yi77so= github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2/go.mod h1:WaHUgvxTVq04UNunO+XhnAqY/wQc+bxr74GqbsZ/Jqw= github.com/aws/aws-sdk-go v1.44.122/go.mod h1:y4AeaBuwd2Lk+GepC1E9v0qOiTws0MIWAX4oIKwKHZo= -github.com/aws/aws-sdk-go v1.55.5 h1:KKUZBfBoyqy5d3swXyiC7Q76ic40rYcbqH7qjh59kzU= -github.com/aws/aws-sdk-go v1.55.5/go.mod h1:eRwEWoyTWFMVYVQzKMNHWP5/RV4xIUGMQfXQHfHkpNU= -github.com/aws/aws-sdk-go-v2 v1.32.6 h1:7BokKRgRPuGmKkFMhEg/jSul+tB9VvXhcViILtfG8b4= -github.com/aws/aws-sdk-go-v2 v1.32.6/go.mod h1:P5WJBrYqqbWVaOxgH0X/FYYD47/nooaPOZPlQdmiN2U= -github.com/aws/aws-sdk-go-v2/config v1.27.40 h1:sie4mPBGFOO+Z27+yHzvyN31G20h/bf2xb5mCbpLv2Q= -github.com/aws/aws-sdk-go-v2/config v1.27.40/go.mod h1:4KW7Aa5tNo+0VHnuLnnE1vPHtwMurlNZNS65IdcewHA= -github.com/aws/aws-sdk-go-v2/credentials v1.17.38 h1:iM90eRhCeZtlkzCNCG1JysOzJXGYf5rx80aD1lUgNDU= -github.com/aws/aws-sdk-go-v2/credentials v1.17.38/go.mod h1:TCVYPZeQuLaYNEkf/TVn6k5k/zdVZZ7xH9po548VNNg= -github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.14 h1:C/d03NAmh8C4BZXhuRNboF/DqhBkBCeDiJDcaqIT5pA= -github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.14/go.mod h1:7I0Ju7p9mCIdlrfS+JCgqcYD0VXz/N4yozsox+0o078= -github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.25 h1:s/fF4+yDQDoElYhfIVvSNyeCydfbuTKzhxSXDXCPasU= -github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.25/go.mod h1:IgPfDv5jqFIzQSNbUEMoitNooSMXjRSDkhXv8jiROvU= -github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.25 h1:ZntTCl5EsYnhN/IygQEUugpdwbhdkom9uHcbCftiGgA= -github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.25/go.mod h1:DBdPrgeocww+CSl1C8cEV8PN1mHMBhuCDLpXezyvWkE= -github.com/aws/aws-sdk-go-v2/internal/ini v1.8.1 h1:VaRN3TlFdd6KxX1x3ILT5ynH6HvKgqdiXoTxAF4HQcQ= -github.com/aws/aws-sdk-go-v2/internal/ini v1.8.1/go.mod h1:FbtygfRFze9usAadmnGJNc8KsP346kEe+y2/oyhGAGc= -github.com/aws/aws-sdk-go-v2/service/ecr v1.36.7 h1:R+5XKIJga2K9Dkj0/iQ6fD/MBGo02oxGGFTc512lK/Q= -github.com/aws/aws-sdk-go-v2/service/ecr v1.36.7/go.mod h1:fDPQV/6ONOQOjvtKhtypIy1wcGLcKYtoK/lvZ9fyDGQ= -github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.11.5 h1:QFASJGfT8wMXtuP3D5CRmMjARHv9ZmzFUMJznHDOY3w= -github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.11.5/go.mod h1:QdZ3OmoIjSX+8D1OPAzPxDfjXASbBMDsz9qvtyIhtik= -github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.11.20 h1:Xbwbmk44URTiHNx6PNo0ujDE6ERlsCKJD3u1zfnzAPg= -github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.11.20/go.mod h1:oAfOFzUB14ltPZj1rWwRc3d/6OgD76R8KlvU3EqM9Fg= -github.com/aws/aws-sdk-go-v2/service/secretsmanager v1.33.4 h1:EoPbZg+DGTRqKKhwk5uDviV9yvx65r1kyoNNC02ZH4Y= -github.com/aws/aws-sdk-go-v2/service/secretsmanager v1.33.4/go.mod h1:WyLS5qwXHtjKAONYZq/4ewdd+hcVsa3LBu77Ow5uj3k= -github.com/aws/aws-sdk-go-v2/service/sso v1.23.4 h1:ck/Y8XWNR1gHa4BFkwE3oSu7XDJGwl+8TI7E/RB2EcQ= -github.com/aws/aws-sdk-go-v2/service/sso v1.23.4/go.mod h1:XRlMvmad0ZNL+75C5FYdMvbbLkd6qiqz6foR1nA1PXY= -github.com/aws/aws-sdk-go-v2/service/ssooidc v1.27.4 h1:4f2/JKYZHAZbQ7koBpZ012bKi32NHPY0m7TDuJgsbug= -github.com/aws/aws-sdk-go-v2/service/ssooidc v1.27.4/go.mod h1:FnvDM4sfa+isJ3kDXIzAB9GAwVSzFzSy97uZ3IsHo4E= -github.com/aws/aws-sdk-go-v2/service/sts v1.31.4 h1:uK6dUUdJtqutK1XO/tmNaQMJiPLCJY/eAeOOmqQ6ygY= -github.com/aws/aws-sdk-go-v2/service/sts v1.31.4/go.mod h1:yMWe0F+XG0DkRZK5ODZhG7BEFYhLXi2dqGsv6tX0cgI= -github.com/aws/smithy-go v1.22.1 h1:/HPHZQ0g7f4eUeK6HKglFz8uwVfZKgoI25rb/J+dnro= -github.com/aws/smithy-go v1.22.1/go.mod h1:irrKGvNn1InZwb2d7fkIRNucdfwR8R+Ts3wxYa/cJHg= +github.com/aws/aws-sdk-go v1.55.7 h1:UJrkFq7es5CShfBwlWAC8DA077vp8PyVbQd3lqLiztE= +github.com/aws/aws-sdk-go v1.55.7/go.mod h1:eRwEWoyTWFMVYVQzKMNHWP5/RV4xIUGMQfXQHfHkpNU= +github.com/aws/aws-sdk-go-v2 v1.36.6 h1:zJqGjVbRdTPojeCGWn5IR5pbJwSQSBh5RWFTQcEQGdU= +github.com/aws/aws-sdk-go-v2 v1.36.6/go.mod h1:EYrzvCCN9CMUTa5+6lf6MM4tq3Zjp8UhSGR/cBsjai0= +github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.6.11 h1:12SpdwU8Djs+YGklkinSSlcrPyj3H4VifVsKf78KbwA= +github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.6.11/go.mod h1:dd+Lkp6YmMryke+qxW/VnKyhMBDTYP41Q2Bb+6gNZgY= +github.com/aws/aws-sdk-go-v2/config v1.29.18 h1:x4T1GRPnqKV8HMJOMtNktbpQMl3bIsfx8KbqmveUO2I= +github.com/aws/aws-sdk-go-v2/config v1.29.18/go.mod h1:bvz8oXugIsH8K7HLhBv06vDqnFv3NsGDt2Znpk7zmOU= +github.com/aws/aws-sdk-go-v2/credentials v1.17.71 h1:r2w4mQWnrTMJjOyIsZtGp3R3XGY3nqHn8C26C2lQWgA= +github.com/aws/aws-sdk-go-v2/credentials v1.17.71/go.mod h1:E7VF3acIup4GB5ckzbKFrCK0vTvEQxOxgdq4U3vcMCY= +github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.33 h1:D9ixiWSG4lyUBL2DDNK924Px9V/NBVpML90MHqyTADY= +github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.33/go.mod h1:caS/m4DI+cij2paz3rtProRBI4s/+TCiWoaWZuQ9010= +github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.37 h1:osMWfm/sC/L4tvEdQ65Gri5ZZDCUpuYJZbTTDrsn4I0= +github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.37/go.mod h1:ZV2/1fbjOPr4G4v38G3Ww5TBT4+hmsK45s/rxu1fGy0= +github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.37 h1:v+X21AvTb2wZ+ycg1gx+orkB/9U6L7AOp93R7qYxsxM= +github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.37/go.mod h1:G0uM1kyssELxmJ2VZEfG0q2npObR3BAkF3c1VsfVnfs= +github.com/aws/aws-sdk-go-v2/internal/ini v1.8.3 h1:bIqFDwgGXXN1Kpp99pDOdKMTTb5d2KyU5X/BZxjOkRo= +github.com/aws/aws-sdk-go-v2/internal/ini v1.8.3/go.mod h1:H5O/EsxDWyU+LP/V8i5sm8cxoZgc2fdNR9bxlOFrQTo= +github.com/aws/aws-sdk-go-v2/internal/v4a v1.3.37 h1:XTZZ0I3SZUHAtBLBU6395ad+VOblE0DwQP6MuaNeics= +github.com/aws/aws-sdk-go-v2/internal/v4a v1.3.37/go.mod h1:Pi6ksbniAWVwu2S8pEzcYPyhUkAcLaufxN7PfAUQjBk= +github.com/aws/aws-sdk-go-v2/service/ecr v1.46.0 h1:oyXvdONSO/VmFwEupTO+P5AFFghpNyM2MeYi7FARciM= +github.com/aws/aws-sdk-go-v2/service/ecr v1.46.0/go.mod h1:uDcrAwhZkHtPAFst5Wx7WSAhMi8BvVegEkc0Kg16vUM= +github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.12.4 h1:CXV68E2dNqhuynZJPB80bhPQwAKqBWVer887figW6Jc= +github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.12.4/go.mod h1:/xFi9KtvBXP97ppCz1TAEvU1Uf66qvid89rbem3wCzQ= +github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.7.5 h1:M5/B8JUaCI8+9QD+u3S/f4YHpvqE9RpSkV3rf0Iks2w= +github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.7.5/go.mod h1:Bktzci1bwdbpuLiu3AOksiNPMl/LLKmX1TWmqp2xbvs= +github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.12.18 h1:vvbXsA2TVO80/KT7ZqCbx934dt6PY+vQ8hZpUZ/cpYg= +github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.12.18/go.mod h1:m2JJHledjBGNMsLOF1g9gbAxprzq3KjC8e4lxtn+eWg= +github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.18.18 h1:OS2e0SKqsU2LiJPqL8u9x41tKc6MMEHrWjLVLn3oysg= +github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.18.18/go.mod h1:+Yrk+MDGzlNGxCXieljNeWpoZTCQUQVL+Jk9hGGJ8qM= +github.com/aws/aws-sdk-go-v2/service/s3 v1.84.1 h1:RkHXU9jP0DptGy7qKI8CBGsUJruWz0v5IgwBa2DwWcU= +github.com/aws/aws-sdk-go-v2/service/s3 v1.84.1/go.mod h1:3xAOf7tdKF+qbb+XpU+EPhNXAdun3Lu1RcDrj8KC24I= +github.com/aws/aws-sdk-go-v2/service/secretsmanager v1.35.8 h1:HD6R8K10gPbN9CNqRDOs42QombXlYeLOr4KkIxe2lQs= +github.com/aws/aws-sdk-go-v2/service/secretsmanager v1.35.8/go.mod h1:x66GdH8qjYTr6Kb4ik38Ewl6moLsg8igbceNsmxVxeA= +github.com/aws/aws-sdk-go-v2/service/sso v1.25.6 h1:rGtWqkQbPk7Bkwuv3NzpE/scwwL9sC1Ul3tn9x83DUI= +github.com/aws/aws-sdk-go-v2/service/sso v1.25.6/go.mod h1:u4ku9OLv4TO4bCPdxf4fA1upaMaJmP9ZijGk3AAOC6Q= +github.com/aws/aws-sdk-go-v2/service/ssooidc v1.30.4 h1:OV/pxyXh+eMA0TExHEC4jyWdumLxNbzz1P0zJoezkJc= +github.com/aws/aws-sdk-go-v2/service/ssooidc v1.30.4/go.mod h1:8Mm5VGYwtm+r305FfPSuc+aFkrypeylGYhFim6XEPoc= +github.com/aws/aws-sdk-go-v2/service/sts v1.34.1 h1:aUrLQwJfZtwv3/ZNG2xRtEen+NqI3iesuacjP51Mv1s= +github.com/aws/aws-sdk-go-v2/service/sts v1.34.1/go.mod h1:3wFBZKoWnX3r+Sm7in79i54fBmNfwhdNdQuscCw7QIk= +github.com/aws/smithy-go v1.22.4 h1:uqXzVZNuNexwc/xrh6Tb56u89WDlJY6HS+KC0S4QSjw= +github.com/aws/smithy-go v1.22.4/go.mod h1:t1ufH5HMublsJYulve2RKmHDC15xu1f26kHCp/HgceI= github.com/aymanbagabas/go-osc52/v2 v2.0.1 h1:HwpRHbFMcZLEVr42D4p7XBqjyuxQH5SMiErDT4WkJ2k= github.com/aymanbagabas/go-osc52/v2 v2.0.1/go.mod h1:uYgXzlJ7ZpABp8OJ+exZzJJhRNQ2ASbcXHWsFqH8hp8= github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= @@ -549,8 +559,6 @@ github.com/google/go-cmp v0.5.8/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeN github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= -github.com/google/go-github/v64 v64.0.0 h1:4G61sozmY3eiPAjjoOHponXDBONm+utovTKbyUb2Qdg= -github.com/google/go-github/v64 v64.0.0/go.mod h1:xB3vqMQNdHzilXBiO2I+M7iEFtHf+DP/omBOv6tQzVo= github.com/google/go-github/v66 v66.0.0 h1:ADJsaXj9UotwdgK8/iFZtv7MLc8E8WBl62WLd/D/9+M= github.com/google/go-github/v66 v66.0.0/go.mod h1:+4SO9Zkuyf8ytMj0csN1NR/5OTR+MfqPp8P8dVlcvY4= github.com/google/go-querystring v1.1.0 h1:AnCroh3fv4ZBgVIf1Iwtovgjaw/GiKJo8M8yD/fhyJ8= @@ -725,8 +733,6 @@ github.com/mattn/go-sqlite3 v1.14.24/go.mod h1:Uh1q+B4BYcTPb+yiD3kU8Ct7aC0hY9fxU github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= github.com/miekg/dns v1.1.57 h1:Jzi7ApEIzwEPLHWRcafCN9LZSBbqQpxjt/wpgvg7wcM= github.com/miekg/dns v1.1.57/go.mod h1:uqRjCRUuEAA6qsOiJvDd+CFo/vW+y5WR6SNmHE55hZk= -github.com/migueleliasweb/go-github-mock v1.0.1 h1:amLEECVny28RCD1ElALUpQxrAimamznkg9rN2O7t934= -github.com/migueleliasweb/go-github-mock v1.0.1/go.mod h1:8PJ7MpMoIiCBBNpuNmvndHm0QicjsE+hjex1yMGmjYQ= github.com/mitchellh/copystructure v1.2.0 h1:vpKXTN4ewci03Vljg/q9QvCGUDttBOGBIa15WveJJGw= github.com/mitchellh/copystructure v1.2.0/go.mod h1:qLl+cE2AmVv+CoeAwDPye/v+N2HKCj9FbZEVFJRxO9s= github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y= diff --git a/cli/pkg/earthly/earthly.go b/cli/pkg/earthly/earthly.go index c29f10d8..4fbb0785 100644 --- a/cli/pkg/earthly/earthly.go +++ b/cli/pkg/earthly/earthly.go @@ -10,7 +10,7 @@ import ( "strings" "github.com/input-output-hk/catalyst-forge/cli/pkg/executor" - secretstore "github.com/input-output-hk/catalyst-forge/lib/project/secrets" + secretstore "github.com/input-output-hk/catalyst-forge/lib/providers/secrets" sc "github.com/input-output-hk/catalyst-forge/lib/schema/blueprint/common" ) diff --git a/cli/pkg/earthly/earthly_test.go b/cli/pkg/earthly/earthly_test.go index 40ba97d3..f4e45221 100644 --- a/cli/pkg/earthly/earthly_test.go +++ b/cli/pkg/earthly/earthly_test.go @@ -6,8 +6,8 @@ import ( "testing" emocks "github.com/input-output-hk/catalyst-forge/cli/pkg/executor/mocks" - "github.com/input-output-hk/catalyst-forge/lib/project/secrets" - smocks "github.com/input-output-hk/catalyst-forge/lib/project/secrets/mocks" + "github.com/input-output-hk/catalyst-forge/lib/providers/secrets" + smocks "github.com/input-output-hk/catalyst-forge/lib/providers/secrets/mocks" sc "github.com/input-output-hk/catalyst-forge/lib/schema/blueprint/common" "github.com/input-output-hk/catalyst-forge/lib/tools/testutils" "github.com/stretchr/testify/assert" diff --git a/cli/pkg/earthly/project.go b/cli/pkg/earthly/project.go index 3c46f297..c1685523 100644 --- a/cli/pkg/earthly/project.go +++ b/cli/pkg/earthly/project.go @@ -10,7 +10,7 @@ import ( "github.com/input-output-hk/catalyst-forge/cli/pkg/executor" "github.com/input-output-hk/catalyst-forge/cli/pkg/run" "github.com/input-output-hk/catalyst-forge/lib/project/project" - "github.com/input-output-hk/catalyst-forge/lib/project/secrets" + "github.com/input-output-hk/catalyst-forge/lib/providers/secrets" "github.com/input-output-hk/catalyst-forge/lib/schema" sp "github.com/input-output-hk/catalyst-forge/lib/schema/blueprint/project" ) diff --git a/cli/pkg/earthly/project_test.go b/cli/pkg/earthly/project_test.go index 3b71b032..c089871f 100644 --- a/cli/pkg/earthly/project_test.go +++ b/cli/pkg/earthly/project_test.go @@ -10,8 +10,8 @@ import ( "github.com/input-output-hk/catalyst-forge/cli/pkg/run" "github.com/input-output-hk/catalyst-forge/lib/project/blueprint" "github.com/input-output-hk/catalyst-forge/lib/project/project" - "github.com/input-output-hk/catalyst-forge/lib/project/secrets" - smocks "github.com/input-output-hk/catalyst-forge/lib/project/secrets/mocks" + "github.com/input-output-hk/catalyst-forge/lib/providers/secrets" + smocks "github.com/input-output-hk/catalyst-forge/lib/providers/secrets/mocks" schema "github.com/input-output-hk/catalyst-forge/lib/schema/blueprint" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" diff --git a/cli/pkg/earthly/satellite/satellite.go b/cli/pkg/earthly/satellite/satellite.go index 574dff61..8896388a 100644 --- a/cli/pkg/earthly/satellite/satellite.go +++ b/cli/pkg/earthly/satellite/satellite.go @@ -7,8 +7,8 @@ import ( "path/filepath" "github.com/input-output-hk/catalyst-forge/lib/project/project" - "github.com/input-output-hk/catalyst-forge/lib/project/providers" - "github.com/input-output-hk/catalyst-forge/lib/project/secrets" + "github.com/input-output-hk/catalyst-forge/lib/providers/earthly" + "github.com/input-output-hk/catalyst-forge/lib/providers/secrets" "github.com/input-output-hk/catalyst-forge/lib/tools/fs" "github.com/input-output-hk/catalyst-forge/lib/tools/fs/billy" "gopkg.in/yaml.v3" @@ -17,7 +17,7 @@ import ( // EarthlySatellite is used to configure the local system to use a remote Earthly Satellite. type EarthlySatellite struct { ci bool - creds providers.EarthlyProviderCreds + creds earthly.EarthlyProviderCreds fs fs.Filesystem logger *slog.Logger path string @@ -104,7 +104,7 @@ func (s *EarthlySatellite) loadCredentials() error { return fmt.Errorf("no satellite credentials found") } - creds, err := providers.GetEarthlyProviderCreds( + creds, err := earthly.GetEarthlyProviderCreds( s.project.Blueprint.Global.Ci.Providers.Earthly.Satellite.Credentials, &s.secretStore, s.logger, diff --git a/cli/pkg/earthly/satellite/satellite_test.go b/cli/pkg/earthly/satellite/satellite_test.go index 9a0173fb..3450e910 100644 --- a/cli/pkg/earthly/satellite/satellite_test.go +++ b/cli/pkg/earthly/satellite/satellite_test.go @@ -8,8 +8,8 @@ import ( "github.com/input-output-hk/catalyst-forge/cli/internal/testutils" "github.com/input-output-hk/catalyst-forge/lib/project/project" - "github.com/input-output-hk/catalyst-forge/lib/project/secrets" - smocks "github.com/input-output-hk/catalyst-forge/lib/project/secrets/mocks" + "github.com/input-output-hk/catalyst-forge/lib/providers/secrets" + smocks "github.com/input-output-hk/catalyst-forge/lib/providers/secrets/mocks" sb "github.com/input-output-hk/catalyst-forge/lib/schema/blueprint" sc "github.com/input-output-hk/catalyst-forge/lib/schema/blueprint/common" sg "github.com/input-output-hk/catalyst-forge/lib/schema/blueprint/global" diff --git a/cli/pkg/events/merge.go b/cli/pkg/events/merge.go index 60a1cf0e..0a3cbed3 100644 --- a/cli/pkg/events/merge.go +++ b/cli/pkg/events/merge.go @@ -6,7 +6,8 @@ import ( "cuelang.org/go/cue" "github.com/input-output-hk/catalyst-forge/lib/project/project" - "github.com/input-output-hk/catalyst-forge/lib/tools/git" + "github.com/input-output-hk/catalyst-forge/lib/providers/git" + "github.com/input-output-hk/catalyst-forge/lib/providers/github" ) // MergeEvent fires when a merge occurs to the default branch. @@ -20,7 +21,12 @@ type MergeEventConfig struct { } func (m *MergeEvent) Firing(p *project.Project, config cue.Value) (bool, error) { - branch, err := git.GetBranch(p.Repo) + gc, err := github.NewDefaultGithubClient("", "") + if err != nil { + return false, fmt.Errorf("failed to create github client: %w", err) + } + + branch, err := git.GetBranch(gc, p.Repo) if err != nil { return false, fmt.Errorf("failed to get branch: %w", err) } diff --git a/cli/pkg/events/tag_test.go b/cli/pkg/events/tag_test.go index 27ae6bd0..5a436e07 100644 --- a/cli/pkg/events/tag_test.go +++ b/cli/pkg/events/tag_test.go @@ -5,7 +5,7 @@ import ( "cuelang.org/go/cue" "github.com/input-output-hk/catalyst-forge/lib/project/project" - "github.com/input-output-hk/catalyst-forge/lib/project/secrets" + "github.com/input-output-hk/catalyst-forge/lib/providers/secrets" schema "github.com/input-output-hk/catalyst-forge/lib/schema/blueprint" "github.com/input-output-hk/catalyst-forge/lib/tools/testutils" "github.com/stretchr/testify/assert" diff --git a/cli/pkg/providers/kcl/client.go b/cli/pkg/providers/kcl/client.go deleted file mode 100644 index 9adef295..00000000 --- a/cli/pkg/providers/kcl/client.go +++ /dev/null @@ -1,73 +0,0 @@ -package kcl - -import ( - "bytes" - "fmt" - - kpm "kcl-lang.io/kpm/pkg/client" -) - -//go:generate go run github.com/matryer/moq@latest -skip-ensure -pkg mocks -out mocks/kcl.go . KCLClient - -type KCLClient interface { - Run(KCLModuleArgs) (string, error) - Log() string -} - -type DefaultKCLClient struct { - logOutput bytes.Buffer -} - -func (k DefaultKCLClient) Run(args KCLModuleArgs) (string, error) { - client, err := kpm.NewKpmClient() - if err != nil { - return "", fmt.Errorf("failed to create KPM client: %w", err) - } - - client.SetLogWriter(&k.logOutput) - - out, err := client.Run( - kpm.WithRunSourceUrl(fmt.Sprintf("oci://%s?tag=%s", args.Module, args.Version)), - kpm.WithArguments(args.Serialize()), - ) - - if err != nil { - return "", fmt.Errorf("failed to run KCL module: %w", err) - } - - return out.GetRawYamlResult(), nil -} - -func (k DefaultKCLClient) Log() string { - return k.logOutput.String() -} - -// KCLModuleArgs contains the arguments to pass to the KCL module. -type KCLModuleArgs struct { - // InstanceName is the name to use for the deployment instance. - InstanceName string - - // Module is the name of the OCI module to deploy. - Module string - - // Namespace is the namespace to deploy the module to. - Namespace string - - // Values contains the values to pass to the module. - Values string - - // Version is the version of the module to deploy. - Version string -} - -// Serialize serializes the KCLModuleArgs to a list of arguments. -func (k *KCLModuleArgs) Serialize() []string { - return []string{ - "-D", - fmt.Sprintf("name=%s", k.InstanceName), - "-D", - fmt.Sprintf("namespace=%s", k.Namespace), - "-D", - fmt.Sprintf("values=%s", k.Values), - } -} diff --git a/cli/pkg/providers/kcl/mocks/kcl.go b/cli/pkg/providers/kcl/mocks/kcl.go deleted file mode 100644 index f65a1879..00000000 --- a/cli/pkg/providers/kcl/mocks/kcl.go +++ /dev/null @@ -1,108 +0,0 @@ -// Code generated by moq; DO NOT EDIT. -// github.com/matryer/moq - -package mocks - -import ( - "github.com/input-output-hk/catalyst-forge/cli/pkg/providers/kcl" - "sync" -) - -// KCLClientMock is a mock implementation of kcl.KCLClient. -// -// func TestSomethingThatUsesKCLClient(t *testing.T) { -// -// // make and configure a mocked kcl.KCLClient -// mockedKCLClient := &KCLClientMock{ -// LogFunc: func() string { -// panic("mock out the Log method") -// }, -// RunFunc: func(kCLModuleArgs kcl.KCLModuleArgs) (string, error) { -// panic("mock out the Run method") -// }, -// } -// -// // use mockedKCLClient in code that requires kcl.KCLClient -// // and then make assertions. -// -// } -type KCLClientMock struct { - // LogFunc mocks the Log method. - LogFunc func() string - - // RunFunc mocks the Run method. - RunFunc func(kCLModuleArgs kcl.KCLModuleArgs) (string, error) - - // calls tracks calls to the methods. - calls struct { - // Log holds details about calls to the Log method. - Log []struct { - } - // Run holds details about calls to the Run method. - Run []struct { - // KCLModuleArgs is the kCLModuleArgs argument value. - KCLModuleArgs kcl.KCLModuleArgs - } - } - lockLog sync.RWMutex - lockRun sync.RWMutex -} - -// Log calls LogFunc. -func (mock *KCLClientMock) Log() string { - if mock.LogFunc == nil { - panic("KCLClientMock.LogFunc: method is nil but KCLClient.Log was just called") - } - callInfo := struct { - }{} - mock.lockLog.Lock() - mock.calls.Log = append(mock.calls.Log, callInfo) - mock.lockLog.Unlock() - return mock.LogFunc() -} - -// LogCalls gets all the calls that were made to Log. -// Check the length with: -// -// len(mockedKCLClient.LogCalls()) -func (mock *KCLClientMock) LogCalls() []struct { -} { - var calls []struct { - } - mock.lockLog.RLock() - calls = mock.calls.Log - mock.lockLog.RUnlock() - return calls -} - -// Run calls RunFunc. -func (mock *KCLClientMock) Run(kCLModuleArgs kcl.KCLModuleArgs) (string, error) { - if mock.RunFunc == nil { - panic("KCLClientMock.RunFunc: method is nil but KCLClient.Run was just called") - } - callInfo := struct { - KCLModuleArgs kcl.KCLModuleArgs - }{ - KCLModuleArgs: kCLModuleArgs, - } - mock.lockRun.Lock() - mock.calls.Run = append(mock.calls.Run, callInfo) - mock.lockRun.Unlock() - return mock.RunFunc(kCLModuleArgs) -} - -// RunCalls gets all the calls that were made to Run. -// Check the length with: -// -// len(mockedKCLClient.RunCalls()) -func (mock *KCLClientMock) RunCalls() []struct { - KCLModuleArgs kcl.KCLModuleArgs -} { - var calls []struct { - KCLModuleArgs kcl.KCLModuleArgs - } - mock.lockRun.RLock() - calls = mock.calls.Run - mock.lockRun.RUnlock() - return calls -} diff --git a/cli/pkg/release/providers/common.go b/cli/pkg/release/providers/common.go index 3664fca7..bc20d354 100644 --- a/cli/pkg/release/providers/common.go +++ b/cli/pkg/release/providers/common.go @@ -6,8 +6,8 @@ import ( "regexp" "strings" - "github.com/input-output-hk/catalyst-forge/cli/pkg/providers/aws" "github.com/input-output-hk/catalyst-forge/lib/project/project" + "github.com/input-output-hk/catalyst-forge/lib/providers/aws" s "github.com/input-output-hk/catalyst-forge/lib/schema" ) @@ -27,7 +27,7 @@ func createECRRepoIfNotExists(client aws.ECRClient, p *project.Project, registry if !exists { logger.Info("ECR repository does not exist, creating", "name", name) - if err := client.CreateECRRepository(p, name); err != nil { + if err := client.CreateECRRepository(name, p.Blueprint.Global.Repo.Name, p.Path); err != nil { return fmt.Errorf("failed to create ECR repository: %w", err) } } diff --git a/cli/pkg/release/providers/common_test.go b/cli/pkg/release/providers/common_test.go index c9fc3e02..4ffabb55 100644 --- a/cli/pkg/release/providers/common_test.go +++ b/cli/pkg/release/providers/common_test.go @@ -6,9 +6,9 @@ import ( "testing" "github.com/aws/aws-sdk-go-v2/service/ecr" - "github.com/input-output-hk/catalyst-forge/cli/pkg/providers/aws" - "github.com/input-output-hk/catalyst-forge/cli/pkg/providers/aws/mocks" "github.com/input-output-hk/catalyst-forge/lib/project/project" + "github.com/input-output-hk/catalyst-forge/lib/providers/aws" + "github.com/input-output-hk/catalyst-forge/lib/providers/aws/mocks" sb "github.com/input-output-hk/catalyst-forge/lib/schema/blueprint" sg "github.com/input-output-hk/catalyst-forge/lib/schema/blueprint/global" "github.com/input-output-hk/catalyst-forge/lib/tools/testutils" diff --git a/cli/pkg/release/providers/cue.go b/cli/pkg/release/providers/cue.go index fb171086..3477d7bc 100644 --- a/cli/pkg/release/providers/cue.go +++ b/cli/pkg/release/providers/cue.go @@ -11,9 +11,9 @@ import ( "cuelang.org/go/cue/cuecontext" "github.com/input-output-hk/catalyst-forge/cli/pkg/events" "github.com/input-output-hk/catalyst-forge/cli/pkg/executor" - "github.com/input-output-hk/catalyst-forge/cli/pkg/providers/aws" "github.com/input-output-hk/catalyst-forge/cli/pkg/run" "github.com/input-output-hk/catalyst-forge/lib/project/project" + "github.com/input-output-hk/catalyst-forge/lib/providers/aws" "github.com/input-output-hk/catalyst-forge/lib/schema" sp "github.com/input-output-hk/catalyst-forge/lib/schema/blueprint/project" lc "github.com/input-output-hk/catalyst-forge/lib/tools/cue" diff --git a/cli/pkg/release/providers/cue_test.go b/cli/pkg/release/providers/cue_test.go index 61620a2d..0bf198cb 100644 --- a/cli/pkg/release/providers/cue_test.go +++ b/cli/pkg/release/providers/cue_test.go @@ -9,9 +9,9 @@ import ( "github.com/aws/aws-sdk-go-v2/service/ecr" exmocks "github.com/input-output-hk/catalyst-forge/cli/pkg/executor/mocks" - "github.com/input-output-hk/catalyst-forge/cli/pkg/providers/aws" - "github.com/input-output-hk/catalyst-forge/cli/pkg/providers/aws/mocks" "github.com/input-output-hk/catalyst-forge/lib/project/project" + "github.com/input-output-hk/catalyst-forge/lib/providers/aws" + "github.com/input-output-hk/catalyst-forge/lib/providers/aws/mocks" sb "github.com/input-output-hk/catalyst-forge/lib/schema/blueprint" sg "github.com/input-output-hk/catalyst-forge/lib/schema/blueprint/global" spr "github.com/input-output-hk/catalyst-forge/lib/schema/blueprint/global/providers" diff --git a/cli/pkg/release/providers/docker.go b/cli/pkg/release/providers/docker.go index bc29a9da..f2205ad2 100644 --- a/cli/pkg/release/providers/docker.go +++ b/cli/pkg/release/providers/docker.go @@ -8,9 +8,9 @@ import ( "github.com/input-output-hk/catalyst-forge/cli/pkg/earthly" "github.com/input-output-hk/catalyst-forge/cli/pkg/events" "github.com/input-output-hk/catalyst-forge/cli/pkg/executor" - "github.com/input-output-hk/catalyst-forge/cli/pkg/providers/aws" "github.com/input-output-hk/catalyst-forge/cli/pkg/run" "github.com/input-output-hk/catalyst-forge/lib/project/project" + "github.com/input-output-hk/catalyst-forge/lib/providers/aws" sp "github.com/input-output-hk/catalyst-forge/lib/schema/blueprint/project" ) diff --git a/cli/pkg/release/providers/docker_test.go b/cli/pkg/release/providers/docker_test.go index ffb0a1d8..d116cb07 100644 --- a/cli/pkg/release/providers/docker_test.go +++ b/cli/pkg/release/providers/docker_test.go @@ -8,9 +8,9 @@ import ( "github.com/aws/aws-sdk-go-v2/service/ecr" exmocks "github.com/input-output-hk/catalyst-forge/cli/pkg/executor/mocks" - "github.com/input-output-hk/catalyst-forge/cli/pkg/providers/aws" - "github.com/input-output-hk/catalyst-forge/cli/pkg/providers/aws/mocks" "github.com/input-output-hk/catalyst-forge/lib/project/project" + "github.com/input-output-hk/catalyst-forge/lib/providers/aws" + "github.com/input-output-hk/catalyst-forge/lib/providers/aws/mocks" sb "github.com/input-output-hk/catalyst-forge/lib/schema/blueprint" sg "github.com/input-output-hk/catalyst-forge/lib/schema/blueprint/global" sp "github.com/input-output-hk/catalyst-forge/lib/schema/blueprint/project" diff --git a/cli/pkg/release/providers/docs.go b/cli/pkg/release/providers/docs.go new file mode 100644 index 00000000..2e435c29 --- /dev/null +++ b/cli/pkg/release/providers/docs.go @@ -0,0 +1,321 @@ +package providers + +import ( + "fmt" + "log/slog" + "net/url" + "path/filepath" + "slices" + "strings" + + "github.com/input-output-hk/catalyst-forge/cli/pkg/earthly" + "github.com/input-output-hk/catalyst-forge/cli/pkg/events" + "github.com/input-output-hk/catalyst-forge/cli/pkg/run" + "github.com/input-output-hk/catalyst-forge/lib/project/project" + "github.com/input-output-hk/catalyst-forge/lib/providers/aws" + "github.com/input-output-hk/catalyst-forge/lib/providers/git" + "github.com/input-output-hk/catalyst-forge/lib/providers/github" + sp "github.com/input-output-hk/catalyst-forge/lib/schema/blueprint/project" + "github.com/input-output-hk/catalyst-forge/lib/tools/fs" + "github.com/input-output-hk/catalyst-forge/lib/tools/fs/billy" +) + +const ( + docsCommentPrefix = "" + bodyTemplate = ` +%s +## 📚 Docs Preview + +The docs for this PR can be previewed at the following URL: + +%s +` +) + +// DocsReleaserConfig is the configuration for the docs release. +type DocsReleaserConfig struct { + Name string `json:"name"` +} + +// DocsReleaser is a provider that releases the docs for a project. +type DocsReleaser struct { + config DocsReleaserConfig + force bool + fs fs.Filesystem + ghClient github.GithubClient + handler events.EventHandler + logger *slog.Logger + project *project.Project + release sp.Release + releaseName string + runner earthly.ProjectRunner + s3 aws.S3Client + workdir string +} + +// Release runs the docs release. +func (r *DocsReleaser) Release() error { + r.logger.Info("Running docs release target", "project", r.project.Name, "target", r.release.Target, "dir", r.workdir) + if err := r.run(r.workdir); err != nil { + return fmt.Errorf("failed to run docs release target: %w", err) + } + + if err := r.validateArtifacts(r.workdir); err != nil { + return fmt.Errorf("failed to validate artifacts: %w", err) + } + + if !r.handler.Firing(r.project, r.project.GetReleaseEvents(r.releaseName)) && !r.force { + r.logger.Info("No release event is firing, skipping release") + return nil + } + + if r.project.Blueprint.Global.Ci == nil || r.project.Blueprint.Global.Ci.Release == nil || r.project.Blueprint.Global.Ci.Release.Docs == nil { + return fmt.Errorf("global docs release configuration not found") + } + + projectName := r.config.Name + if projectName == "" { + projectName = r.project.Name + } + + docsConfig := r.project.Blueprint.Global.Ci.Release.Docs + if docsConfig.Bucket == "" { + return fmt.Errorf("no S3 bucket specified in global docs configuration") + } + + s3Path, err := r.generatePath(projectName) + if err != nil { + return fmt.Errorf("failed to generate S3 path: %w", err) + } + + r.logger.Info("Cleaning existing docs from S3", "bucket", docsConfig.Bucket, "path", s3Path) + if err := r.s3.DeleteDirectory(docsConfig.Bucket, s3Path, []string{".*/b/.*"}); err != nil { + return fmt.Errorf("failed to clean existing docs from S3: %w", err) + } + + finalPath := filepath.Join(r.workdir, earthly.GetBuildPlatform()) + r.logger.Info("Uploading docs to S3", "bucket", docsConfig.Bucket, "path", s3Path) + if err := r.s3.UploadDirectory(docsConfig.Bucket, s3Path, finalPath, r.fs); err != nil { + return fmt.Errorf("failed to upload docs to S3: %w", err) + } + + if github.InCI() { + url := r.project.Blueprint.Global.Ci.Release.Docs.Url + if err := r.postComment(url, projectName); err != nil { + return fmt.Errorf("failed to post comment: %w", err) + } + + isDefault, err := r.isDefaultBranch() + if err != nil { + return fmt.Errorf("failed to check if branch is default: %w", err) + } + + if isDefault { + if err := r.cleanupBranches(docsConfig.Bucket, filepath.Join(s3Path, "b")); err != nil { + return fmt.Errorf("failed to cleanup branches: %w", err) + } + } + + } + + r.logger.Info("Docs release complete") + return nil +} + +// cleanupBranches deletes branches from S3 that are no longer present in GitHub. +func (r *DocsReleaser) cleanupBranches(bucket, path string) error { + branches, err := r.ghClient.ListBranches() + if err != nil { + return fmt.Errorf("failed to list GitHub branches: %w", err) + } + + var branchNames []string + for _, branch := range branches { + branchNames = append(branchNames, branch.Name) + } + + children, err := r.s3.ListImmediateChildren(bucket, path) + if err != nil { + return fmt.Errorf("failed to list immediate children: %w", err) + } + + for _, child := range children { + if !slices.Contains(branchNames, child) { + r.logger.Info("Deleting branch", "branch", child) + if err := r.s3.DeleteDirectory(bucket, filepath.Join(path, child), nil); err != nil { + return fmt.Errorf("failed to delete branch: %w", err) + } + } + } + + return nil +} + +// generatePath generates the S3 path for the docs. +func (r *DocsReleaser) generatePath(projectName string) (string, error) { + docsConfig := r.project.Blueprint.Global.Ci.Release.Docs + if docsConfig.Bucket == "" { + return "", fmt.Errorf("no S3 bucket specified in global docs configuration") + } + + s3Path := projectName + if docsConfig.Path != "" { + s3Path = filepath.Join(docsConfig.Path, projectName) + } + + branch, err := git.GetBranch(r.ghClient, r.project.Repo) + if err != nil { + return "", fmt.Errorf("failed to get branch: %w", err) + } + + if branch == r.project.Blueprint.Global.Repo.DefaultBranch { + return s3Path, nil + } + + return filepath.Join(s3Path, "b", branch), nil +} + +// isDefaultBranch returns true if the current branch is the default branch. +func (r *DocsReleaser) isDefaultBranch() (bool, error) { + branch, err := git.GetBranch(r.ghClient, r.project.Repo) + if err != nil { + return false, fmt.Errorf("failed to get branch: %w", err) + } + + return branch == r.project.Blueprint.Global.Repo.DefaultBranch, nil +} + +// postComment posts a comment to the PR. +func (r *DocsReleaser) postComment(baseURL, name string) error { + if r.ghClient.Env().IsPR() { + pr := r.ghClient.Env().GetPRNumber() + if pr == 0 { + r.logger.Warn("No PR number found, skipping comment") + return nil + } + + comments, err := r.ghClient.ListPullRequestComments(pr) + if err != nil { + return fmt.Errorf("failed to list comments: %w", err) + } + + for _, comment := range comments { + if comment.Author == "github-actions[bot]" && strings.Contains(comment.Body, docsCommentPrefix) { + r.logger.Info("Found existing comment, skipping ") + return nil + } + } + + branch, err := git.GetBranch(r.ghClient, r.project.Repo) + if err != nil { + return fmt.Errorf("failed to get branch: %w", err) + } + + var docURL string + if branch == r.project.Blueprint.Global.Repo.DefaultBranch { + docURL, err = url.JoinPath(baseURL, name) + } else { + docURL, err = url.JoinPath(baseURL, name, "b", branch) + } + if err != nil { + return fmt.Errorf("failed to join URL path: %w", err) + } + + body := fmt.Sprintf(bodyTemplate, docsCommentPrefix, docURL) + if err := r.ghClient.PostPullRequestComment(pr, body); err != nil { + return fmt.Errorf("failed to post comment to PR: %w", err) + } + } else { + r.logger.Info("No PR found, skipping comment") + } + + return nil +} + +// run runs the docs release target. +func (r *DocsReleaser) run(path string) error { + return r.runner.RunTarget( + r.release.Target, + earthly.WithArtifact(path), + ) +} + +// validateArtifacts validates that the expected artifacts exist. +func (r *DocsReleaser) validateArtifacts(path string) error { + r.logger.Info("Validating docs artifacts", "path", path) + exists, err := r.fs.Exists(path) + if err != nil { + return fmt.Errorf("failed to check if output folder exists: %w", err) + } else if !exists { + return fmt.Errorf("unable to find output folder: %s", path) + } + + children, err := r.fs.ReadDir(path) + if err != nil { + return fmt.Errorf("failed to read output folder: %w", err) + } + + if len(children) == 0 { + return fmt.Errorf("no docs artifacts found") + } + + return nil +} + +// NewDocsReleaser creates a new docs release provider. +func NewDocsReleaser( + ctx run.RunContext, + project project.Project, + name string, + force bool, +) (*DocsReleaser, error) { + release, ok := project.Blueprint.Project.Release[name] + if !ok { + return nil, fmt.Errorf("unknown release: %s", name) + } + + var config DocsReleaserConfig + if err := parseConfig(&project, name, &config); err != nil { + return nil, fmt.Errorf("failed to parse release config: %w", err) + } + + fs := billy.NewBaseOsFS() + workdir, err := fs.TempDir("", "catalyst-forge-docs-") + if err != nil { + return nil, fmt.Errorf("failed to create temporary directory: %w", err) + } + + s3, err := aws.NewS3Client(ctx.Logger) + if err != nil { + return nil, fmt.Errorf("failed to create S3 client: %w", err) + } + + owner := strings.Split(project.Blueprint.Global.Repo.Name, "/")[0] + repo := strings.Split(project.Blueprint.Global.Repo.Name, "/")[1] + ghClient, err := github.NewDefaultGithubClient( + owner, + repo, + github.WithCredsOrEnv(project.Blueprint.Global.Ci.Providers.Github.Credentials), + github.WithLogger(ctx.Logger), + ) + if err != nil { + return nil, fmt.Errorf("failed to create github client: %w", err) + } + + handler := events.NewDefaultEventHandler(ctx.Logger) + runner := earthly.NewDefaultProjectRunner(ctx, &project) + return &DocsReleaser{ + config: config, + force: force, + fs: fs, + ghClient: ghClient, + handler: &handler, + logger: ctx.Logger, + project: &project, + release: release, + releaseName: name, + runner: &runner, + s3: s3, + workdir: workdir, + }, nil +} diff --git a/cli/pkg/release/providers/docs_test.go b/cli/pkg/release/providers/docs_test.go new file mode 100644 index 00000000..26820456 --- /dev/null +++ b/cli/pkg/release/providers/docs_test.go @@ -0,0 +1,407 @@ +package providers + +import ( + "context" + "io" + "os" + "path/filepath" + "strings" + "testing" + + "cuelang.org/go/cue" + "github.com/aws/aws-sdk-go-v2/service/s3" + s3types "github.com/aws/aws-sdk-go-v2/service/s3/types" + "github.com/input-output-hk/catalyst-forge/cli/pkg/earthly" + earthlyMocks "github.com/input-output-hk/catalyst-forge/cli/pkg/earthly/mocks" + eventsMocks "github.com/input-output-hk/catalyst-forge/cli/pkg/events/mocks" + "github.com/input-output-hk/catalyst-forge/lib/project/project" + "github.com/input-output-hk/catalyst-forge/lib/providers/aws" + awsMocks "github.com/input-output-hk/catalyst-forge/lib/providers/aws/mocks" + gh "github.com/input-output-hk/catalyst-forge/lib/providers/github" + ghMocks "github.com/input-output-hk/catalyst-forge/lib/providers/github/mocks" + sb "github.com/input-output-hk/catalyst-forge/lib/schema/blueprint" + "github.com/input-output-hk/catalyst-forge/lib/schema/blueprint/global" + sp "github.com/input-output-hk/catalyst-forge/lib/schema/blueprint/project" + "github.com/input-output-hk/catalyst-forge/lib/tools/fs" + "github.com/input-output-hk/catalyst-forge/lib/tools/fs/billy" + "github.com/input-output-hk/catalyst-forge/lib/tools/testutils" + "github.com/input-output-hk/catalyst-forge/lib/tools/walker" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +) + +func TestDocsReleaserRelease(t *testing.T) { + type prPostResult struct { + prNumber int + body string + } + + type testResult struct { + localFs fs.Filesystem + s3Fs fs.Filesystem + err error + prPost prPostResult + } + + type branchFile struct { + branch string + name string + content string + } + + newProject := func(projectName, branch, bucket, docsPath string) project.Project { + return project.Project{ + Name: projectName, + Blueprint: sb.Blueprint{ + Global: &global.Global{ + Repo: &global.Repo{ + Name: "owner/repo", + DefaultBranch: branch, + }, + Ci: &global.CI{ + Release: &global.Release{ + Docs: &global.DocsRelease{ + Bucket: bucket, + Path: docsPath, + Url: "https://docs.example.com/", + }, + }, + }, + }, + Project: &sp.Project{ + Release: map[string]sp.Release{ + "docs": { + Target: "docs", + }, + }, + }, + }, + Repo: nil, + } + } + + tests := []struct { + name string + projectName string + defaultBranch string + bucket string + prefix string + releaseName string + prNumber int + curBranch string + files map[string]string + s3files map[string]string + branchFiles []branchFile + prComments []gh.PullRequestComment + branches []gh.Branch + inCI bool + isPR bool + validate func(*testing.T, testResult) + }{ + { + name: "default branch", + projectName: "project", + defaultBranch: "master", + bucket: "bucket", + prefix: "prefix", + releaseName: "test", + prNumber: 123, + curBranch: "master", + files: map[string]string{ + "index.html": "test docs", + }, + s3files: map[string]string{ + "test.html": "test", + }, + branchFiles: []branchFile{ + { + branch: "mybranch", + name: "index.html", + content: "test docs", + }, + }, + prComments: []gh.PullRequestComment{}, + branches: []gh.Branch{}, + inCI: true, + isPR: false, + validate: func(t *testing.T, result testResult) { + assert.NoError(t, result.err) + + exists, err := result.s3Fs.Exists("/bucket/prefix/test/index.html") + require.NoError(t, err) + assert.True(t, exists) + + exists, err = result.s3Fs.Exists("/bucket/prefix/test/test.html") + require.NoError(t, err) + assert.False(t, exists) + + exists, err = result.s3Fs.Exists("/bucket/prefix/test/b/mybranch/index.html") + require.NoError(t, err) + assert.False(t, exists) + + content, err := result.s3Fs.ReadFile("/bucket/prefix/test/index.html") + require.NoError(t, err) + assert.Equal(t, "test docs", string(content)) + + assert.Equal(t, 0, result.prPost.prNumber) + assert.Equal(t, "", result.prPost.body) + }, + }, + { + name: "pr", + projectName: "project", + defaultBranch: "master", + bucket: "bucket", + prefix: "prefix", + releaseName: "test", + prNumber: 123, + curBranch: "mybranch", + files: map[string]string{ + "index.html": "test docs", + }, + s3files: map[string]string{ + "test.html": "test", + }, + prComments: []gh.PullRequestComment{}, + branches: []gh.Branch{}, + inCI: true, + isPR: true, + validate: func(t *testing.T, result testResult) { + assert.NoError(t, result.err) + + exists, err := result.s3Fs.Exists("/bucket/prefix/test/b/mybranch/index.html") + require.NoError(t, err) + assert.True(t, exists) + + exists, err = result.s3Fs.Exists("/bucket/prefix/test/b/mybranch/test.html") + require.NoError(t, err) + assert.False(t, exists) + + content, err := result.s3Fs.ReadFile("/bucket/prefix/test/b/mybranch/index.html") + require.NoError(t, err) + assert.Equal(t, "test docs", string(content)) + + expectedBody := ` + +## 📚 Docs Preview + +The docs for this PR can be previewed at the following URL: + +https://docs.example.com/test/b/mybranch +` + + assert.Equal(t, expectedBody, result.prPost.body) + }, + }, + { + name: "pr comment exists", + projectName: "project", + defaultBranch: "master", + bucket: "bucket", + prefix: "prefix", + releaseName: "test", + prNumber: 123, + curBranch: "mybranch", + files: map[string]string{ + "index.html": "test docs", + }, + s3files: map[string]string{ + "test.html": "test", + }, + prComments: []gh.PullRequestComment{ + { + Author: "github-actions[bot]", + Body: "", + }, + }, + branches: []gh.Branch{}, + inCI: true, + isPR: true, + validate: func(t *testing.T, result testResult) { + assert.NoError(t, result.err) + + assert.Equal(t, 0, result.prPost.prNumber) + assert.Equal(t, "", result.prPost.body) + }, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if tt.inCI { + t.Setenv("GITHUB_ACTIONS", "true") + } + + prj := newProject(tt.projectName, tt.defaultBranch, tt.bucket, tt.prefix) + + s3Fs := billy.NewInMemoryFs() + logger := testutils.NewNoopLogger() + for name, content := range tt.s3files { + p := filepath.Join("/", + prj.Blueprint.Global.Ci.Release.Docs.Bucket, + prj.Blueprint.Global.Ci.Release.Docs.Path, + tt.releaseName, + name, + ) + require.NoError(t, s3Fs.WriteFile(p, []byte(content), 0o644)) + } + + for _, branchFile := range tt.branchFiles { + p := filepath.Join("/", + prj.Blueprint.Global.Ci.Release.Docs.Bucket, + prj.Blueprint.Global.Ci.Release.Docs.Path, + tt.releaseName, + "b", + branchFile.branch, + branchFile.name, + ) + require.NoError(t, s3Fs.MkdirAll(filepath.Dir(p), 0o755)) + require.NoError(t, s3Fs.WriteFile(p, []byte(branchFile.content), 0o644)) + } + + mockAWSS3 := &awsMocks.AWSS3ClientMock{ + PutObjectFunc: func(ctx context.Context, params *s3.PutObjectInput, optFns ...func(*s3.Options)) (*s3.PutObjectOutput, error) { + bucket := *params.Bucket + key := *params.Key + + bucketDir := "/" + bucket + _ = s3Fs.MkdirAll(bucketDir, 0o755) + filePath := filepath.Join(bucketDir, key) + data, err := io.ReadAll(params.Body) + if err != nil { + return nil, err + } + + if err := s3Fs.MkdirAll(filepath.Dir(filePath), 0o755); err != nil { + return nil, err + } + + if err := s3Fs.WriteFile(filePath, data, 0o644); err != nil { + return nil, err + } + + return &s3.PutObjectOutput{}, nil + }, + DeleteObjectFunc: func(ctx context.Context, params *s3.DeleteObjectInput, optFns ...func(*s3.Options)) (*s3.DeleteObjectOutput, error) { + bucket := *params.Bucket + key := *params.Key + bucketDir := "/" + bucket + filePath := filepath.Join(bucketDir, key) + + _ = s3Fs.Remove(filePath) + + return &s3.DeleteObjectOutput{}, nil + }, + ListObjectsV2Func: func(ctx context.Context, params *s3.ListObjectsV2Input, optFns ...func(*s3.Options)) (*s3.ListObjectsV2Output, error) { + bucket := *params.Bucket + prefix := "" + if params.Prefix != nil { + prefix = *params.Prefix + } + bucketDir := "/" + bucket + + if params.Delimiter != nil { + var prefixes []s3types.CommonPrefix + + s3Fs.Walk("/", func(path string, info os.FileInfo, err error) error { + if err != nil { + return err + } + + if info.IsDir() { + return nil + } + + p1 := strings.TrimPrefix(path, "/"+tt.bucket+"/") + if strings.HasPrefix(p1, *params.Prefix) { + prefixes = append(prefixes, s3types.CommonPrefix{Prefix: &p1}) + } + return nil + }) + + truncated := false + return &s3.ListObjectsV2Output{CommonPrefixes: prefixes, IsTruncated: &truncated}, nil + } + + var contents []s3types.Object + _ = s3Fs.Walk(bucketDir, func(path string, info os.FileInfo, err error) error { + if err != nil { + return nil + } + + relPath, _ := filepath.Rel(bucketDir, path) + if !info.IsDir() && strings.HasPrefix(relPath, prefix) { + contents = append(contents, s3types.Object{Key: &relPath}) + } + + return nil + }) + + return &s3.ListObjectsV2Output{Contents: contents}, nil + }, + } + + ghEnvMock := &ghMocks.GithubEnvMock{ + IsPRFunc: func() bool { + return tt.isPR + }, + GetBranchFunc: func() string { + return tt.curBranch + }, + GetPRNumberFunc: func() int { + return tt.prNumber + }, + } + + var prPost prPostResult + ghMock := &ghMocks.GithubClientMock{ + EnvFunc: func() gh.GithubEnv { + return ghEnvMock + }, + ListBranchesFunc: func() ([]gh.Branch, error) { + return tt.branches, nil + }, + ListPullRequestCommentsFunc: func(prNumber int) ([]gh.PullRequestComment, error) { + return tt.prComments, nil + }, + PostPullRequestCommentFunc: func(prNumber int, body string) error { + prPost.prNumber = prNumber + prPost.body = body + return nil + }, + } + + localFs := billy.NewInMemoryFs() + for name, content := range tt.files { + p := filepath.Join("/", earthly.GetBuildPlatform(), name) + require.NoError(t, localFs.MkdirAll(filepath.Dir(p), 0o755)) + require.NoError(t, localFs.WriteFile(p, []byte(content), 0o644)) + } + + w := walker.NewCustomDefaultFSWalker(localFs, logger) + s3Client := aws.NewCustomS3Client(mockAWSS3, &w, logger) + releaser := &DocsReleaser{ + config: DocsReleaserConfig{Name: tt.releaseName}, + force: true, + fs: localFs, + ghClient: ghMock, + handler: &eventsMocks.EventHandlerMock{FiringFunc: func(_ *project.Project, _ map[string]cue.Value) bool { return true }}, + logger: logger, + project: &prj, + release: sp.Release{Target: "docs"}, + releaseName: "docs", + runner: &earthlyMocks.ProjectRunnerMock{RunTargetFunc: func(string, ...earthly.EarthlyExecutorOption) error { return nil }}, + s3: s3Client, + workdir: "/", + } + + err := releaser.Release() + tt.validate(t, testResult{ + localFs: localFs, + s3Fs: s3Fs, + err: err, + prPost: prPost, + }) + }) + } +} diff --git a/cli/pkg/release/providers/github.go b/cli/pkg/release/providers/github.go index 0a6b1014..bc13eefc 100644 --- a/cli/pkg/release/providers/github.go +++ b/cli/pkg/release/providers/github.go @@ -1,7 +1,7 @@ package providers import ( - "context" + "errors" "fmt" "log/slog" "path/filepath" @@ -12,7 +12,7 @@ import ( "github.com/input-output-hk/catalyst-forge/cli/pkg/events" "github.com/input-output-hk/catalyst-forge/cli/pkg/run" "github.com/input-output-hk/catalyst-forge/lib/project/project" - "github.com/input-output-hk/catalyst-forge/lib/project/providers" + gh "github.com/input-output-hk/catalyst-forge/lib/providers/github" sp "github.com/input-output-hk/catalyst-forge/lib/schema/blueprint/project" "github.com/input-output-hk/catalyst-forge/lib/tools/archive" "github.com/input-output-hk/catalyst-forge/lib/tools/fs" @@ -25,7 +25,7 @@ type GithubReleaserConfig struct { } type GithubReleaser struct { - client *github.Client + client gh.GithubClient config GithubReleaserConfig force bool fs fs.Filesystem @@ -71,15 +71,10 @@ func (r *GithubReleaser) Release() error { assets = append(assets, filename) } - parts := strings.Split(r.project.Blueprint.Global.Repo.Name, "/") - owner, repo := parts[0], parts[1] - - ctx := context.Background() - - release, resp, err := r.client.Repositories.GetReleaseByTag(ctx, owner, repo, r.project.Tag.Full) - if resp.StatusCode == 404 { + release, err := r.client.GetReleaseByTag(r.project.Tag.Full) + if errors.Is(err, gh.ErrReleaseNotFound) { r.logger.Info("Creating release", "name", r.config.Name) - release, _, err = r.client.Repositories.CreateRelease(ctx, owner, repo, &github.RepositoryRelease{ + release, err = r.client.CreateRelease(&github.RepositoryRelease{ Name: &r.config.Name, TagName: &r.project.Tag.Full, Draft: github.Bool(false), @@ -101,28 +96,9 @@ func (r *GithubReleaser) Release() error { } r.logger.Info("Uploading asset", "asset", asset) - f, err := r.fs.Open(filepath.Join(r.workdir, asset)) - if err != nil { - return fmt.Errorf("failed to open asset: %w", err) - } - - stat, err := f.Stat() - if err != nil { - return fmt.Errorf("failed to stat asset: %w", err) - } - - url := fmt.Sprintf("repos/%s/%s/releases/%d/assets?name=%s", owner, repo, *release.ID, asset) - req, err := r.client.NewUploadRequest(url, f, stat.Size(), "application/gzip") - if err != nil { - return fmt.Errorf("failed to create upload request: %w", err) - } - - _, err = r.client.Do(ctx, req, nil) - if err != nil { + if err := r.client.UploadReleaseAsset(*release.ID, filepath.Join(r.workdir, asset)); err != nil { return fmt.Errorf("failed to upload asset: %w", err) } - - f.Close() } return nil @@ -205,7 +181,14 @@ func NewGithubReleaser( return nil, fmt.Errorf("failed to create temporary directory: %w", err) } - client, err := providers.NewGithubClient(&project, ctx.Logger) + owner := strings.Split(project.Blueprint.Global.Repo.Name, "/")[0] + repo := strings.Split(project.Blueprint.Global.Repo.Name, "/")[1] + client, err := gh.NewDefaultGithubClient( + owner, + repo, + gh.WithCredsOrEnv(project.Blueprint.Global.Ci.Providers.Github.Credentials), + gh.WithLogger(ctx.Logger), + ) if err != nil { return nil, fmt.Errorf("failed to create github client: %w", err) } diff --git a/cli/pkg/release/providers/github_test.go b/cli/pkg/release/providers/github_test.go index 6be46f71..232cc4a4 100644 --- a/cli/pkg/release/providers/github_test.go +++ b/cli/pkg/release/providers/github_test.go @@ -6,19 +6,19 @@ import ( "compress/gzip" "fmt" "io" - "net/http" "path/filepath" "testing" "github.com/google/go-github/v66/github" "github.com/input-output-hk/catalyst-forge/lib/project/project" + gh "github.com/input-output-hk/catalyst-forge/lib/providers/github" + gm "github.com/input-output-hk/catalyst-forge/lib/providers/github/mocks" sb "github.com/input-output-hk/catalyst-forge/lib/schema/blueprint" sg "github.com/input-output-hk/catalyst-forge/lib/schema/blueprint/global" sp "github.com/input-output-hk/catalyst-forge/lib/schema/blueprint/project" "github.com/input-output-hk/catalyst-forge/lib/tools/fs" "github.com/input-output-hk/catalyst-forge/lib/tools/fs/billy" "github.com/input-output-hk/catalyst-forge/lib/tools/testutils" - "github.com/migueleliasweb/go-github-mock/src/mock" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" ) @@ -105,8 +105,7 @@ func TestGithubReleaserRelease(t *testing.T) { assert.True(t, created) - url := fmt.Sprintf("/repos/owner/repo/releases/123456/assets?name=%s", filename) - data, ok := uploads[url] + data, ok := uploads[filename] assert.True(t, ok) files := make(map[string]string) @@ -161,8 +160,7 @@ func TestGithubReleaserRelease(t *testing.T) { require.NoError(t, err) assert.True(t, exists) - url := fmt.Sprintf("/repos/owner/repo/releases/123456/assets?name=%s", filename) - data, ok := uploads[url] + data, ok := uploads[filename] assert.True(t, ok) files := make(map[string]string) @@ -348,67 +346,36 @@ func TestGithubReleaserRelease(t *testing.T) { var releaseCreated bool uploads := make(map[string][]byte) - client := github.NewClient( - mock.NewMockedHTTPClient( - mock.WithRequestMatchHandler( - mock.GetReposReleasesTagsByOwnerByRepoByTag, - http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - body, _ := io.ReadAll(r.Body) - uploads[r.URL.String()] = body - - if tt.ghRelease.ID == nil { - mock.WriteError( - w, - http.StatusNotFound, - "release not found", - ) - return - } - - w.Write(mock.MustMarshal(tt.ghRelease)) - }), - ), - mock.WithRequestMatchHandler( - mock.PostReposReleasesByOwnerByRepo, - http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - if tt.createFail { - mock.WriteError( - w, - http.StatusInternalServerError, - "failed to create release", - ) - return - } - - releaseCreated = true - w.Write(mock.MustMarshal(github.RepositoryRelease{ - ID: github.Int64(123456), - })) - }), - ), - mock.WithRequestMatchHandler( - mock.PostReposReleasesAssetsByOwnerByRepoByReleaseId, - http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - body, _ := io.ReadAll(r.Body) - uploads[r.URL.String()] = body - - if tt.uploadFail { - mock.WriteError( - w, - http.StatusInternalServerError, - "failed to upload asset", - ) - return - } - - w.Write(mock.MustMarshal(github.ReleaseAsset{})) - }), - ), - ), - ) + client := gm.GithubClientMock{ + GetReleaseByTagFunc: func(tag string) (*github.RepositoryRelease, error) { + if tt.ghRelease.ID == nil { + return nil, gh.ErrReleaseNotFound + } + return &tt.ghRelease, nil + }, + CreateReleaseFunc: func(opts *github.RepositoryRelease) (*github.RepositoryRelease, error) { + if tt.createFail { + return nil, fmt.Errorf("failed to create release") + } + releaseCreated = true + return &github.RepositoryRelease{ + ID: github.Int64(123456), + }, nil + }, + UploadReleaseAssetFunc: func(releaseID int64, path string) error { + if tt.uploadFail { + return fmt.Errorf("failed to upload asset") + } + assetName := filepath.Base(path) + assetContent, err := fs.ReadFile(path) + require.NoError(t, err) + uploads[assetName] = assetContent + return nil + }, + } releaser := GithubReleaser{ - client: client, + client: &client, config: tt.config, force: tt.force, fs: fs, diff --git a/cli/pkg/release/providers/kcl.go b/cli/pkg/release/providers/kcl.go index b87e5f8b..791c9b9e 100644 --- a/cli/pkg/release/providers/kcl.go +++ b/cli/pkg/release/providers/kcl.go @@ -6,9 +6,9 @@ import ( "github.com/input-output-hk/catalyst-forge/cli/pkg/events" "github.com/input-output-hk/catalyst-forge/cli/pkg/executor" - "github.com/input-output-hk/catalyst-forge/cli/pkg/providers/aws" "github.com/input-output-hk/catalyst-forge/cli/pkg/run" "github.com/input-output-hk/catalyst-forge/lib/project/project" + "github.com/input-output-hk/catalyst-forge/lib/providers/aws" sp "github.com/input-output-hk/catalyst-forge/lib/schema/blueprint/project" ) diff --git a/cli/pkg/release/providers/kcl_test.go b/cli/pkg/release/providers/kcl_test.go index 37d27dc4..80853211 100644 --- a/cli/pkg/release/providers/kcl_test.go +++ b/cli/pkg/release/providers/kcl_test.go @@ -6,9 +6,9 @@ import ( "testing" "github.com/aws/aws-sdk-go-v2/service/ecr" - "github.com/input-output-hk/catalyst-forge/cli/pkg/providers/aws" - "github.com/input-output-hk/catalyst-forge/cli/pkg/providers/aws/mocks" "github.com/input-output-hk/catalyst-forge/lib/project/project" + "github.com/input-output-hk/catalyst-forge/lib/providers/aws" + "github.com/input-output-hk/catalyst-forge/lib/providers/aws/mocks" sb "github.com/input-output-hk/catalyst-forge/lib/schema/blueprint" sg "github.com/input-output-hk/catalyst-forge/lib/schema/blueprint/global" spr "github.com/input-output-hk/catalyst-forge/lib/schema/blueprint/global/providers" diff --git a/cli/pkg/release/releaser.go b/cli/pkg/release/releaser.go index 7022db29..cf246a2a 100644 --- a/cli/pkg/release/releaser.go +++ b/cli/pkg/release/releaser.go @@ -13,6 +13,7 @@ type ReleaserType string const ( ReleaserTypeCue ReleaserType = "cue" ReleaserTypeDocker ReleaserType = "docker" + ReleaserTypeDocs ReleaserType = "docs" ReleaserTypeGithub ReleaserType = "github" ReleaserTypeKCL ReleaserType = "kcl" ReleaserTypeTimoni ReleaserType = "timoni" @@ -52,6 +53,9 @@ func NewDefaultReleaserStore() *ReleaserStore { ReleaserTypeDocker: func(ctx run.RunContext, project project.Project, name string, force bool) (Releaser, error) { return providers.NewDockerReleaser(ctx, project, name, force) }, + ReleaserTypeDocs: func(ctx run.RunContext, project project.Project, name string, force bool) (Releaser, error) { + return providers.NewDocsReleaser(ctx, project, name, force) + }, ReleaserTypeGithub: func(ctx run.RunContext, project project.Project, name string, force bool) (Releaser, error) { return providers.NewGithubReleaser(ctx, project, name, force) }, diff --git a/cli/pkg/run/context.go b/cli/pkg/run/context.go index c763e2e0..f633df46 100644 --- a/cli/pkg/run/context.go +++ b/cli/pkg/run/context.go @@ -6,7 +6,7 @@ import ( "cuelang.org/go/cue" "github.com/input-output-hk/catalyst-forge/lib/project/deployment" "github.com/input-output-hk/catalyst-forge/lib/project/project" - "github.com/input-output-hk/catalyst-forge/lib/project/secrets" + "github.com/input-output-hk/catalyst-forge/lib/providers/secrets" "github.com/input-output-hk/catalyst-forge/lib/tools/walker" ) diff --git a/cli/tui/ci/app.go b/cli/tui/ci/app.go index 486d85c3..a5e61a9d 100644 --- a/cli/tui/ci/app.go +++ b/cli/tui/ci/app.go @@ -15,7 +15,7 @@ import ( "github.com/input-output-hk/catalyst-forge/cli/pkg/run" "github.com/input-output-hk/catalyst-forge/cli/tui" "github.com/input-output-hk/catalyst-forge/lib/project/project" - "github.com/input-output-hk/catalyst-forge/lib/tools/git" + "github.com/input-output-hk/catalyst-forge/lib/providers/git" "github.com/input-output-hk/catalyst-forge/lib/tools/walker" ) diff --git a/cli/tui/ci/ci.go b/cli/tui/ci/ci.go index 2dbeb746..cd7ab9df 100644 --- a/cli/tui/ci/ci.go +++ b/cli/tui/ci/ci.go @@ -16,7 +16,7 @@ import ( "github.com/input-output-hk/catalyst-forge/cli/pkg/run" "github.com/input-output-hk/catalyst-forge/cli/pkg/scan" "github.com/input-output-hk/catalyst-forge/lib/project/project" - "github.com/input-output-hk/catalyst-forge/lib/project/secrets" + "github.com/input-output-hk/catalyst-forge/lib/providers/secrets" "github.com/input-output-hk/catalyst-forge/lib/tools/walker" ) diff --git a/docs/blueprint.cue b/docs/blueprint.cue index dd85bd5c..30d7421b 100644 --- a/docs/blueprint.cue +++ b/docs/blueprint.cue @@ -1 +1,15 @@ -project: name: "forge-docs" +project: { + name: "forge-docs" + + release: { + docs: { + on: { + always: {} + } + + config: { + name: "forge" + } + } + } +} diff --git a/foundry/api/Earthfile b/foundry/api/Earthfile index a1acdd9f..9bcb5694 100644 --- a/foundry/api/Earthfile +++ b/foundry/api/Earthfile @@ -1,7 +1,7 @@ VERSION 0.8 deps: - FROM golang:1.24.0-bookworm + FROM golang:1.24.2-bookworm WORKDIR /work diff --git a/foundry/operator/Earthfile b/foundry/operator/Earthfile index d244f8f7..cd65ab2f 100644 --- a/foundry/operator/Earthfile +++ b/foundry/operator/Earthfile @@ -1,7 +1,7 @@ VERSION 0.8 deps: - FROM golang:1.24.0-bookworm + FROM golang:1.24.2-bookworm WORKDIR /work/operator ARG CONTROLLER_GEN_VERSION=v0.17.2 @@ -31,6 +31,7 @@ deps: # Copy local deps COPY ../api+src/src /work/api COPY ../../lib/project+src/src /lib/project + COPY ../../lib/providers+src/src /lib/providers COPY ../../lib/schema+src/src /lib/schema COPY ../../lib/tools+src/src /lib/tools diff --git a/foundry/operator/cmd/main.go b/foundry/operator/cmd/main.go index bdeed3cd..6eabce77 100644 --- a/foundry/operator/cmd/main.go +++ b/foundry/operator/cmd/main.go @@ -47,8 +47,8 @@ import ( "github.com/input-output-hk/catalyst-forge/foundry/operator/pkg/config" "github.com/input-output-hk/catalyst-forge/foundry/operator/pkg/handlers" "github.com/input-output-hk/catalyst-forge/lib/project/deployment" - "github.com/input-output-hk/catalyst-forge/lib/project/providers" - "github.com/input-output-hk/catalyst-forge/lib/project/secrets" + "github.com/input-output-hk/catalyst-forge/lib/providers/git" + "github.com/input-output-hk/catalyst-forge/lib/providers/secrets" "github.com/input-output-hk/catalyst-forge/lib/tools/fs/billy" "github.com/input-output-hk/catalyst-forge/lib/tools/git/repo/remote" // +kubebuilder:scaffold:imports @@ -229,7 +229,7 @@ func main() { setupLog.Info("Fetching git auth token") secretStore := secrets.NewDefaultSecretStore() - creds, err := providers.GetGitProviderCreds(&cfg.Deployer.Git.Creds, &secretStore, logger) + creds, err := git.GetGitProviderCreds(&cfg.Deployer.Git.Creds, &secretStore, logger) if err != nil { setupLog.Error(err, "unable to get auth token") os.Exit(1) diff --git a/foundry/operator/go.mod b/foundry/operator/go.mod index 82e3dc1e..2363a94c 100644 --- a/foundry/operator/go.mod +++ b/foundry/operator/go.mod @@ -1,6 +1,6 @@ module github.com/input-output-hk/catalyst-forge/foundry/operator -go 1.23.0 +go 1.24.2 godebug default=go1.23 @@ -11,6 +11,7 @@ require ( github.com/go-git/go-git/v5 v5.12.0 github.com/input-output-hk/catalyst-forge/foundry/api v0.0.0 github.com/input-output-hk/catalyst-forge/lib/project v0.0.0 + github.com/input-output-hk/catalyst-forge/lib/providers v0.0.0 github.com/input-output-hk/catalyst-forge/lib/schema v0.0.0 github.com/input-output-hk/catalyst-forge/lib/tools v0.0.0 github.com/onsi/ginkgo/v2 v2.22.0 @@ -41,21 +42,21 @@ require ( github.com/antlr/antlr4/runtime/Go/antlr/v4 v4.0.0-20230219212500-1f9a474cc2dc // indirect github.com/antlr4-go/antlr/v4 v4.13.0 // indirect github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2 // indirect - github.com/aws/aws-sdk-go v1.55.5 // indirect - github.com/aws/aws-sdk-go-v2 v1.31.0 // indirect - github.com/aws/aws-sdk-go-v2/config v1.27.40 // indirect - github.com/aws/aws-sdk-go-v2/credentials v1.17.38 // indirect - github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.14 // indirect - github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.18 // indirect - github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.18 // indirect - github.com/aws/aws-sdk-go-v2/internal/ini v1.8.1 // indirect - github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.11.5 // indirect - github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.11.20 // indirect - github.com/aws/aws-sdk-go-v2/service/secretsmanager v1.33.4 // indirect - github.com/aws/aws-sdk-go-v2/service/sso v1.23.4 // indirect - github.com/aws/aws-sdk-go-v2/service/ssooidc v1.27.4 // indirect - github.com/aws/aws-sdk-go-v2/service/sts v1.31.4 // indirect - github.com/aws/smithy-go v1.21.0 // indirect + github.com/aws/aws-sdk-go v1.55.7 // indirect + github.com/aws/aws-sdk-go-v2 v1.36.6 // indirect + github.com/aws/aws-sdk-go-v2/config v1.29.18 // indirect + github.com/aws/aws-sdk-go-v2/credentials v1.17.71 // indirect + github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.33 // indirect + github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.37 // indirect + github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.37 // indirect + github.com/aws/aws-sdk-go-v2/internal/ini v1.8.3 // indirect + github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.12.4 // indirect + github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.12.18 // indirect + github.com/aws/aws-sdk-go-v2/service/secretsmanager v1.35.8 // indirect + github.com/aws/aws-sdk-go-v2/service/sso v1.25.6 // indirect + github.com/aws/aws-sdk-go-v2/service/ssooidc v1.30.4 // indirect + github.com/aws/aws-sdk-go-v2/service/sts v1.34.1 // indirect + github.com/aws/smithy-go v1.22.4 // indirect github.com/beorn7/perks v1.0.1 // indirect github.com/bgentry/go-netrc v0.0.0-20140422174119-9fd32a8b3d3d // indirect github.com/blang/semver/v4 v4.0.0 // indirect @@ -272,6 +273,8 @@ require ( replace github.com/input-output-hk/catalyst-forge/lib/project => ../../lib/project +replace github.com/input-output-hk/catalyst-forge/lib/providers => ../../lib/providers + replace github.com/input-output-hk/catalyst-forge/lib/schema => ../../lib/schema replace github.com/input-output-hk/catalyst-forge/lib/tools => ../../lib/tools diff --git a/foundry/operator/go.sum b/foundry/operator/go.sum index 30c26471..ff52574c 100644 --- a/foundry/operator/go.sum +++ b/foundry/operator/go.sum @@ -237,36 +237,36 @@ github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkY github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2 h1:DklsrG3dyBCFEj5IhUbnKptjxatkF07cF2ak3yi77so= github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2/go.mod h1:WaHUgvxTVq04UNunO+XhnAqY/wQc+bxr74GqbsZ/Jqw= github.com/aws/aws-sdk-go v1.44.122/go.mod h1:y4AeaBuwd2Lk+GepC1E9v0qOiTws0MIWAX4oIKwKHZo= -github.com/aws/aws-sdk-go v1.55.5 h1:KKUZBfBoyqy5d3swXyiC7Q76ic40rYcbqH7qjh59kzU= -github.com/aws/aws-sdk-go v1.55.5/go.mod h1:eRwEWoyTWFMVYVQzKMNHWP5/RV4xIUGMQfXQHfHkpNU= -github.com/aws/aws-sdk-go-v2 v1.31.0 h1:3V05LbxTSItI5kUqNwhJrrrY1BAXxXt0sN0l72QmG5U= -github.com/aws/aws-sdk-go-v2 v1.31.0/go.mod h1:ztolYtaEUtdpf9Wftr31CJfLVjOnD/CVRkKOOYgF8hA= -github.com/aws/aws-sdk-go-v2/config v1.27.40 h1:sie4mPBGFOO+Z27+yHzvyN31G20h/bf2xb5mCbpLv2Q= -github.com/aws/aws-sdk-go-v2/config v1.27.40/go.mod h1:4KW7Aa5tNo+0VHnuLnnE1vPHtwMurlNZNS65IdcewHA= -github.com/aws/aws-sdk-go-v2/credentials v1.17.38 h1:iM90eRhCeZtlkzCNCG1JysOzJXGYf5rx80aD1lUgNDU= -github.com/aws/aws-sdk-go-v2/credentials v1.17.38/go.mod h1:TCVYPZeQuLaYNEkf/TVn6k5k/zdVZZ7xH9po548VNNg= -github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.14 h1:C/d03NAmh8C4BZXhuRNboF/DqhBkBCeDiJDcaqIT5pA= -github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.14/go.mod h1:7I0Ju7p9mCIdlrfS+JCgqcYD0VXz/N4yozsox+0o078= -github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.18 h1:kYQ3H1u0ANr9KEKlGs/jTLrBFPo8P8NaH/w7A01NeeM= -github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.18/go.mod h1:r506HmK5JDUh9+Mw4CfGJGSSoqIiLCndAuqXuhbv67Y= -github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.18 h1:Z7IdFUONvTcvS7YuhtVxN99v2cCoHRXOS4mTr0B/pUc= -github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.18/go.mod h1:DkKMmksZVVyat+Y+r1dEOgJEfUeA7UngIHWeKsi0yNc= -github.com/aws/aws-sdk-go-v2/internal/ini v1.8.1 h1:VaRN3TlFdd6KxX1x3ILT5ynH6HvKgqdiXoTxAF4HQcQ= -github.com/aws/aws-sdk-go-v2/internal/ini v1.8.1/go.mod h1:FbtygfRFze9usAadmnGJNc8KsP346kEe+y2/oyhGAGc= -github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.11.5 h1:QFASJGfT8wMXtuP3D5CRmMjARHv9ZmzFUMJznHDOY3w= -github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.11.5/go.mod h1:QdZ3OmoIjSX+8D1OPAzPxDfjXASbBMDsz9qvtyIhtik= -github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.11.20 h1:Xbwbmk44URTiHNx6PNo0ujDE6ERlsCKJD3u1zfnzAPg= -github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.11.20/go.mod h1:oAfOFzUB14ltPZj1rWwRc3d/6OgD76R8KlvU3EqM9Fg= -github.com/aws/aws-sdk-go-v2/service/secretsmanager v1.33.4 h1:EoPbZg+DGTRqKKhwk5uDviV9yvx65r1kyoNNC02ZH4Y= -github.com/aws/aws-sdk-go-v2/service/secretsmanager v1.33.4/go.mod h1:WyLS5qwXHtjKAONYZq/4ewdd+hcVsa3LBu77Ow5uj3k= -github.com/aws/aws-sdk-go-v2/service/sso v1.23.4 h1:ck/Y8XWNR1gHa4BFkwE3oSu7XDJGwl+8TI7E/RB2EcQ= -github.com/aws/aws-sdk-go-v2/service/sso v1.23.4/go.mod h1:XRlMvmad0ZNL+75C5FYdMvbbLkd6qiqz6foR1nA1PXY= -github.com/aws/aws-sdk-go-v2/service/ssooidc v1.27.4 h1:4f2/JKYZHAZbQ7koBpZ012bKi32NHPY0m7TDuJgsbug= -github.com/aws/aws-sdk-go-v2/service/ssooidc v1.27.4/go.mod h1:FnvDM4sfa+isJ3kDXIzAB9GAwVSzFzSy97uZ3IsHo4E= -github.com/aws/aws-sdk-go-v2/service/sts v1.31.4 h1:uK6dUUdJtqutK1XO/tmNaQMJiPLCJY/eAeOOmqQ6ygY= -github.com/aws/aws-sdk-go-v2/service/sts v1.31.4/go.mod h1:yMWe0F+XG0DkRZK5ODZhG7BEFYhLXi2dqGsv6tX0cgI= -github.com/aws/smithy-go v1.21.0 h1:H7L8dtDRk0P1Qm6y0ji7MCYMQObJ5R9CRpyPhRUkLYA= -github.com/aws/smithy-go v1.21.0/go.mod h1:irrKGvNn1InZwb2d7fkIRNucdfwR8R+Ts3wxYa/cJHg= +github.com/aws/aws-sdk-go v1.55.7 h1:UJrkFq7es5CShfBwlWAC8DA077vp8PyVbQd3lqLiztE= +github.com/aws/aws-sdk-go v1.55.7/go.mod h1:eRwEWoyTWFMVYVQzKMNHWP5/RV4xIUGMQfXQHfHkpNU= +github.com/aws/aws-sdk-go-v2 v1.36.6 h1:zJqGjVbRdTPojeCGWn5IR5pbJwSQSBh5RWFTQcEQGdU= +github.com/aws/aws-sdk-go-v2 v1.36.6/go.mod h1:EYrzvCCN9CMUTa5+6lf6MM4tq3Zjp8UhSGR/cBsjai0= +github.com/aws/aws-sdk-go-v2/config v1.29.18 h1:x4T1GRPnqKV8HMJOMtNktbpQMl3bIsfx8KbqmveUO2I= +github.com/aws/aws-sdk-go-v2/config v1.29.18/go.mod h1:bvz8oXugIsH8K7HLhBv06vDqnFv3NsGDt2Znpk7zmOU= +github.com/aws/aws-sdk-go-v2/credentials v1.17.71 h1:r2w4mQWnrTMJjOyIsZtGp3R3XGY3nqHn8C26C2lQWgA= +github.com/aws/aws-sdk-go-v2/credentials v1.17.71/go.mod h1:E7VF3acIup4GB5ckzbKFrCK0vTvEQxOxgdq4U3vcMCY= +github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.33 h1:D9ixiWSG4lyUBL2DDNK924Px9V/NBVpML90MHqyTADY= +github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.33/go.mod h1:caS/m4DI+cij2paz3rtProRBI4s/+TCiWoaWZuQ9010= +github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.37 h1:osMWfm/sC/L4tvEdQ65Gri5ZZDCUpuYJZbTTDrsn4I0= +github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.37/go.mod h1:ZV2/1fbjOPr4G4v38G3Ww5TBT4+hmsK45s/rxu1fGy0= +github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.37 h1:v+X21AvTb2wZ+ycg1gx+orkB/9U6L7AOp93R7qYxsxM= +github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.37/go.mod h1:G0uM1kyssELxmJ2VZEfG0q2npObR3BAkF3c1VsfVnfs= +github.com/aws/aws-sdk-go-v2/internal/ini v1.8.3 h1:bIqFDwgGXXN1Kpp99pDOdKMTTb5d2KyU5X/BZxjOkRo= +github.com/aws/aws-sdk-go-v2/internal/ini v1.8.3/go.mod h1:H5O/EsxDWyU+LP/V8i5sm8cxoZgc2fdNR9bxlOFrQTo= +github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.12.4 h1:CXV68E2dNqhuynZJPB80bhPQwAKqBWVer887figW6Jc= +github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.12.4/go.mod h1:/xFi9KtvBXP97ppCz1TAEvU1Uf66qvid89rbem3wCzQ= +github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.12.18 h1:vvbXsA2TVO80/KT7ZqCbx934dt6PY+vQ8hZpUZ/cpYg= +github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.12.18/go.mod h1:m2JJHledjBGNMsLOF1g9gbAxprzq3KjC8e4lxtn+eWg= +github.com/aws/aws-sdk-go-v2/service/secretsmanager v1.35.8 h1:HD6R8K10gPbN9CNqRDOs42QombXlYeLOr4KkIxe2lQs= +github.com/aws/aws-sdk-go-v2/service/secretsmanager v1.35.8/go.mod h1:x66GdH8qjYTr6Kb4ik38Ewl6moLsg8igbceNsmxVxeA= +github.com/aws/aws-sdk-go-v2/service/sso v1.25.6 h1:rGtWqkQbPk7Bkwuv3NzpE/scwwL9sC1Ul3tn9x83DUI= +github.com/aws/aws-sdk-go-v2/service/sso v1.25.6/go.mod h1:u4ku9OLv4TO4bCPdxf4fA1upaMaJmP9ZijGk3AAOC6Q= +github.com/aws/aws-sdk-go-v2/service/ssooidc v1.30.4 h1:OV/pxyXh+eMA0TExHEC4jyWdumLxNbzz1P0zJoezkJc= +github.com/aws/aws-sdk-go-v2/service/ssooidc v1.30.4/go.mod h1:8Mm5VGYwtm+r305FfPSuc+aFkrypeylGYhFim6XEPoc= +github.com/aws/aws-sdk-go-v2/service/sts v1.34.1 h1:aUrLQwJfZtwv3/ZNG2xRtEen+NqI3iesuacjP51Mv1s= +github.com/aws/aws-sdk-go-v2/service/sts v1.34.1/go.mod h1:3wFBZKoWnX3r+Sm7in79i54fBmNfwhdNdQuscCw7QIk= +github.com/aws/smithy-go v1.22.4 h1:uqXzVZNuNexwc/xrh6Tb56u89WDlJY6HS+KC0S4QSjw= +github.com/aws/smithy-go v1.22.4/go.mod h1:t1ufH5HMublsJYulve2RKmHDC15xu1f26kHCp/HgceI= github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= diff --git a/foundry/operator/internal/controller/release_controller.go b/foundry/operator/internal/controller/release_controller.go index 363ba3b7..03037265 100644 --- a/foundry/operator/internal/controller/release_controller.go +++ b/foundry/operator/internal/controller/release_controller.go @@ -32,7 +32,7 @@ import ( "github.com/input-output-hk/catalyst-forge/foundry/operator/pkg/handlers" "github.com/input-output-hk/catalyst-forge/lib/project/deployment" depl "github.com/input-output-hk/catalyst-forge/lib/project/deployment/deployer" - "github.com/input-output-hk/catalyst-forge/lib/project/secrets" + "github.com/input-output-hk/catalyst-forge/lib/providers/secrets" "github.com/input-output-hk/catalyst-forge/lib/tools/git/repo/remote" ) diff --git a/foundry/operator/internal/controller/suite_env_test.go b/foundry/operator/internal/controller/suite_env_test.go index e64af2be..b24c6904 100644 --- a/foundry/operator/internal/controller/suite_env_test.go +++ b/foundry/operator/internal/controller/suite_env_test.go @@ -20,8 +20,8 @@ import ( "github.com/input-output-hk/catalyst-forge/foundry/operator/pkg/handlers" "github.com/input-output-hk/catalyst-forge/lib/project/deployment" "github.com/input-output-hk/catalyst-forge/lib/project/deployment/deployer" - "github.com/input-output-hk/catalyst-forge/lib/project/secrets" tu "github.com/input-output-hk/catalyst-forge/lib/project/utils/test" + "github.com/input-output-hk/catalyst-forge/lib/providers/secrets" sb "github.com/input-output-hk/catalyst-forge/lib/schema/blueprint" sc "github.com/input-output-hk/catalyst-forge/lib/schema/blueprint/common" bfs "github.com/input-output-hk/catalyst-forge/lib/tools/fs/billy" diff --git a/lib/project/Earthfile b/lib/project/Earthfile index 7be8fcdc..9d79fac6 100644 --- a/lib/project/Earthfile +++ b/lib/project/Earthfile @@ -1,7 +1,7 @@ VERSION 0.8 deps: - FROM golang:1.24.0-bookworm + FROM golang:1.24.2-bookworm WORKDIR /work @@ -10,6 +10,7 @@ deps: ENV GOMODCACHE=/go/modcache CACHE --persist --sharing shared /go + COPY ../providers+src/src /providers COPY ../schema+src/src /schema COPY ../tools+src/src /tools diff --git a/lib/project/deployment/deployer/deployer.go b/lib/project/deployment/deployer/deployer.go index 230ed51c..8b3c34b9 100644 --- a/lib/project/deployment/deployer/deployer.go +++ b/lib/project/deployment/deployer/deployer.go @@ -10,8 +10,8 @@ import ( "github.com/input-output-hk/catalyst-forge/lib/project/deployment" "github.com/input-output-hk/catalyst-forge/lib/project/deployment/generator" "github.com/input-output-hk/catalyst-forge/lib/project/project" - "github.com/input-output-hk/catalyst-forge/lib/project/providers" - "github.com/input-output-hk/catalyst-forge/lib/project/secrets" + "github.com/input-output-hk/catalyst-forge/lib/providers/git" + "github.com/input-output-hk/catalyst-forge/lib/providers/secrets" "github.com/input-output-hk/catalyst-forge/lib/schema/blueprint/common" "github.com/input-output-hk/catalyst-forge/lib/tools/fs" "github.com/input-output-hk/catalyst-forge/lib/tools/fs/billy" @@ -332,7 +332,7 @@ func (d *Deployer) clone(url, ref string, fs fs.Filesystem) (repo.GitRepo, error repo.WithFS(fs), } - creds, err := providers.GetGitProviderCreds(&d.cfg.Git.Creds, &d.ss, d.logger) + creds, err := git.GetGitProviderCreds(&d.cfg.Git.Creds, &d.ss, d.logger) if err != nil { d.logger.Warn("could not get git provider credentials, not using any authentication", "error", err) } else { diff --git a/lib/project/deployment/module.go b/lib/project/deployment/module.go index 2c230563..ac36e0f4 100644 --- a/lib/project/deployment/module.go +++ b/lib/project/deployment/module.go @@ -8,7 +8,7 @@ import ( "cuelang.org/go/cue/cuecontext" "cuelang.org/go/cue/format" "github.com/input-output-hk/catalyst-forge/lib/project/project" - "github.com/input-output-hk/catalyst-forge/lib/project/secrets" + "github.com/input-output-hk/catalyst-forge/lib/providers/secrets" sp "github.com/input-output-hk/catalyst-forge/lib/schema/blueprint/project" "github.com/input-output-hk/catalyst-forge/lib/tools/git/repo" ) diff --git a/lib/project/deployment/module_test.go b/lib/project/deployment/module_test.go index 4628814a..8f676d21 100644 --- a/lib/project/deployment/module_test.go +++ b/lib/project/deployment/module_test.go @@ -5,8 +5,8 @@ import ( "testing" "cuelang.org/go/cue/cuecontext" - "github.com/input-output-hk/catalyst-forge/lib/project/secrets" - sm "github.com/input-output-hk/catalyst-forge/lib/project/secrets/mocks" + "github.com/input-output-hk/catalyst-forge/lib/providers/secrets" + sm "github.com/input-output-hk/catalyst-forge/lib/providers/secrets/mocks" sp "github.com/input-output-hk/catalyst-forge/lib/schema/blueprint/project" "github.com/input-output-hk/catalyst-forge/lib/tools/fs/billy" "github.com/input-output-hk/catalyst-forge/lib/tools/git/repo" diff --git a/lib/project/go.mod b/lib/project/go.mod index ea6a65ba..f72f6511 100644 --- a/lib/project/go.mod +++ b/lib/project/go.mod @@ -3,13 +3,10 @@ module github.com/input-output-hk/catalyst-forge/lib/project require ( cuelang.org/go v0.12.0 github.com/BurntSushi/toml v1.4.0 - github.com/Masterminds/semver/v3 v3.3.1 - github.com/aws/aws-sdk-go v1.55.5 - github.com/aws/aws-sdk-go-v2/config v1.27.40 - github.com/aws/aws-sdk-go-v2/service/secretsmanager v1.33.4 github.com/go-git/go-billy/v5 v5.5.0 github.com/go-git/go-git/v5 v5.12.0 github.com/google/go-github/v66 v66.0.0 + github.com/input-output-hk/catalyst-forge/lib/providers v0.0.0-00010101000000-000000000000 github.com/input-output-hk/catalyst-forge/lib/schema v0.0.0 github.com/input-output-hk/catalyst-forge/lib/tools v0.0.0 github.com/stretchr/testify v1.10.0 @@ -28,6 +25,7 @@ require ( github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161 // indirect github.com/MakeNowJust/heredoc v1.0.0 // indirect github.com/Masterminds/goutils v1.1.1 // indirect + github.com/Masterminds/semver/v3 v3.3.1 // indirect github.com/Masterminds/sprig/v3 v3.3.0 // indirect github.com/Masterminds/squirrel v1.5.4 // indirect github.com/Microsoft/go-winio v0.6.2 // indirect @@ -35,18 +33,21 @@ require ( github.com/adrg/xdg v0.5.3 // indirect github.com/antlr/antlr4/runtime/Go/antlr/v4 v4.0.0-20230219212500-1f9a474cc2dc // indirect github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2 // indirect - github.com/aws/aws-sdk-go-v2 v1.31.0 // indirect - github.com/aws/aws-sdk-go-v2/credentials v1.17.38 // indirect - github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.14 // indirect - github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.18 // indirect - github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.18 // indirect - github.com/aws/aws-sdk-go-v2/internal/ini v1.8.1 // indirect - github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.11.5 // indirect - github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.11.20 // indirect - github.com/aws/aws-sdk-go-v2/service/sso v1.23.4 // indirect - github.com/aws/aws-sdk-go-v2/service/ssooidc v1.27.4 // indirect - github.com/aws/aws-sdk-go-v2/service/sts v1.31.4 // indirect - github.com/aws/smithy-go v1.21.0 // indirect + github.com/aws/aws-sdk-go v1.55.7 // indirect + github.com/aws/aws-sdk-go-v2 v1.36.6 // indirect + github.com/aws/aws-sdk-go-v2/config v1.29.18 // indirect + github.com/aws/aws-sdk-go-v2/credentials v1.17.71 // indirect + github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.33 // indirect + github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.37 // indirect + github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.37 // indirect + github.com/aws/aws-sdk-go-v2/internal/ini v1.8.3 // indirect + github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.12.4 // indirect + github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.12.18 // indirect + github.com/aws/aws-sdk-go-v2/service/secretsmanager v1.35.8 // indirect + github.com/aws/aws-sdk-go-v2/service/sso v1.25.6 // indirect + github.com/aws/aws-sdk-go-v2/service/ssooidc v1.30.4 // indirect + github.com/aws/aws-sdk-go-v2/service/sts v1.34.1 // indirect + github.com/aws/smithy-go v1.22.4 // indirect github.com/beorn7/perks v1.0.1 // indirect github.com/bgentry/go-netrc v0.0.0-20140422174119-9fd32a8b3d3d // indirect github.com/blang/semver/v4 v4.0.0 // indirect @@ -241,8 +242,10 @@ require ( sigs.k8s.io/yaml v1.4.0 // indirect ) +replace github.com/input-output-hk/catalyst-forge/lib/providers => ../providers + replace github.com/input-output-hk/catalyst-forge/lib/schema => ../schema replace github.com/input-output-hk/catalyst-forge/lib/tools => ../tools -go 1.23.0 +go 1.24.2 diff --git a/lib/project/go.sum b/lib/project/go.sum index a5ef652d..266c3df0 100644 --- a/lib/project/go.sum +++ b/lib/project/go.sum @@ -233,36 +233,36 @@ github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkY github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2 h1:DklsrG3dyBCFEj5IhUbnKptjxatkF07cF2ak3yi77so= github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2/go.mod h1:WaHUgvxTVq04UNunO+XhnAqY/wQc+bxr74GqbsZ/Jqw= github.com/aws/aws-sdk-go v1.44.122/go.mod h1:y4AeaBuwd2Lk+GepC1E9v0qOiTws0MIWAX4oIKwKHZo= -github.com/aws/aws-sdk-go v1.55.5 h1:KKUZBfBoyqy5d3swXyiC7Q76ic40rYcbqH7qjh59kzU= -github.com/aws/aws-sdk-go v1.55.5/go.mod h1:eRwEWoyTWFMVYVQzKMNHWP5/RV4xIUGMQfXQHfHkpNU= -github.com/aws/aws-sdk-go-v2 v1.31.0 h1:3V05LbxTSItI5kUqNwhJrrrY1BAXxXt0sN0l72QmG5U= -github.com/aws/aws-sdk-go-v2 v1.31.0/go.mod h1:ztolYtaEUtdpf9Wftr31CJfLVjOnD/CVRkKOOYgF8hA= -github.com/aws/aws-sdk-go-v2/config v1.27.40 h1:sie4mPBGFOO+Z27+yHzvyN31G20h/bf2xb5mCbpLv2Q= -github.com/aws/aws-sdk-go-v2/config v1.27.40/go.mod h1:4KW7Aa5tNo+0VHnuLnnE1vPHtwMurlNZNS65IdcewHA= -github.com/aws/aws-sdk-go-v2/credentials v1.17.38 h1:iM90eRhCeZtlkzCNCG1JysOzJXGYf5rx80aD1lUgNDU= -github.com/aws/aws-sdk-go-v2/credentials v1.17.38/go.mod h1:TCVYPZeQuLaYNEkf/TVn6k5k/zdVZZ7xH9po548VNNg= -github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.14 h1:C/d03NAmh8C4BZXhuRNboF/DqhBkBCeDiJDcaqIT5pA= -github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.14/go.mod h1:7I0Ju7p9mCIdlrfS+JCgqcYD0VXz/N4yozsox+0o078= -github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.18 h1:kYQ3H1u0ANr9KEKlGs/jTLrBFPo8P8NaH/w7A01NeeM= -github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.18/go.mod h1:r506HmK5JDUh9+Mw4CfGJGSSoqIiLCndAuqXuhbv67Y= -github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.18 h1:Z7IdFUONvTcvS7YuhtVxN99v2cCoHRXOS4mTr0B/pUc= -github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.18/go.mod h1:DkKMmksZVVyat+Y+r1dEOgJEfUeA7UngIHWeKsi0yNc= -github.com/aws/aws-sdk-go-v2/internal/ini v1.8.1 h1:VaRN3TlFdd6KxX1x3ILT5ynH6HvKgqdiXoTxAF4HQcQ= -github.com/aws/aws-sdk-go-v2/internal/ini v1.8.1/go.mod h1:FbtygfRFze9usAadmnGJNc8KsP346kEe+y2/oyhGAGc= -github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.11.5 h1:QFASJGfT8wMXtuP3D5CRmMjARHv9ZmzFUMJznHDOY3w= -github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.11.5/go.mod h1:QdZ3OmoIjSX+8D1OPAzPxDfjXASbBMDsz9qvtyIhtik= -github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.11.20 h1:Xbwbmk44URTiHNx6PNo0ujDE6ERlsCKJD3u1zfnzAPg= -github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.11.20/go.mod h1:oAfOFzUB14ltPZj1rWwRc3d/6OgD76R8KlvU3EqM9Fg= -github.com/aws/aws-sdk-go-v2/service/secretsmanager v1.33.4 h1:EoPbZg+DGTRqKKhwk5uDviV9yvx65r1kyoNNC02ZH4Y= -github.com/aws/aws-sdk-go-v2/service/secretsmanager v1.33.4/go.mod h1:WyLS5qwXHtjKAONYZq/4ewdd+hcVsa3LBu77Ow5uj3k= -github.com/aws/aws-sdk-go-v2/service/sso v1.23.4 h1:ck/Y8XWNR1gHa4BFkwE3oSu7XDJGwl+8TI7E/RB2EcQ= -github.com/aws/aws-sdk-go-v2/service/sso v1.23.4/go.mod h1:XRlMvmad0ZNL+75C5FYdMvbbLkd6qiqz6foR1nA1PXY= -github.com/aws/aws-sdk-go-v2/service/ssooidc v1.27.4 h1:4f2/JKYZHAZbQ7koBpZ012bKi32NHPY0m7TDuJgsbug= -github.com/aws/aws-sdk-go-v2/service/ssooidc v1.27.4/go.mod h1:FnvDM4sfa+isJ3kDXIzAB9GAwVSzFzSy97uZ3IsHo4E= -github.com/aws/aws-sdk-go-v2/service/sts v1.31.4 h1:uK6dUUdJtqutK1XO/tmNaQMJiPLCJY/eAeOOmqQ6ygY= -github.com/aws/aws-sdk-go-v2/service/sts v1.31.4/go.mod h1:yMWe0F+XG0DkRZK5ODZhG7BEFYhLXi2dqGsv6tX0cgI= -github.com/aws/smithy-go v1.21.0 h1:H7L8dtDRk0P1Qm6y0ji7MCYMQObJ5R9CRpyPhRUkLYA= -github.com/aws/smithy-go v1.21.0/go.mod h1:irrKGvNn1InZwb2d7fkIRNucdfwR8R+Ts3wxYa/cJHg= +github.com/aws/aws-sdk-go v1.55.7 h1:UJrkFq7es5CShfBwlWAC8DA077vp8PyVbQd3lqLiztE= +github.com/aws/aws-sdk-go v1.55.7/go.mod h1:eRwEWoyTWFMVYVQzKMNHWP5/RV4xIUGMQfXQHfHkpNU= +github.com/aws/aws-sdk-go-v2 v1.36.6 h1:zJqGjVbRdTPojeCGWn5IR5pbJwSQSBh5RWFTQcEQGdU= +github.com/aws/aws-sdk-go-v2 v1.36.6/go.mod h1:EYrzvCCN9CMUTa5+6lf6MM4tq3Zjp8UhSGR/cBsjai0= +github.com/aws/aws-sdk-go-v2/config v1.29.18 h1:x4T1GRPnqKV8HMJOMtNktbpQMl3bIsfx8KbqmveUO2I= +github.com/aws/aws-sdk-go-v2/config v1.29.18/go.mod h1:bvz8oXugIsH8K7HLhBv06vDqnFv3NsGDt2Znpk7zmOU= +github.com/aws/aws-sdk-go-v2/credentials v1.17.71 h1:r2w4mQWnrTMJjOyIsZtGp3R3XGY3nqHn8C26C2lQWgA= +github.com/aws/aws-sdk-go-v2/credentials v1.17.71/go.mod h1:E7VF3acIup4GB5ckzbKFrCK0vTvEQxOxgdq4U3vcMCY= +github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.33 h1:D9ixiWSG4lyUBL2DDNK924Px9V/NBVpML90MHqyTADY= +github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.33/go.mod h1:caS/m4DI+cij2paz3rtProRBI4s/+TCiWoaWZuQ9010= +github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.37 h1:osMWfm/sC/L4tvEdQ65Gri5ZZDCUpuYJZbTTDrsn4I0= +github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.37/go.mod h1:ZV2/1fbjOPr4G4v38G3Ww5TBT4+hmsK45s/rxu1fGy0= +github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.37 h1:v+X21AvTb2wZ+ycg1gx+orkB/9U6L7AOp93R7qYxsxM= +github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.37/go.mod h1:G0uM1kyssELxmJ2VZEfG0q2npObR3BAkF3c1VsfVnfs= +github.com/aws/aws-sdk-go-v2/internal/ini v1.8.3 h1:bIqFDwgGXXN1Kpp99pDOdKMTTb5d2KyU5X/BZxjOkRo= +github.com/aws/aws-sdk-go-v2/internal/ini v1.8.3/go.mod h1:H5O/EsxDWyU+LP/V8i5sm8cxoZgc2fdNR9bxlOFrQTo= +github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.12.4 h1:CXV68E2dNqhuynZJPB80bhPQwAKqBWVer887figW6Jc= +github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.12.4/go.mod h1:/xFi9KtvBXP97ppCz1TAEvU1Uf66qvid89rbem3wCzQ= +github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.12.18 h1:vvbXsA2TVO80/KT7ZqCbx934dt6PY+vQ8hZpUZ/cpYg= +github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.12.18/go.mod h1:m2JJHledjBGNMsLOF1g9gbAxprzq3KjC8e4lxtn+eWg= +github.com/aws/aws-sdk-go-v2/service/secretsmanager v1.35.8 h1:HD6R8K10gPbN9CNqRDOs42QombXlYeLOr4KkIxe2lQs= +github.com/aws/aws-sdk-go-v2/service/secretsmanager v1.35.8/go.mod h1:x66GdH8qjYTr6Kb4ik38Ewl6moLsg8igbceNsmxVxeA= +github.com/aws/aws-sdk-go-v2/service/sso v1.25.6 h1:rGtWqkQbPk7Bkwuv3NzpE/scwwL9sC1Ul3tn9x83DUI= +github.com/aws/aws-sdk-go-v2/service/sso v1.25.6/go.mod h1:u4ku9OLv4TO4bCPdxf4fA1upaMaJmP9ZijGk3AAOC6Q= +github.com/aws/aws-sdk-go-v2/service/ssooidc v1.30.4 h1:OV/pxyXh+eMA0TExHEC4jyWdumLxNbzz1P0zJoezkJc= +github.com/aws/aws-sdk-go-v2/service/ssooidc v1.30.4/go.mod h1:8Mm5VGYwtm+r305FfPSuc+aFkrypeylGYhFim6XEPoc= +github.com/aws/aws-sdk-go-v2/service/sts v1.34.1 h1:aUrLQwJfZtwv3/ZNG2xRtEen+NqI3iesuacjP51Mv1s= +github.com/aws/aws-sdk-go-v2/service/sts v1.34.1/go.mod h1:3wFBZKoWnX3r+Sm7in79i54fBmNfwhdNdQuscCw7QIk= +github.com/aws/smithy-go v1.22.4 h1:uqXzVZNuNexwc/xrh6Tb56u89WDlJY6HS+KC0S4QSjw= +github.com/aws/smithy-go v1.22.4/go.mod h1:t1ufH5HMublsJYulve2RKmHDC15xu1f26kHCp/HgceI= github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= diff --git a/lib/project/project/loader.go b/lib/project/project/loader.go index fec8c6d2..c667db26 100644 --- a/lib/project/project/loader.go +++ b/lib/project/project/loader.go @@ -11,12 +11,13 @@ import ( "cuelang.org/go/cue/cuecontext" "github.com/input-output-hk/catalyst-forge/lib/project/blueprint" "github.com/input-output-hk/catalyst-forge/lib/project/injector" - "github.com/input-output-hk/catalyst-forge/lib/project/secrets" + "github.com/input-output-hk/catalyst-forge/lib/providers/git" + "github.com/input-output-hk/catalyst-forge/lib/providers/github" + "github.com/input-output-hk/catalyst-forge/lib/providers/secrets" sb "github.com/input-output-hk/catalyst-forge/lib/schema/blueprint" "github.com/input-output-hk/catalyst-forge/lib/tools/earthly" "github.com/input-output-hk/catalyst-forge/lib/tools/fs" "github.com/input-output-hk/catalyst-forge/lib/tools/fs/billy" - "github.com/input-output-hk/catalyst-forge/lib/tools/git" r "github.com/input-output-hk/catalyst-forge/lib/tools/git/repo" "github.com/input-output-hk/catalyst-forge/lib/tools/walker" ) @@ -142,7 +143,13 @@ func (p *DefaultProjectLoader) Load(projectPath string) (Project, error) { p.logger.Info("Loading tag data") var tag *ProjectTag - gitTag, err := git.GetTag(&repo) + + gc, err := github.NewDefaultGithubClient("", "") + if err != nil { + return Project{}, fmt.Errorf("failed to create github client: %w", err) + } + + gitTag, err := git.GetTag(gc, &repo) if err != nil { p.logger.Warn("Failed to get git tag", "error", err) } else if gitTag != "" { diff --git a/lib/project/project/project.go b/lib/project/project/project.go index 6e796ff9..e0cefff4 100644 --- a/lib/project/project/project.go +++ b/lib/project/project/project.go @@ -8,7 +8,7 @@ import ( "cuelang.org/go/cue" "github.com/input-output-hk/catalyst-forge/lib/project/blueprint" - "github.com/input-output-hk/catalyst-forge/lib/project/secrets" + "github.com/input-output-hk/catalyst-forge/lib/providers/secrets" sb "github.com/input-output-hk/catalyst-forge/lib/schema/blueprint" "github.com/input-output-hk/catalyst-forge/lib/tools/earthly" "github.com/input-output-hk/catalyst-forge/lib/tools/git/repo" diff --git a/lib/project/project/runtime.go b/lib/project/project/runtime.go index c91c90c1..75f95bb1 100644 --- a/lib/project/project/runtime.go +++ b/lib/project/project/runtime.go @@ -6,11 +6,11 @@ import ( "cuelang.org/go/cue" "github.com/google/go-github/v66/github" + gh "github.com/input-output-hk/catalyst-forge/lib/providers/github" sb "github.com/input-output-hk/catalyst-forge/lib/schema/blueprint" sg "github.com/input-output-hk/catalyst-forge/lib/schema/blueprint/global" "github.com/input-output-hk/catalyst-forge/lib/tools/fs" "github.com/input-output-hk/catalyst-forge/lib/tools/fs/billy" - gh "github.com/input-output-hk/catalyst-forge/lib/tools/git/github" "github.com/input-output-hk/catalyst-forge/lib/tools/git/repo" ) @@ -96,11 +96,15 @@ func (g *GitRuntime) Load(project *Project) map[string]cue.Value { // getCommitHash returns the commit hash of the HEAD commit. func (g *GitRuntime) getCommitHash(repo *repo.GitRepo) (string, error) { - env := gh.NewCustomGithubEnv(g.fs, g.logger) - if env.HasEvent() { - if env.GetEventType() == "pull_request" { + gc, err := gh.NewDefaultGithubClient("", "", gh.WithFs(g.fs), gh.WithLogger(g.logger)) + if err != nil { + return "", fmt.Errorf("failed to create github client: %w", err) + } + + if gc.Env().HasEvent() { + if gc.Env().GetEventType() == "pull_request" { g.logger.Debug("Found GitHub pull request event") - event, err := env.GetEventPayload() + event, err := gc.Env().GetEventPayload() if err != nil { return "", fmt.Errorf("failed to get event payload: %w", err) } @@ -115,9 +119,9 @@ func (g *GitRuntime) getCommitHash(repo *repo.GitRepo) (string, error) { } return *pr.PullRequest.Head.SHA, nil - } else if env.GetEventType() == "push" { - g.logger.Debug("Found GitHub push event") - event, err := env.GetEventPayload() + } else if gc.Env().GetEventType() == "push" { + g.logger.Debug("xFound GitHub push event") + event, err := gc.Env().GetEventPayload() if err != nil { return "", fmt.Errorf("failed to get event payload: %w", err) } diff --git a/lib/project/providers/github.go b/lib/project/providers/github.go deleted file mode 100644 index b120f68c..00000000 --- a/lib/project/providers/github.go +++ /dev/null @@ -1,59 +0,0 @@ -package providers - -import ( - "fmt" - "log/slog" - "os" - - "github.com/google/go-github/v66/github" - "github.com/input-output-hk/catalyst-forge/lib/project/project" - "github.com/input-output-hk/catalyst-forge/lib/project/secrets" -) - -// GithubProviderCreds is the struct that holds the credentials for the Github provider -type GithubProviderCreds struct { - Token string -} - -// GetGithubProviderCreds loads the Github provider credentials from the project. -func GetGithubProviderCreds(p *project.Project, logger *slog.Logger) (GithubProviderCreds, error) { - secret := p.Blueprint.Global.Ci.Providers.Github.Credentials - if secret == nil { - return GithubProviderCreds{}, fmt.Errorf("project does not have a Github provider configured") - } - - m, err := secrets.GetSecretMap(secret, &p.SecretStore, logger) - if err != nil { - return GithubProviderCreds{}, fmt.Errorf("could not get secret: %w", err) - } - - creds, ok := m["token"] - if !ok { - return GithubProviderCreds{}, fmt.Errorf("github provider token is missing in secret") - } - - return GithubProviderCreds{Token: creds}, nil -} - -// NewGithubClient returns a new Github client. -// If a GITHUB_TOKEN environment variable is set, it will use that token. -// Otherwise, it will use the provider secret. -// If neither are set, it will create an anonymous client. -func NewGithubClient(p *project.Project, logger *slog.Logger) (*github.Client, error) { - token, exists := os.LookupEnv("GITHUB_TOKEN") - if exists { - logger.Info("Creating Github client with environment token") - return github.NewClient(nil).WithAuthToken(token), nil - } else if p.Blueprint.Global.Ci.Providers.Github.Credentials != nil { - logger.Info("Creating Github client with provider secret") - creds, err := GetGithubProviderCreds(p, logger) - if err != nil { - logger.Error("Failed to get Github provider credentials", "error", err) - } - - return github.NewClient(nil).WithAuthToken(creds.Token), nil - } - - logger.Info("Creating new anonymous Github client") - return github.NewClient(nil), nil -} diff --git a/lib/project/utils/pointers.go b/lib/project/utils/pointers.go deleted file mode 100644 index d0b60993..00000000 --- a/lib/project/utils/pointers.go +++ /dev/null @@ -1,16 +0,0 @@ -package utils - -// IntPtr returns a pointer to an integer. -func IntPtr(i int) *int { - return &i -} - -// StringPtr returns a pointer to a string. -func StringPtr(s string) *string { - return &s -} - -// BoolPtr returns a pointer to a boolean. -func BoolPtr(b bool) *bool { - return &b -} diff --git a/lib/project/utils/test/secrets.go b/lib/project/utils/test/secrets.go index fab35ace..b1940b03 100644 --- a/lib/project/utils/test/secrets.go +++ b/lib/project/utils/test/secrets.go @@ -4,8 +4,8 @@ import ( "encoding/json" "log/slog" - "github.com/input-output-hk/catalyst-forge/lib/project/secrets" - sm "github.com/input-output-hk/catalyst-forge/lib/project/secrets/mocks" + "github.com/input-output-hk/catalyst-forge/lib/providers/secrets" + sm "github.com/input-output-hk/catalyst-forge/lib/providers/secrets/mocks" ) func NewMockSecretStore(result map[string]string) secrets.SecretStore { diff --git a/lib/providers/.earthlyignore b/lib/providers/.earthlyignore new file mode 100644 index 00000000..3d720b45 --- /dev/null +++ b/lib/providers/.earthlyignore @@ -0,0 +1,4 @@ +Earthfile +README.md +LICENSE-* +blueprint.cue \ No newline at end of file diff --git a/lib/providers/Earthfile b/lib/providers/Earthfile new file mode 100644 index 00000000..d43e1619 --- /dev/null +++ b/lib/providers/Earthfile @@ -0,0 +1,39 @@ +VERSION 0.8 + +deps: + FROM golang:1.24.2-bookworm + + WORKDIR /work + + RUN mkdir -p /go/cache && mkdir -p /go/modcache + ENV GOCACHE=/go/cache + ENV GOMODCACHE=/go/modcache + CACHE --persist --sharing shared /go + + COPY ../schema+src/src /schema + COPY ../tools+src/src /tools + + COPY go.mod go.sum . + RUN go mod download + +src: + FROM +deps + + CACHE --persist --sharing shared /go + + COPY . . + + RUN go generate ./... + + SAVE ARTIFACT . src + +check: + FROM +src + + RUN gofmt -l . | grep . && exit 1 || exit 0 + RUN go vet ./... + +test: + FROM +src + + RUN go test ./... \ No newline at end of file diff --git a/lib/providers/LICENSE-APACHE b/lib/providers/LICENSE-APACHE new file mode 100644 index 00000000..a55761ab --- /dev/null +++ b/lib/providers/LICENSE-APACHE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + +TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + +1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + +2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + +3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + +4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + +5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + +6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + +7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + +8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + +9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + +END OF TERMS AND CONDITIONS + +APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + +Copyright (c) 2023 Input Output (IOG). + +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. \ No newline at end of file diff --git a/lib/providers/LICENSE-MIT b/lib/providers/LICENSE-MIT new file mode 100644 index 00000000..ac4df9c0 --- /dev/null +++ b/lib/providers/LICENSE-MIT @@ -0,0 +1,25 @@ +Copyright (c) 2024 Input Output (IOG). + +Permission is hereby granted, free of charge, to any +person obtaining a copy of this software and associated +documentation files (the "Software"), to deal in the +Software without restriction, including without +limitation the rights to use, copy, modify, merge, +publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software +is furnished to do so, subject to the following +conditions: + +The above copyright notice and this permission notice +shall be included in all copies or substantial portions +of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF +ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A +PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT +SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR +IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. \ No newline at end of file diff --git a/cli/pkg/providers/aws/common.go b/lib/providers/aws/common.go similarity index 100% rename from cli/pkg/providers/aws/common.go rename to lib/providers/aws/common.go diff --git a/cli/pkg/providers/aws/ecr.go b/lib/providers/aws/ecr.go similarity index 93% rename from cli/pkg/providers/aws/ecr.go rename to lib/providers/aws/ecr.go index 49820670..783d32b9 100644 --- a/cli/pkg/providers/aws/ecr.go +++ b/lib/providers/aws/ecr.go @@ -10,7 +10,6 @@ import ( "github.com/aws/aws-sdk-go-v2/service/ecr" "github.com/aws/aws-sdk-go-v2/service/ecr/types" "github.com/aws/aws-sdk-go/aws" - "github.com/input-output-hk/catalyst-forge/lib/project/project" ) //go:generate go run github.com/matryer/moq@latest -skip-ensure --pkg mocks -out mocks/ecr.go . AWSECRClient @@ -30,7 +29,7 @@ type ECRClient struct { // CreateECRRepository creates a new ECR repository. // By default, the repository is immutable and has image scanning enabled. // The repository is also tagged with metadata about the given project. -func (c *ECRClient) CreateECRRepository(project *project.Project, name string) error { +func (c *ECRClient) CreateECRRepository(name string, gitRepoName, gitRepoPath string) error { input := &ecr.CreateRepositoryInput{ RepositoryName: aws.String(name), ImageTagMutability: types.ImageTagMutabilityImmutable, @@ -47,11 +46,11 @@ func (c *ECRClient) CreateECRRepository(project *project.Project, name string) e }, { Key: aws.String("Repo"), - Value: aws.String(project.Blueprint.Global.Repo.Name), + Value: aws.String(gitRepoName), }, { Key: aws.String("RepoPath"), - Value: aws.String(project.Path), + Value: aws.String(gitRepoPath), }, }, } diff --git a/cli/pkg/providers/aws/ecr_test.go b/lib/providers/aws/ecr_test.go similarity index 86% rename from cli/pkg/providers/aws/ecr_test.go rename to lib/providers/aws/ecr_test.go index 6332ec70..f6c31385 100644 --- a/cli/pkg/providers/aws/ecr_test.go +++ b/lib/providers/aws/ecr_test.go @@ -8,39 +8,23 @@ import ( "github.com/aws/aws-sdk-go-v2/service/ecr" "github.com/aws/aws-sdk-go-v2/service/ecr/types" "github.com/aws/aws-sdk-go/aws" - "github.com/input-output-hk/catalyst-forge/cli/internal/testutils" - "github.com/input-output-hk/catalyst-forge/cli/pkg/providers/aws/mocks" - "github.com/input-output-hk/catalyst-forge/lib/project/project" - sb "github.com/input-output-hk/catalyst-forge/lib/schema/blueprint" - sg "github.com/input-output-hk/catalyst-forge/lib/schema/blueprint/global" + "github.com/input-output-hk/catalyst-forge/lib/providers/aws/mocks" + "github.com/input-output-hk/catalyst-forge/lib/tools/testutils" "github.com/stretchr/testify/assert" ) func TestECRClient_CreateECRRepository(t *testing.T) { - newProject := func(repo, path string) *project.Project { - return &project.Project{ - Blueprint: sb.Blueprint{ - Global: &sg.Global{ - Repo: &sg.Repo{ - Name: repo, - }, - }, - }, - Path: path, - } - } - tests := []struct { name string repo string - project *project.Project + path string fail bool validate func(t *testing.T, params *ecr.CreateRepositoryInput, err error) }{ { - name: "simple", - repo: "myapp", - project: newProject("myapp", "/path/to/myapp"), + name: "simple", + repo: "myapp", + path: "/path/to/myapp", validate: func(t *testing.T, params *ecr.CreateRepositoryInput, err error) { assert.NoError(t, err) assert.Equal(t, "myapp", *params.RepositoryName) @@ -55,10 +39,10 @@ func TestECRClient_CreateECRRepository(t *testing.T) { }, }, { - name: "failed", - repo: "myapp", - project: newProject("myapp", "/path/to/myapp"), - fail: true, + name: "failed", + repo: "myapp", + path: "/path/to/myapp", + fail: true, validate: func(t *testing.T, params *ecr.CreateRepositoryInput, err error) { assert.Error(t, err) }, @@ -85,7 +69,7 @@ func TestECRClient_CreateECRRepository(t *testing.T) { logger: testutils.NewNoopLogger(), } - err := client.CreateECRRepository(tt.project, tt.repo) + err := client.CreateECRRepository(tt.repo, tt.repo, tt.path) tt.validate(t, pp, err) }) } diff --git a/cli/pkg/providers/aws/mocks/ecr.go b/lib/providers/aws/mocks/ecr.go similarity index 100% rename from cli/pkg/providers/aws/mocks/ecr.go rename to lib/providers/aws/mocks/ecr.go diff --git a/lib/providers/aws/mocks/s3.go b/lib/providers/aws/mocks/s3.go new file mode 100644 index 00000000..77226126 --- /dev/null +++ b/lib/providers/aws/mocks/s3.go @@ -0,0 +1,196 @@ +// Code generated by moq; DO NOT EDIT. +// github.com/matryer/moq + +package mocks + +import ( + "context" + "github.com/aws/aws-sdk-go-v2/service/s3" + "sync" +) + +// AWSS3ClientMock is a mock implementation of aws.AWSS3Client. +// +// func TestSomethingThatUsesAWSS3Client(t *testing.T) { +// +// // make and configure a mocked aws.AWSS3Client +// mockedAWSS3Client := &AWSS3ClientMock{ +// DeleteObjectFunc: func(ctx context.Context, params *s3.DeleteObjectInput, optFns ...func(*s3.Options)) (*s3.DeleteObjectOutput, error) { +// panic("mock out the DeleteObject method") +// }, +// ListObjectsV2Func: func(ctx context.Context, params *s3.ListObjectsV2Input, optFns ...func(*s3.Options)) (*s3.ListObjectsV2Output, error) { +// panic("mock out the ListObjectsV2 method") +// }, +// PutObjectFunc: func(ctx context.Context, params *s3.PutObjectInput, optFns ...func(*s3.Options)) (*s3.PutObjectOutput, error) { +// panic("mock out the PutObject method") +// }, +// } +// +// // use mockedAWSS3Client in code that requires aws.AWSS3Client +// // and then make assertions. +// +// } +type AWSS3ClientMock struct { + // DeleteObjectFunc mocks the DeleteObject method. + DeleteObjectFunc func(ctx context.Context, params *s3.DeleteObjectInput, optFns ...func(*s3.Options)) (*s3.DeleteObjectOutput, error) + + // ListObjectsV2Func mocks the ListObjectsV2 method. + ListObjectsV2Func func(ctx context.Context, params *s3.ListObjectsV2Input, optFns ...func(*s3.Options)) (*s3.ListObjectsV2Output, error) + + // PutObjectFunc mocks the PutObject method. + PutObjectFunc func(ctx context.Context, params *s3.PutObjectInput, optFns ...func(*s3.Options)) (*s3.PutObjectOutput, error) + + // calls tracks calls to the methods. + calls struct { + // DeleteObject holds details about calls to the DeleteObject method. + DeleteObject []struct { + // Ctx is the ctx argument value. + Ctx context.Context + // Params is the params argument value. + Params *s3.DeleteObjectInput + // OptFns is the optFns argument value. + OptFns []func(*s3.Options) + } + // ListObjectsV2 holds details about calls to the ListObjectsV2 method. + ListObjectsV2 []struct { + // Ctx is the ctx argument value. + Ctx context.Context + // Params is the params argument value. + Params *s3.ListObjectsV2Input + // OptFns is the optFns argument value. + OptFns []func(*s3.Options) + } + // PutObject holds details about calls to the PutObject method. + PutObject []struct { + // Ctx is the ctx argument value. + Ctx context.Context + // Params is the params argument value. + Params *s3.PutObjectInput + // OptFns is the optFns argument value. + OptFns []func(*s3.Options) + } + } + lockDeleteObject sync.RWMutex + lockListObjectsV2 sync.RWMutex + lockPutObject sync.RWMutex +} + +// DeleteObject calls DeleteObjectFunc. +func (mock *AWSS3ClientMock) DeleteObject(ctx context.Context, params *s3.DeleteObjectInput, optFns ...func(*s3.Options)) (*s3.DeleteObjectOutput, error) { + if mock.DeleteObjectFunc == nil { + panic("AWSS3ClientMock.DeleteObjectFunc: method is nil but AWSS3Client.DeleteObject was just called") + } + callInfo := struct { + Ctx context.Context + Params *s3.DeleteObjectInput + OptFns []func(*s3.Options) + }{ + Ctx: ctx, + Params: params, + OptFns: optFns, + } + mock.lockDeleteObject.Lock() + mock.calls.DeleteObject = append(mock.calls.DeleteObject, callInfo) + mock.lockDeleteObject.Unlock() + return mock.DeleteObjectFunc(ctx, params, optFns...) +} + +// DeleteObjectCalls gets all the calls that were made to DeleteObject. +// Check the length with: +// +// len(mockedAWSS3Client.DeleteObjectCalls()) +func (mock *AWSS3ClientMock) DeleteObjectCalls() []struct { + Ctx context.Context + Params *s3.DeleteObjectInput + OptFns []func(*s3.Options) +} { + var calls []struct { + Ctx context.Context + Params *s3.DeleteObjectInput + OptFns []func(*s3.Options) + } + mock.lockDeleteObject.RLock() + calls = mock.calls.DeleteObject + mock.lockDeleteObject.RUnlock() + return calls +} + +// ListObjectsV2 calls ListObjectsV2Func. +func (mock *AWSS3ClientMock) ListObjectsV2(ctx context.Context, params *s3.ListObjectsV2Input, optFns ...func(*s3.Options)) (*s3.ListObjectsV2Output, error) { + if mock.ListObjectsV2Func == nil { + panic("AWSS3ClientMock.ListObjectsV2Func: method is nil but AWSS3Client.ListObjectsV2 was just called") + } + callInfo := struct { + Ctx context.Context + Params *s3.ListObjectsV2Input + OptFns []func(*s3.Options) + }{ + Ctx: ctx, + Params: params, + OptFns: optFns, + } + mock.lockListObjectsV2.Lock() + mock.calls.ListObjectsV2 = append(mock.calls.ListObjectsV2, callInfo) + mock.lockListObjectsV2.Unlock() + return mock.ListObjectsV2Func(ctx, params, optFns...) +} + +// ListObjectsV2Calls gets all the calls that were made to ListObjectsV2. +// Check the length with: +// +// len(mockedAWSS3Client.ListObjectsV2Calls()) +func (mock *AWSS3ClientMock) ListObjectsV2Calls() []struct { + Ctx context.Context + Params *s3.ListObjectsV2Input + OptFns []func(*s3.Options) +} { + var calls []struct { + Ctx context.Context + Params *s3.ListObjectsV2Input + OptFns []func(*s3.Options) + } + mock.lockListObjectsV2.RLock() + calls = mock.calls.ListObjectsV2 + mock.lockListObjectsV2.RUnlock() + return calls +} + +// PutObject calls PutObjectFunc. +func (mock *AWSS3ClientMock) PutObject(ctx context.Context, params *s3.PutObjectInput, optFns ...func(*s3.Options)) (*s3.PutObjectOutput, error) { + if mock.PutObjectFunc == nil { + panic("AWSS3ClientMock.PutObjectFunc: method is nil but AWSS3Client.PutObject was just called") + } + callInfo := struct { + Ctx context.Context + Params *s3.PutObjectInput + OptFns []func(*s3.Options) + }{ + Ctx: ctx, + Params: params, + OptFns: optFns, + } + mock.lockPutObject.Lock() + mock.calls.PutObject = append(mock.calls.PutObject, callInfo) + mock.lockPutObject.Unlock() + return mock.PutObjectFunc(ctx, params, optFns...) +} + +// PutObjectCalls gets all the calls that were made to PutObject. +// Check the length with: +// +// len(mockedAWSS3Client.PutObjectCalls()) +func (mock *AWSS3ClientMock) PutObjectCalls() []struct { + Ctx context.Context + Params *s3.PutObjectInput + OptFns []func(*s3.Options) +} { + var calls []struct { + Ctx context.Context + Params *s3.PutObjectInput + OptFns []func(*s3.Options) + } + mock.lockPutObject.RLock() + calls = mock.calls.PutObject + mock.lockPutObject.RUnlock() + return calls +} diff --git a/lib/providers/aws/s3.go b/lib/providers/aws/s3.go new file mode 100644 index 00000000..bee8d77e --- /dev/null +++ b/lib/providers/aws/s3.go @@ -0,0 +1,213 @@ +package aws + +import ( + "context" + "fmt" + "io" + "log/slog" + "mime" + "path/filepath" + "regexp" + "strings" + + "github.com/aws/aws-sdk-go-v2/service/s3" + "github.com/aws/aws-sdk-go/aws" + "github.com/input-output-hk/catalyst-forge/lib/tools/fs" + "github.com/input-output-hk/catalyst-forge/lib/tools/walker" +) + +//go:generate go run github.com/matryer/moq@latest -skip-ensure --pkg mocks -out mocks/s3.go . AWSS3Client + +// AWSS3Client is an interface for an AWS S3 client. +type AWSS3Client interface { + PutObject(ctx context.Context, params *s3.PutObjectInput, optFns ...func(*s3.Options)) (*s3.PutObjectOutput, error) + DeleteObject(ctx context.Context, params *s3.DeleteObjectInput, optFns ...func(*s3.Options)) (*s3.DeleteObjectOutput, error) + ListObjectsV2(ctx context.Context, params *s3.ListObjectsV2Input, optFns ...func(*s3.Options)) (*s3.ListObjectsV2Output, error) +} + +// S3Client is a client for interacting with AWS S3. +type S3Client struct { + client AWSS3Client + logger *slog.Logger + walker walker.Walker +} + +// UploadFile uploads a file to S3. +func (c *S3Client) UploadFile(bucket, key string, body io.Reader, contentType string) error { + input := &s3.PutObjectInput{ + Bucket: aws.String(bucket), + Key: aws.String(key), + Body: body, + ContentType: aws.String(contentType), + } + + _, err := c.client.PutObject(context.Background(), input) + if err != nil { + return fmt.Errorf("failed to upload file to S3: %w", err) + } + + c.logger.Debug("Successfully uploaded file to S3", "bucket", bucket, "key", key) + return nil +} + +// DeleteFile deletes a file from S3. +func (c *S3Client) DeleteFile(bucket, key string) error { + input := &s3.DeleteObjectInput{ + Bucket: aws.String(bucket), + Key: aws.String(key), + } + + _, err := c.client.DeleteObject(context.Background(), input) + if err != nil { + return fmt.Errorf("failed to delete file from S3: %w", err) + } + + c.logger.Debug("Successfully deleted file from S3", "bucket", bucket, "key", key) + return nil +} + +// DeleteDirectory deletes all objects in a directory (prefix) from S3. +// exclude is a list of regexes to exclude from deletion. +func (c *S3Client) DeleteDirectory(bucket, prefix string, exclude []string) error { + listInput := &s3.ListObjectsV2Input{ + Bucket: aws.String(bucket), + Prefix: aws.String(prefix), + } + + listOutput, err := c.client.ListObjectsV2(context.Background(), listInput) + if err != nil { + return fmt.Errorf("failed to list objects in S3: %w", err) + } + + for _, obj := range listOutput.Contents { + skip := false + for _, pat := range exclude { + if regexp.MustCompile(pat).MatchString(*obj.Key) { + skip = true + break + } + } + if skip { + c.logger.Debug("Skipping delete (excluded)", "key", *obj.Key) + continue + } + + if err := c.DeleteFile(bucket, *obj.Key); err != nil { + return fmt.Errorf("failed to delete object %s: %w", *obj.Key, err) + } + } + + c.logger.Debug("Successfully deleted directory from S3", "bucket", bucket, "prefix", prefix) + return nil +} + +func (c *S3Client) ListImmediateChildren(bucket, prefix string) ([]string, error) { + if prefix != "" && !strings.HasSuffix(prefix, "/") { + prefix += "/" + } + + var children []string + seen := make(map[string]struct{}) + + input := &s3.ListObjectsV2Input{ + Bucket: aws.String(bucket), + Prefix: aws.String(prefix), + Delimiter: aws.String("/"), + } + + for { + out, err := c.client.ListObjectsV2(context.Background(), input) + if err != nil { + return nil, fmt.Errorf("list objects (prefix=%s): %w", prefix, err) + } + + for _, cp := range out.CommonPrefixes { + if cp.Prefix == nil { + continue + } + + name := strings.TrimSuffix(strings.TrimPrefix(*cp.Prefix, prefix), "/") + if name == "" { + continue + } + if _, ok := seen[name]; !ok { + seen[name] = struct{}{} + children = append(children, name) + } + } + + if out.IsTruncated != nil && !*out.IsTruncated { + break + } + input.ContinuationToken = out.NextContinuationToken + } + + return children, nil +} + +// UploadDirectory uploads all files from a local directory to S3. +func (c *S3Client) UploadDirectory(bucket, prefix string, localPath string, fs fs.Filesystem) error { + if c.walker == nil { + return fmt.Errorf("walker not initialized") + } + + c.logger.Info("Uploading directory to S3", "bucket", bucket, "prefix", prefix, "localPath", localPath) + + return c.walker.Walk(localPath, func(path string, fileType walker.FileType, getReader func() (walker.FileSeeker, error)) error { + if fileType != walker.FileTypeFile { + return nil + } + + relPath, err := filepath.Rel(localPath, path) + if err != nil { + return fmt.Errorf("failed to calculate relative path: %w", err) + } + + s3Key := filepath.Join(prefix, relPath) + s3Key = filepath.ToSlash(s3Key) + + reader, err := getReader() + if err != nil { + return fmt.Errorf("failed to get file reader for %s: %w", path, err) + } + defer reader.Close() + + contentType := mime.TypeByExtension(filepath.Ext(path)) + if contentType == "" { + contentType = "application/octet-stream" + } + + c.logger.Debug("Uploading file", "localPath", path, "s3Key", s3Key, "contentType", contentType) + if err := c.UploadFile(bucket, s3Key, reader, contentType); err != nil { + return fmt.Errorf("failed to upload file %s: %w", path, err) + } + + return nil + }) +} + +// NewS3Client returns a new S3 client. +func NewS3Client(logger *slog.Logger) (S3Client, error) { + cfg, err := NewConfig() + if err != nil { + return S3Client{}, err + } + + c := s3.NewFromConfig(cfg) + w := walker.NewDefaultFSWalker(logger) + + return S3Client{ + client: c, + logger: logger, + walker: &w, + }, nil +} + +// NewCustomS3Client returns a new custom S3 client. +func NewCustomS3Client(client AWSS3Client, walker walker.Walker, logger *slog.Logger) S3Client { + return S3Client{ + client: client, + logger: logger, + walker: walker, + } +} diff --git a/lib/providers/blueprint.cue b/lib/providers/blueprint.cue new file mode 100644 index 00000000..acd6ce1b --- /dev/null +++ b/lib/providers/blueprint.cue @@ -0,0 +1 @@ +project: name: "blueprint" diff --git a/lib/project/providers/earthly.go b/lib/providers/earthly/earthly.go similarity index 94% rename from lib/project/providers/earthly.go rename to lib/providers/earthly/earthly.go index 79153c1f..1bd39297 100644 --- a/lib/project/providers/earthly.go +++ b/lib/providers/earthly/earthly.go @@ -1,10 +1,10 @@ -package providers +package earthly import ( "fmt" "log/slog" - "github.com/input-output-hk/catalyst-forge/lib/project/secrets" + "github.com/input-output-hk/catalyst-forge/lib/providers/secrets" "github.com/input-output-hk/catalyst-forge/lib/schema/blueprint/common" ) diff --git a/lib/tools/git/branch.go b/lib/providers/git/branch.go similarity index 64% rename from lib/tools/git/branch.go rename to lib/providers/git/branch.go index 6967728a..8c3e84b7 100644 --- a/lib/tools/git/branch.go +++ b/lib/providers/git/branch.go @@ -3,7 +3,7 @@ package git import ( "fmt" - "github.com/input-output-hk/catalyst-forge/lib/tools/git/github" + "github.com/input-output-hk/catalyst-forge/lib/providers/github" "github.com/input-output-hk/catalyst-forge/lib/tools/git/repo" ) @@ -11,11 +11,9 @@ var ( ErrBranchNotFound = fmt.Errorf("branch not found") ) -func GetBranch(repo *repo.GitRepo) (string, error) { - env := github.NewGithubEnv(nil) - +func GetBranch(gc github.GithubClient, repo *repo.GitRepo) (string, error) { if github.InCI() { - ref := env.GetBranch() + ref := gc.Env().GetBranch() if ref != "" { return ref, nil } diff --git a/lib/project/providers/git.go b/lib/providers/git/git.go similarity index 90% rename from lib/project/providers/git.go rename to lib/providers/git/git.go index 8cedb5df..3891e6d0 100644 --- a/lib/project/providers/git.go +++ b/lib/providers/git/git.go @@ -1,10 +1,10 @@ -package providers +package git import ( "fmt" "log/slog" - "github.com/input-output-hk/catalyst-forge/lib/project/secrets" + "github.com/input-output-hk/catalyst-forge/lib/providers/secrets" "github.com/input-output-hk/catalyst-forge/lib/schema/blueprint/common" ) diff --git a/lib/tools/git/tag.go b/lib/providers/git/tag.go similarity index 71% rename from lib/tools/git/tag.go rename to lib/providers/git/tag.go index da2b5809..5fab4f00 100644 --- a/lib/tools/git/tag.go +++ b/lib/providers/git/tag.go @@ -3,7 +3,7 @@ package git import ( "fmt" - "github.com/input-output-hk/catalyst-forge/lib/tools/git/github" + "github.com/input-output-hk/catalyst-forge/lib/providers/github" "github.com/input-output-hk/catalyst-forge/lib/tools/git/repo" ) @@ -12,13 +12,12 @@ var ( ) // GetTag returns the tag of the current HEAD commit. -func GetTag(r *repo.GitRepo) (string, error) { +func GetTag(gc github.GithubClient, r *repo.GitRepo) (string, error) { var tag string var err error - env := github.NewGithubEnv(nil) if github.InCI() { - tag = env.GetTag() + tag = gc.Env().GetTag() if tag == "" { return "", ErrTagNotFound } diff --git a/lib/tools/git/util.go b/lib/providers/git/util.go similarity index 100% rename from lib/tools/git/util.go rename to lib/providers/git/util.go diff --git a/lib/tools/git/util_test.go b/lib/providers/git/util_test.go similarity index 100% rename from lib/tools/git/util_test.go rename to lib/providers/git/util_test.go diff --git a/lib/providers/github/client.go b/lib/providers/github/client.go new file mode 100644 index 00000000..c27b3973 --- /dev/null +++ b/lib/providers/github/client.go @@ -0,0 +1,278 @@ +package github + +import ( + "context" + "fmt" + "io" + "log/slog" + "mime" + "path/filepath" + + "github.com/google/go-github/v66/github" + "github.com/input-output-hk/catalyst-forge/lib/providers/secrets" + "github.com/input-output-hk/catalyst-forge/lib/tools/fs" + "github.com/input-output-hk/catalyst-forge/lib/tools/fs/billy" +) + +var ( + ErrNoGitHubToken = fmt.Errorf("no GitHub token found") + ErrNoRepository = fmt.Errorf("no repository information found") + ErrInvalidPR = fmt.Errorf("invalid pull request number") + ErrReleaseNotFound = fmt.Errorf("release not found") +) + +//go:generate go run github.com/matryer/moq@latest -skip-ensure --pkg mocks -out mocks/github.go . GithubClient + +// GithubClient is the interface for the Github client. +type GithubClient interface { + CreateRelease(opts *github.RepositoryRelease) (*github.RepositoryRelease, error) + Env() GithubEnv + GetReleaseByTag(tag string) (*github.RepositoryRelease, error) + ListPullRequestComments(prNumber int) ([]PullRequestComment, error) + PostPullRequestComment(prNumber int, body string) error + ListBranches() ([]Branch, error) + UploadReleaseAsset(releaseID int64, path string) error +} + +// DefaultGithubClient is the default implementation of the Github client. +type DefaultGithubClient struct { + client *github.Client + env GithubEnv + fs fs.Filesystem + logger *slog.Logger + opts *DefaultGithubClientOptions + Owner string + RepoName string + secretStore *secrets.SecretStore +} + +// Branch represents a Git branch in the repository. +type Branch struct { + Name string + CommitSHA string + Protected bool +} + +// PullRequestComment is a comment on a pull request. +type PullRequestComment struct { + Author string + Body string +} + +// Env returns the Github environment. +func (g *DefaultGithubClient) Env() GithubEnv { + return g.env +} + +// CreateRelease creates a new release. +func (g *DefaultGithubClient) CreateRelease(opts *github.RepositoryRelease) (*github.RepositoryRelease, error) { + g.logger.Info("Creating release", "name", opts.Name) + release, _, err := g.client.Repositories.CreateRelease(context.Background(), g.Owner, g.RepoName, opts) + return release, err +} + +// ListPullRequestComments lists comments for a pull request. +func (g *DefaultGithubClient) ListPullRequestComments(prNumber int) ([]PullRequestComment, error) { + var all []PullRequestComment + ctx := context.Background() + opts := &github.IssueListCommentsOptions{ + ListOptions: github.ListOptions{PerPage: 100}, + } + + for { + g.logger.Debug("Fetching PR comments page", + "owner", g.Owner, "repo", g.RepoName, "pr", prNumber, "page", opts.Page) + comments, resp, err := g.client.Issues.ListComments(ctx, g.Owner, g.RepoName, prNumber, opts) + if err != nil { + return nil, fmt.Errorf("failed to list comments: %w", err) + } + + for _, c := range comments { + author := "" + if c.User != nil && c.User.Login != nil { + author = *c.User.Login + } + body := "" + if c.Body != nil { + body = *c.Body + } + all = append(all, PullRequestComment{ + Author: author, + Body: body, + }) + } + + // Break out when we've reached the last page. + if resp.NextPage == 0 { + break + } + opts.Page = resp.NextPage + } + + return all, nil +} + +// GetReleaseByTag gets a release by tag. +func (g *DefaultGithubClient) GetReleaseByTag(tag string) (*github.RepositoryRelease, error) { + release, resp, err := g.client.Repositories.GetReleaseByTag(context.Background(), g.Owner, g.RepoName, tag) + if resp.StatusCode == 404 { + return nil, ErrReleaseNotFound + } + return release, err +} + +// PostPullRequestComment posts a comment to a pull request. +func (g *DefaultGithubClient) PostPullRequestComment(prNumber int, body string) error { + if prNumber <= 0 { + return ErrInvalidPR + } + + if body == "" { + return fmt.Errorf("comment body cannot be empty") + } + + comment := &github.IssueComment{ + Body: &body, + } + + g.logger.Debug("Posting comment to PR", "owner", g.Owner, "repo", g.RepoName, "pr", prNumber) + _, _, err := g.client.Issues.CreateComment(context.Background(), g.Owner, g.RepoName, prNumber, comment) + if err != nil { + return fmt.Errorf("failed to post comment: %w", err) + } + + g.logger.Info("Successfully posted comment to PR", "owner", g.Owner, "repo", g.RepoName, "pr", prNumber) + return nil +} + +// ListBranches lists all branches in the repository. +func (g *DefaultGithubClient) ListBranches() ([]Branch, error) { + var all []Branch + ctx := context.Background() + opts := &github.BranchListOptions{ + ListOptions: github.ListOptions{PerPage: 100}, + } + + for { + g.logger.Debug("Fetching branches page", + "owner", g.Owner, "repo", g.RepoName, "page", opts.Page) + branches, resp, err := g.client.Repositories.ListBranches(ctx, g.Owner, g.RepoName, opts) + if err != nil { + return nil, fmt.Errorf("failed to list branches: %w", err) + } + + for _, b := range branches { + name := "" + if b.Name != nil { + name = *b.Name + } + + commitSHA := "" + if b.Commit != nil && b.Commit.SHA != nil { + commitSHA = *b.Commit.SHA + } + + all = append(all, Branch{ + Name: name, + CommitSHA: commitSHA, + Protected: b.GetProtected(), + }) + } + + // Break out when we've reached the last page. + if resp.NextPage == 0 { + break + } + opts.Page = resp.NextPage + } + + return all, nil +} + +// UploadReleaseAsset uploads a release asset to the given release. +func (g *DefaultGithubClient) UploadReleaseAsset(releaseID int64, path string) error { + f, err := g.fs.Open(path) + if err != nil { + return fmt.Errorf("failed to open release asset: %w", err) + } + defer f.Close() + + stat, err := f.Stat() + if err != nil { + return fmt.Errorf("failed to stat asset: %w", err) + } + + asset := filepath.Base(path) + contentType := mime.TypeByExtension(filepath.Ext(asset)) + if contentType == "" { + contentType = "application/octet-stream" + } + + url := fmt.Sprintf("repos/%s/%s/releases/%d/assets?name=%s", g.Owner, g.RepoName, releaseID, asset) + req, err := g.client.NewUploadRequest(url, f, stat.Size(), contentType) + if err != nil { + return fmt.Errorf("failed to create upload request: %w", err) + } + + _, err = g.client.Do(context.Background(), req, nil) + if err != nil { + return fmt.Errorf("failed to upload asset: %w", err) + } + + return nil +} + +// NewDefaultGithubClient creates a new DefaultGithubClient with a *github.Client and repository owner and name. +func NewDefaultGithubClient(owner, repoName string, opts ...DefaultGithubClientOption) (*DefaultGithubClient, error) { + gc := &DefaultGithubClient{ + opts: &DefaultGithubClientOptions{}, + } + for _, opt := range opts { + opt(gc) + } + + if gc.logger == nil { + gc.logger = slog.New(slog.NewTextHandler(io.Discard, nil)) + } + + if gc.fs == nil { + gc.fs = billy.NewBaseOsFS() + } + + if gc.client == nil { + if gc.opts.Token != "" { + gc.client = github.NewClient(nil).WithAuthToken(gc.opts.Token) + } else if gc.opts.Creds != nil { + if gc.secretStore == nil { + ss := secrets.NewDefaultSecretStore() + gc.secretStore = &ss + } + + creds, err := getGithubProviderCreds(gc.opts.Creds, gc.secretStore, gc.logger) + if err != nil { + return nil, fmt.Errorf("could not get Github provider credentials: %w", err) + } + gc.client = github.NewClient(nil).WithAuthToken(creds.Token) + } else { + gc.client = github.NewClient(nil) + } + } + + if gc.env == nil { + gc.env = &DefaultGithubEnv{ + fs: gc.fs, + logger: gc.logger, + } + } + + return &DefaultGithubClient{ + client: gc.client, + env: gc.env, + fs: gc.fs, + logger: gc.logger, + opts: gc.opts, + Owner: owner, + RepoName: repoName, + secretStore: gc.secretStore, + }, nil +} diff --git a/lib/providers/github/creds.go b/lib/providers/github/creds.go new file mode 100644 index 00000000..7e9848d4 --- /dev/null +++ b/lib/providers/github/creds.go @@ -0,0 +1,29 @@ +package github + +import ( + "fmt" + "log/slog" + + "github.com/input-output-hk/catalyst-forge/lib/providers/secrets" + "github.com/input-output-hk/catalyst-forge/lib/schema/blueprint/common" +) + +// GithubProviderCreds is the struct that holds the credentials for the Github provider +type GithubProviderCreds struct { + Token string +} + +// getGithubProviderCreds loads the Github provider credentials from the project. +func getGithubProviderCreds(s *common.Secret, ss *secrets.SecretStore, logger *slog.Logger) (GithubProviderCreds, error) { + m, err := secrets.GetSecretMap(s, ss, logger) + if err != nil { + return GithubProviderCreds{}, fmt.Errorf("could not get secret: %w", err) + } + + creds, ok := m["token"] + if !ok { + return GithubProviderCreds{}, fmt.Errorf("github provider token is missing in secret") + } + + return GithubProviderCreds{Token: creds}, nil +} diff --git a/lib/tools/git/github/env.go b/lib/providers/github/env.go similarity index 52% rename from lib/tools/git/github/env.go rename to lib/providers/github/env.go index debfb479..63c989e0 100644 --- a/lib/tools/git/github/env.go +++ b/lib/providers/github/env.go @@ -2,14 +2,13 @@ package github import ( "fmt" - "io" "log/slog" "os" + "strconv" "strings" "github.com/google/go-github/v66/github" "github.com/input-output-hk/catalyst-forge/lib/tools/fs" - "github.com/input-output-hk/catalyst-forge/lib/tools/fs/billy" ) var ( @@ -17,13 +16,27 @@ var ( ErrTagNotFound = fmt.Errorf("tag not found") ) +//go:generate go run github.com/matryer/moq@latest -skip-ensure --pkg mocks -out mocks/env.go . GithubEnv + // GithubEnv provides GitHub environment information. -type GithubEnv struct { +type GithubEnv interface { + GetBranch() string + GetEventPayload() (any, error) + GetEventType() string + GetPRNumber() int + GetTag() string + IsPR() bool + HasEvent() bool +} + +// DefaultGithubEnv provides the default implementation of the GithubEnv interface. +type DefaultGithubEnv struct { fs fs.Filesystem logger *slog.Logger } -func (g *GithubEnv) GetBranch() string { +// GetBranch returns the current branch from the CI environment. +func (g *DefaultGithubEnv) GetBranch() string { ref, ok := os.LookupEnv("GITHUB_HEAD_REF") if !ok || ref == "" { if strings.HasPrefix(os.Getenv("GITHUB_REF"), "refs/heads/") { @@ -35,7 +48,7 @@ func (g *GithubEnv) GetBranch() string { } // GetEventPayload returns the GitHub event payload. -func (g *GithubEnv) GetEventPayload() (any, error) { +func (g *DefaultGithubEnv) GetEventPayload() (any, error) { path, pathExists := os.LookupEnv("GITHUB_EVENT_PATH") name, nameExists := os.LookupEnv("GITHUB_EVENT_NAME") @@ -58,13 +71,13 @@ func (g *GithubEnv) GetEventPayload() (any, error) { } // GetEventType returns the GitHub event type. -func (g *GithubEnv) GetEventType() string { +func (g *DefaultGithubEnv) GetEventType() string { return os.Getenv("GITHUB_EVENT_NAME") } // GetTag returns the tag from the CI environment if it exists. // If the tag is not found, an empty string is returned. -func (g *GithubEnv) GetTag() string { +func (g *DefaultGithubEnv) GetTag() string { tag, exists := os.LookupEnv("GITHUB_REF") if exists && strings.HasPrefix(tag, "refs/tags/") { return strings.TrimPrefix(tag, "refs/tags/") @@ -73,35 +86,54 @@ func (g *GithubEnv) GetTag() string { return "" } -// HasEvent returns whether a GitHub event payload exists. -func (g *GithubEnv) HasEvent() bool { - _, pathExists := os.LookupEnv("GITHUB_EVENT_PATH") - _, nameExists := os.LookupEnv("GITHUB_EVENT_NAME") - return pathExists && nameExists -} +// GetPRNumber returns the pull request number if the current environment is associated with a PR. +// Returns 0 if not in a PR context or if the PR number cannot be determined. +func (g *DefaultGithubEnv) GetPRNumber() int { + if !g.IsPR() { + return 0 + } -// NewGithubEnv creates a new GithubEnv. -func NewGithubEnv(logger *slog.Logger) GithubEnv { - if logger == nil { - logger = slog.New(slog.NewTextHandler(io.Discard, nil)) + if prNumberStr, ok := os.LookupEnv("GITHUB_EVENT_NUMBER"); ok { + if prNumber, err := strconv.Atoi(prNumberStr); err == nil { + return prNumber + } } - return GithubEnv{ - fs: billy.NewBaseOsFS(), - logger: logger, + if g.HasEvent() { + event, err := g.GetEventPayload() + if err != nil { + g.logger.Debug("Failed to get event payload for PR number", "error", err) + return 0 + } + + if prEvent, ok := event.(*github.PullRequestEvent); ok { + if prEvent.PullRequest != nil && prEvent.PullRequest.Number != nil { + return *prEvent.PullRequest.Number + } + } } + + return 0 } -// NewCustomGithubEnv creates a new GithubEnv with a custom filesystem. -func NewCustomGithubEnv(fs fs.Filesystem, logger *slog.Logger) GithubEnv { - if logger == nil { - logger = slog.New(slog.NewTextHandler(io.Discard, nil)) +// IsPR returns whether the current environment is associated with a pull request. +func (g *DefaultGithubEnv) IsPR() bool { + if _, ok := os.LookupEnv("GITHUB_HEAD_REF"); ok { + return true } - return GithubEnv{ - fs: fs, - logger: logger, + if g.GetEventType() == "pull_request" { + return true } + + return false +} + +// HasEvent returns whether a GitHub event payload exists. +func (g *DefaultGithubEnv) HasEvent() bool { + _, pathExists := os.LookupEnv("GITHUB_EVENT_PATH") + _, nameExists := os.LookupEnv("GITHUB_EVENT_NAME") + return pathExists && nameExists } // InCI returns whether the code is running in a CI environment. diff --git a/lib/tools/git/github/env_test.go b/lib/providers/github/env_test.go similarity index 97% rename from lib/tools/git/github/env_test.go rename to lib/providers/github/env_test.go index 9bdfb8ee..ad68c216 100644 --- a/lib/tools/git/github/env_test.go +++ b/lib/providers/github/env_test.go @@ -44,7 +44,7 @@ func TestGithubEnvGetBranch(t *testing.T) { defer os.Unsetenv(k) } - gh := GithubEnv{} + gh := DefaultGithubEnv{} tt.validate(t, gh.GetBranch()) }) } @@ -121,7 +121,7 @@ func TestGithubEnvGetEventPayload(t *testing.T) { fs := billy.NewInMemoryFs() testutils.SetupFS(t, fs, tt.files) - gh := GithubEnv{ + gh := DefaultGithubEnv{ fs: fs, logger: testutils.NewNoopLogger(), } @@ -133,7 +133,7 @@ func TestGithubEnvGetEventPayload(t *testing.T) { } func TestGithubEnvGetEventType(t *testing.T) { - gh := GithubEnv{} + gh := DefaultGithubEnv{} require.NoError(t, os.Setenv("GITHUB_EVENT_NAME", "push")) assert.Equal(t, "push", gh.GetEventType()) @@ -172,7 +172,7 @@ func TestGithubEnvGetTag(t *testing.T) { defer os.Unsetenv(k) } - gh := GithubEnv{} + gh := DefaultGithubEnv{} tt.validate(t, gh.GetTag()) }) } @@ -215,7 +215,7 @@ func TestGithubEnvHasEvent(t *testing.T) { defer os.Unsetenv(k) } - gh := GithubEnv{} + gh := DefaultGithubEnv{} assert.Equal(t, tt.expect, gh.HasEvent()) }) } diff --git a/lib/providers/github/mocks/env.go b/lib/providers/github/mocks/env.go new file mode 100644 index 00000000..fe24ffc6 --- /dev/null +++ b/lib/providers/github/mocks/env.go @@ -0,0 +1,285 @@ +// Code generated by moq; DO NOT EDIT. +// github.com/matryer/moq + +package mocks + +import ( + "sync" +) + +// GithubEnvMock is a mock implementation of github.GithubEnv. +// +// func TestSomethingThatUsesGithubEnv(t *testing.T) { +// +// // make and configure a mocked github.GithubEnv +// mockedGithubEnv := &GithubEnvMock{ +// GetBranchFunc: func() string { +// panic("mock out the GetBranch method") +// }, +// GetEventPayloadFunc: func() (any, error) { +// panic("mock out the GetEventPayload method") +// }, +// GetEventTypeFunc: func() string { +// panic("mock out the GetEventType method") +// }, +// GetPRNumberFunc: func() int { +// panic("mock out the GetPRNumber method") +// }, +// GetTagFunc: func() string { +// panic("mock out the GetTag method") +// }, +// HasEventFunc: func() bool { +// panic("mock out the HasEvent method") +// }, +// IsPRFunc: func() bool { +// panic("mock out the IsPR method") +// }, +// } +// +// // use mockedGithubEnv in code that requires github.GithubEnv +// // and then make assertions. +// +// } +type GithubEnvMock struct { + // GetBranchFunc mocks the GetBranch method. + GetBranchFunc func() string + + // GetEventPayloadFunc mocks the GetEventPayload method. + GetEventPayloadFunc func() (any, error) + + // GetEventTypeFunc mocks the GetEventType method. + GetEventTypeFunc func() string + + // GetPRNumberFunc mocks the GetPRNumber method. + GetPRNumberFunc func() int + + // GetTagFunc mocks the GetTag method. + GetTagFunc func() string + + // HasEventFunc mocks the HasEvent method. + HasEventFunc func() bool + + // IsPRFunc mocks the IsPR method. + IsPRFunc func() bool + + // calls tracks calls to the methods. + calls struct { + // GetBranch holds details about calls to the GetBranch method. + GetBranch []struct { + } + // GetEventPayload holds details about calls to the GetEventPayload method. + GetEventPayload []struct { + } + // GetEventType holds details about calls to the GetEventType method. + GetEventType []struct { + } + // GetPRNumber holds details about calls to the GetPRNumber method. + GetPRNumber []struct { + } + // GetTag holds details about calls to the GetTag method. + GetTag []struct { + } + // HasEvent holds details about calls to the HasEvent method. + HasEvent []struct { + } + // IsPR holds details about calls to the IsPR method. + IsPR []struct { + } + } + lockGetBranch sync.RWMutex + lockGetEventPayload sync.RWMutex + lockGetEventType sync.RWMutex + lockGetPRNumber sync.RWMutex + lockGetTag sync.RWMutex + lockHasEvent sync.RWMutex + lockIsPR sync.RWMutex +} + +// GetBranch calls GetBranchFunc. +func (mock *GithubEnvMock) GetBranch() string { + if mock.GetBranchFunc == nil { + panic("GithubEnvMock.GetBranchFunc: method is nil but GithubEnv.GetBranch was just called") + } + callInfo := struct { + }{} + mock.lockGetBranch.Lock() + mock.calls.GetBranch = append(mock.calls.GetBranch, callInfo) + mock.lockGetBranch.Unlock() + return mock.GetBranchFunc() +} + +// GetBranchCalls gets all the calls that were made to GetBranch. +// Check the length with: +// +// len(mockedGithubEnv.GetBranchCalls()) +func (mock *GithubEnvMock) GetBranchCalls() []struct { +} { + var calls []struct { + } + mock.lockGetBranch.RLock() + calls = mock.calls.GetBranch + mock.lockGetBranch.RUnlock() + return calls +} + +// GetEventPayload calls GetEventPayloadFunc. +func (mock *GithubEnvMock) GetEventPayload() (any, error) { + if mock.GetEventPayloadFunc == nil { + panic("GithubEnvMock.GetEventPayloadFunc: method is nil but GithubEnv.GetEventPayload was just called") + } + callInfo := struct { + }{} + mock.lockGetEventPayload.Lock() + mock.calls.GetEventPayload = append(mock.calls.GetEventPayload, callInfo) + mock.lockGetEventPayload.Unlock() + return mock.GetEventPayloadFunc() +} + +// GetEventPayloadCalls gets all the calls that were made to GetEventPayload. +// Check the length with: +// +// len(mockedGithubEnv.GetEventPayloadCalls()) +func (mock *GithubEnvMock) GetEventPayloadCalls() []struct { +} { + var calls []struct { + } + mock.lockGetEventPayload.RLock() + calls = mock.calls.GetEventPayload + mock.lockGetEventPayload.RUnlock() + return calls +} + +// GetEventType calls GetEventTypeFunc. +func (mock *GithubEnvMock) GetEventType() string { + if mock.GetEventTypeFunc == nil { + panic("GithubEnvMock.GetEventTypeFunc: method is nil but GithubEnv.GetEventType was just called") + } + callInfo := struct { + }{} + mock.lockGetEventType.Lock() + mock.calls.GetEventType = append(mock.calls.GetEventType, callInfo) + mock.lockGetEventType.Unlock() + return mock.GetEventTypeFunc() +} + +// GetEventTypeCalls gets all the calls that were made to GetEventType. +// Check the length with: +// +// len(mockedGithubEnv.GetEventTypeCalls()) +func (mock *GithubEnvMock) GetEventTypeCalls() []struct { +} { + var calls []struct { + } + mock.lockGetEventType.RLock() + calls = mock.calls.GetEventType + mock.lockGetEventType.RUnlock() + return calls +} + +// GetPRNumber calls GetPRNumberFunc. +func (mock *GithubEnvMock) GetPRNumber() int { + if mock.GetPRNumberFunc == nil { + panic("GithubEnvMock.GetPRNumberFunc: method is nil but GithubEnv.GetPRNumber was just called") + } + callInfo := struct { + }{} + mock.lockGetPRNumber.Lock() + mock.calls.GetPRNumber = append(mock.calls.GetPRNumber, callInfo) + mock.lockGetPRNumber.Unlock() + return mock.GetPRNumberFunc() +} + +// GetPRNumberCalls gets all the calls that were made to GetPRNumber. +// Check the length with: +// +// len(mockedGithubEnv.GetPRNumberCalls()) +func (mock *GithubEnvMock) GetPRNumberCalls() []struct { +} { + var calls []struct { + } + mock.lockGetPRNumber.RLock() + calls = mock.calls.GetPRNumber + mock.lockGetPRNumber.RUnlock() + return calls +} + +// GetTag calls GetTagFunc. +func (mock *GithubEnvMock) GetTag() string { + if mock.GetTagFunc == nil { + panic("GithubEnvMock.GetTagFunc: method is nil but GithubEnv.GetTag was just called") + } + callInfo := struct { + }{} + mock.lockGetTag.Lock() + mock.calls.GetTag = append(mock.calls.GetTag, callInfo) + mock.lockGetTag.Unlock() + return mock.GetTagFunc() +} + +// GetTagCalls gets all the calls that were made to GetTag. +// Check the length with: +// +// len(mockedGithubEnv.GetTagCalls()) +func (mock *GithubEnvMock) GetTagCalls() []struct { +} { + var calls []struct { + } + mock.lockGetTag.RLock() + calls = mock.calls.GetTag + mock.lockGetTag.RUnlock() + return calls +} + +// HasEvent calls HasEventFunc. +func (mock *GithubEnvMock) HasEvent() bool { + if mock.HasEventFunc == nil { + panic("GithubEnvMock.HasEventFunc: method is nil but GithubEnv.HasEvent was just called") + } + callInfo := struct { + }{} + mock.lockHasEvent.Lock() + mock.calls.HasEvent = append(mock.calls.HasEvent, callInfo) + mock.lockHasEvent.Unlock() + return mock.HasEventFunc() +} + +// HasEventCalls gets all the calls that were made to HasEvent. +// Check the length with: +// +// len(mockedGithubEnv.HasEventCalls()) +func (mock *GithubEnvMock) HasEventCalls() []struct { +} { + var calls []struct { + } + mock.lockHasEvent.RLock() + calls = mock.calls.HasEvent + mock.lockHasEvent.RUnlock() + return calls +} + +// IsPR calls IsPRFunc. +func (mock *GithubEnvMock) IsPR() bool { + if mock.IsPRFunc == nil { + panic("GithubEnvMock.IsPRFunc: method is nil but GithubEnv.IsPR was just called") + } + callInfo := struct { + }{} + mock.lockIsPR.Lock() + mock.calls.IsPR = append(mock.calls.IsPR, callInfo) + mock.lockIsPR.Unlock() + return mock.IsPRFunc() +} + +// IsPRCalls gets all the calls that were made to IsPR. +// Check the length with: +// +// len(mockedGithubEnv.IsPRCalls()) +func (mock *GithubEnvMock) IsPRCalls() []struct { +} { + var calls []struct { + } + mock.lockIsPR.RLock() + calls = mock.calls.IsPR + mock.lockIsPR.RUnlock() + return calls +} diff --git a/lib/providers/github/mocks/github.go b/lib/providers/github/mocks/github.go new file mode 100644 index 00000000..f460447f --- /dev/null +++ b/lib/providers/github/mocks/github.go @@ -0,0 +1,334 @@ +// Code generated by moq; DO NOT EDIT. +// github.com/matryer/moq + +package mocks + +import ( + v66github "github.com/google/go-github/v66/github" + providersgithub "github.com/input-output-hk/catalyst-forge/lib/providers/github" + "sync" +) + +// GithubClientMock is a mock implementation of github.GithubClient. +// +// func TestSomethingThatUsesGithubClient(t *testing.T) { +// +// // make and configure a mocked github.GithubClient +// mockedGithubClient := &GithubClientMock{ +// CreateReleaseFunc: func(opts *v66github.RepositoryRelease) (*v66github.RepositoryRelease, error) { +// panic("mock out the CreateRelease method") +// }, +// EnvFunc: func() providersgithub.GithubEnv { +// panic("mock out the Env method") +// }, +// GetReleaseByTagFunc: func(tag string) (*v66github.RepositoryRelease, error) { +// panic("mock out the GetReleaseByTag method") +// }, +// ListBranchesFunc: func() ([]providersgithub.Branch, error) { +// panic("mock out the ListBranches method") +// }, +// ListPullRequestCommentsFunc: func(prNumber int) ([]providersgithub.PullRequestComment, error) { +// panic("mock out the ListPullRequestComments method") +// }, +// PostPullRequestCommentFunc: func(prNumber int, body string) error { +// panic("mock out the PostPullRequestComment method") +// }, +// UploadReleaseAssetFunc: func(releaseID int64, path string) error { +// panic("mock out the UploadReleaseAsset method") +// }, +// } +// +// // use mockedGithubClient in code that requires github.GithubClient +// // and then make assertions. +// +// } +type GithubClientMock struct { + // CreateReleaseFunc mocks the CreateRelease method. + CreateReleaseFunc func(opts *v66github.RepositoryRelease) (*v66github.RepositoryRelease, error) + + // EnvFunc mocks the Env method. + EnvFunc func() providersgithub.GithubEnv + + // GetReleaseByTagFunc mocks the GetReleaseByTag method. + GetReleaseByTagFunc func(tag string) (*v66github.RepositoryRelease, error) + + // ListBranchesFunc mocks the ListBranches method. + ListBranchesFunc func() ([]providersgithub.Branch, error) + + // ListPullRequestCommentsFunc mocks the ListPullRequestComments method. + ListPullRequestCommentsFunc func(prNumber int) ([]providersgithub.PullRequestComment, error) + + // PostPullRequestCommentFunc mocks the PostPullRequestComment method. + PostPullRequestCommentFunc func(prNumber int, body string) error + + // UploadReleaseAssetFunc mocks the UploadReleaseAsset method. + UploadReleaseAssetFunc func(releaseID int64, path string) error + + // calls tracks calls to the methods. + calls struct { + // CreateRelease holds details about calls to the CreateRelease method. + CreateRelease []struct { + // Opts is the opts argument value. + Opts *v66github.RepositoryRelease + } + // Env holds details about calls to the Env method. + Env []struct { + } + // GetReleaseByTag holds details about calls to the GetReleaseByTag method. + GetReleaseByTag []struct { + // Tag is the tag argument value. + Tag string + } + // ListBranches holds details about calls to the ListBranches method. + ListBranches []struct { + } + // ListPullRequestComments holds details about calls to the ListPullRequestComments method. + ListPullRequestComments []struct { + // PrNumber is the prNumber argument value. + PrNumber int + } + // PostPullRequestComment holds details about calls to the PostPullRequestComment method. + PostPullRequestComment []struct { + // PrNumber is the prNumber argument value. + PrNumber int + // Body is the body argument value. + Body string + } + // UploadReleaseAsset holds details about calls to the UploadReleaseAsset method. + UploadReleaseAsset []struct { + // ReleaseID is the releaseID argument value. + ReleaseID int64 + // Path is the path argument value. + Path string + } + } + lockCreateRelease sync.RWMutex + lockEnv sync.RWMutex + lockGetReleaseByTag sync.RWMutex + lockListBranches sync.RWMutex + lockListPullRequestComments sync.RWMutex + lockPostPullRequestComment sync.RWMutex + lockUploadReleaseAsset sync.RWMutex +} + +// CreateRelease calls CreateReleaseFunc. +func (mock *GithubClientMock) CreateRelease(opts *v66github.RepositoryRelease) (*v66github.RepositoryRelease, error) { + if mock.CreateReleaseFunc == nil { + panic("GithubClientMock.CreateReleaseFunc: method is nil but GithubClient.CreateRelease was just called") + } + callInfo := struct { + Opts *v66github.RepositoryRelease + }{ + Opts: opts, + } + mock.lockCreateRelease.Lock() + mock.calls.CreateRelease = append(mock.calls.CreateRelease, callInfo) + mock.lockCreateRelease.Unlock() + return mock.CreateReleaseFunc(opts) +} + +// CreateReleaseCalls gets all the calls that were made to CreateRelease. +// Check the length with: +// +// len(mockedGithubClient.CreateReleaseCalls()) +func (mock *GithubClientMock) CreateReleaseCalls() []struct { + Opts *v66github.RepositoryRelease +} { + var calls []struct { + Opts *v66github.RepositoryRelease + } + mock.lockCreateRelease.RLock() + calls = mock.calls.CreateRelease + mock.lockCreateRelease.RUnlock() + return calls +} + +// Env calls EnvFunc. +func (mock *GithubClientMock) Env() providersgithub.GithubEnv { + if mock.EnvFunc == nil { + panic("GithubClientMock.EnvFunc: method is nil but GithubClient.Env was just called") + } + callInfo := struct { + }{} + mock.lockEnv.Lock() + mock.calls.Env = append(mock.calls.Env, callInfo) + mock.lockEnv.Unlock() + return mock.EnvFunc() +} + +// EnvCalls gets all the calls that were made to Env. +// Check the length with: +// +// len(mockedGithubClient.EnvCalls()) +func (mock *GithubClientMock) EnvCalls() []struct { +} { + var calls []struct { + } + mock.lockEnv.RLock() + calls = mock.calls.Env + mock.lockEnv.RUnlock() + return calls +} + +// GetReleaseByTag calls GetReleaseByTagFunc. +func (mock *GithubClientMock) GetReleaseByTag(tag string) (*v66github.RepositoryRelease, error) { + if mock.GetReleaseByTagFunc == nil { + panic("GithubClientMock.GetReleaseByTagFunc: method is nil but GithubClient.GetReleaseByTag was just called") + } + callInfo := struct { + Tag string + }{ + Tag: tag, + } + mock.lockGetReleaseByTag.Lock() + mock.calls.GetReleaseByTag = append(mock.calls.GetReleaseByTag, callInfo) + mock.lockGetReleaseByTag.Unlock() + return mock.GetReleaseByTagFunc(tag) +} + +// GetReleaseByTagCalls gets all the calls that were made to GetReleaseByTag. +// Check the length with: +// +// len(mockedGithubClient.GetReleaseByTagCalls()) +func (mock *GithubClientMock) GetReleaseByTagCalls() []struct { + Tag string +} { + var calls []struct { + Tag string + } + mock.lockGetReleaseByTag.RLock() + calls = mock.calls.GetReleaseByTag + mock.lockGetReleaseByTag.RUnlock() + return calls +} + +// ListBranches calls ListBranchesFunc. +func (mock *GithubClientMock) ListBranches() ([]providersgithub.Branch, error) { + if mock.ListBranchesFunc == nil { + panic("GithubClientMock.ListBranchesFunc: method is nil but GithubClient.ListBranches was just called") + } + callInfo := struct { + }{} + mock.lockListBranches.Lock() + mock.calls.ListBranches = append(mock.calls.ListBranches, callInfo) + mock.lockListBranches.Unlock() + return mock.ListBranchesFunc() +} + +// ListBranchesCalls gets all the calls that were made to ListBranches. +// Check the length with: +// +// len(mockedGithubClient.ListBranchesCalls()) +func (mock *GithubClientMock) ListBranchesCalls() []struct { +} { + var calls []struct { + } + mock.lockListBranches.RLock() + calls = mock.calls.ListBranches + mock.lockListBranches.RUnlock() + return calls +} + +// ListPullRequestComments calls ListPullRequestCommentsFunc. +func (mock *GithubClientMock) ListPullRequestComments(prNumber int) ([]providersgithub.PullRequestComment, error) { + if mock.ListPullRequestCommentsFunc == nil { + panic("GithubClientMock.ListPullRequestCommentsFunc: method is nil but GithubClient.ListPullRequestComments was just called") + } + callInfo := struct { + PrNumber int + }{ + PrNumber: prNumber, + } + mock.lockListPullRequestComments.Lock() + mock.calls.ListPullRequestComments = append(mock.calls.ListPullRequestComments, callInfo) + mock.lockListPullRequestComments.Unlock() + return mock.ListPullRequestCommentsFunc(prNumber) +} + +// ListPullRequestCommentsCalls gets all the calls that were made to ListPullRequestComments. +// Check the length with: +// +// len(mockedGithubClient.ListPullRequestCommentsCalls()) +func (mock *GithubClientMock) ListPullRequestCommentsCalls() []struct { + PrNumber int +} { + var calls []struct { + PrNumber int + } + mock.lockListPullRequestComments.RLock() + calls = mock.calls.ListPullRequestComments + mock.lockListPullRequestComments.RUnlock() + return calls +} + +// PostPullRequestComment calls PostPullRequestCommentFunc. +func (mock *GithubClientMock) PostPullRequestComment(prNumber int, body string) error { + if mock.PostPullRequestCommentFunc == nil { + panic("GithubClientMock.PostPullRequestCommentFunc: method is nil but GithubClient.PostPullRequestComment was just called") + } + callInfo := struct { + PrNumber int + Body string + }{ + PrNumber: prNumber, + Body: body, + } + mock.lockPostPullRequestComment.Lock() + mock.calls.PostPullRequestComment = append(mock.calls.PostPullRequestComment, callInfo) + mock.lockPostPullRequestComment.Unlock() + return mock.PostPullRequestCommentFunc(prNumber, body) +} + +// PostPullRequestCommentCalls gets all the calls that were made to PostPullRequestComment. +// Check the length with: +// +// len(mockedGithubClient.PostPullRequestCommentCalls()) +func (mock *GithubClientMock) PostPullRequestCommentCalls() []struct { + PrNumber int + Body string +} { + var calls []struct { + PrNumber int + Body string + } + mock.lockPostPullRequestComment.RLock() + calls = mock.calls.PostPullRequestComment + mock.lockPostPullRequestComment.RUnlock() + return calls +} + +// UploadReleaseAsset calls UploadReleaseAssetFunc. +func (mock *GithubClientMock) UploadReleaseAsset(releaseID int64, path string) error { + if mock.UploadReleaseAssetFunc == nil { + panic("GithubClientMock.UploadReleaseAssetFunc: method is nil but GithubClient.UploadReleaseAsset was just called") + } + callInfo := struct { + ReleaseID int64 + Path string + }{ + ReleaseID: releaseID, + Path: path, + } + mock.lockUploadReleaseAsset.Lock() + mock.calls.UploadReleaseAsset = append(mock.calls.UploadReleaseAsset, callInfo) + mock.lockUploadReleaseAsset.Unlock() + return mock.UploadReleaseAssetFunc(releaseID, path) +} + +// UploadReleaseAssetCalls gets all the calls that were made to UploadReleaseAsset. +// Check the length with: +// +// len(mockedGithubClient.UploadReleaseAssetCalls()) +func (mock *GithubClientMock) UploadReleaseAssetCalls() []struct { + ReleaseID int64 + Path string +} { + var calls []struct { + ReleaseID int64 + Path string + } + mock.lockUploadReleaseAsset.RLock() + calls = mock.calls.UploadReleaseAsset + mock.lockUploadReleaseAsset.RUnlock() + return calls +} diff --git a/lib/providers/github/opts.go b/lib/providers/github/opts.go new file mode 100644 index 00000000..2d4cc599 --- /dev/null +++ b/lib/providers/github/opts.go @@ -0,0 +1,75 @@ +package github + +import ( + "log/slog" + "os" + + "github.com/google/go-github/v66/github" + "github.com/input-output-hk/catalyst-forge/lib/providers/secrets" + "github.com/input-output-hk/catalyst-forge/lib/schema/blueprint/common" + "github.com/input-output-hk/catalyst-forge/lib/tools/fs" +) + +type DefaultGithubClientOption func(*DefaultGithubClient) +type DefaultGithubClientOptions struct { + Creds *common.Secret + Token string +} + +// WithCreds sets the credentials for the Github client. +func WithCreds(creds *common.Secret) DefaultGithubClientOption { + return func(c *DefaultGithubClient) { + c.opts.Creds = creds + } +} + +// WithCredsOrEnv sets the credentials for the Github client. +// If a GITHUB_TOKEN environment variable is set, it will use that token. +// Otherwise, it will use the given secret. +func WithCredsOrEnv(creds *common.Secret) DefaultGithubClientOption { + token, exists := os.LookupEnv("GITHUB_TOKEN") + if exists { + return func(c *DefaultGithubClient) { + c.opts.Token = token + } + } + + return func(c *DefaultGithubClient) { + c.opts.Creds = creds + } +} + +// WithFs sets the filesystem for the Github client. +func WithFs(fs fs.Filesystem) DefaultGithubClientOption { + return func(c *DefaultGithubClient) { + c.fs = fs + } +} + +// WithGithubEnv sets the Github environment for the Github client. +func WithGithubEnv(env GithubEnv) DefaultGithubClientOption { + return func(c *DefaultGithubClient) { + c.env = env + } +} + +// WithGithubClient sets the native Github client for the Github client. +func WithGithubClient(client *github.Client) DefaultGithubClientOption { + return func(c *DefaultGithubClient) { + c.client = client + } +} + +// WithLogger sets the logger for the Github client. +func WithLogger(logger *slog.Logger) DefaultGithubClientOption { + return func(c *DefaultGithubClient) { + c.logger = logger + } +} + +// WithSecretStore sets the secret store for the Github client. +func WithSecretStore(ss *secrets.SecretStore) DefaultGithubClientOption { + return func(c *DefaultGithubClient) { + c.secretStore = ss + } +} diff --git a/lib/tools/git/github/testdata/event.json b/lib/providers/github/testdata/event.json similarity index 100% rename from lib/tools/git/github/testdata/event.json rename to lib/providers/github/testdata/event.json diff --git a/lib/providers/go.mod b/lib/providers/go.mod new file mode 100644 index 00000000..ea3d532c --- /dev/null +++ b/lib/providers/go.mod @@ -0,0 +1,63 @@ +module github.com/input-output-hk/catalyst-forge/lib/providers + +go 1.24.2 + +replace github.com/input-output-hk/catalyst-forge/lib/schema => ../schema + +replace github.com/input-output-hk/catalyst-forge/lib/tools => ../tools + +require ( + github.com/aws/aws-sdk-go v1.55.7 + github.com/aws/aws-sdk-go-v2 v1.36.6 + github.com/aws/aws-sdk-go-v2/config v1.29.18 + github.com/aws/aws-sdk-go-v2/service/ecr v1.46.0 + github.com/aws/aws-sdk-go-v2/service/s3 v1.84.1 + github.com/aws/aws-sdk-go-v2/service/secretsmanager v1.35.8 + github.com/google/go-github/v66 v66.0.0 + github.com/input-output-hk/catalyst-forge/lib/schema v0.0.0 + github.com/input-output-hk/catalyst-forge/lib/tools v0.0.0 + github.com/stretchr/testify v1.10.0 +) + +require ( + dario.cat/mergo v1.0.1 // indirect + github.com/Microsoft/go-winio v0.6.2 // indirect + github.com/ProtonMail/go-crypto v1.0.0 // indirect + github.com/adrg/xdg v0.5.3 // indirect + github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.6.11 // indirect + github.com/aws/aws-sdk-go-v2/credentials v1.17.71 // indirect + github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.33 // indirect + github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.37 // indirect + github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.37 // indirect + github.com/aws/aws-sdk-go-v2/internal/ini v1.8.3 // indirect + github.com/aws/aws-sdk-go-v2/internal/v4a v1.3.37 // indirect + github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.12.4 // indirect + github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.7.5 // indirect + github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.12.18 // indirect + github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.18.18 // indirect + github.com/aws/aws-sdk-go-v2/service/sso v1.25.6 // indirect + github.com/aws/aws-sdk-go-v2/service/ssooidc v1.30.4 // indirect + github.com/aws/aws-sdk-go-v2/service/sts v1.34.1 // indirect + github.com/aws/smithy-go v1.22.4 // indirect + github.com/cloudflare/circl v1.3.7 // indirect + github.com/cyphar/filepath-securejoin v0.3.6 // indirect + github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect + github.com/emirpasic/gods v1.18.1 // indirect + github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 // indirect + github.com/go-git/go-billy/v5 v5.5.0 // indirect + github.com/go-git/go-git/v5 v5.12.0 // indirect + github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect + github.com/google/go-querystring v1.1.0 // indirect + github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 // indirect + github.com/kevinburke/ssh_config v1.2.0 // indirect + github.com/pjbgf/sha1cd v0.3.0 // indirect + github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect + github.com/sergi/go-diff v1.3.2-0.20230802210424-5b0b94c5c0d3 // indirect + github.com/skeema/knownhosts v1.2.2 // indirect + github.com/xanzy/ssh-agent v0.3.3 // indirect + golang.org/x/crypto v0.32.0 // indirect + golang.org/x/net v0.34.0 // indirect + golang.org/x/sys v0.29.0 // indirect + gopkg.in/warnings.v0 v0.1.2 // indirect + gopkg.in/yaml.v3 v3.0.1 // indirect +) diff --git a/lib/providers/go.sum b/lib/providers/go.sum new file mode 100644 index 00000000..a01b2286 --- /dev/null +++ b/lib/providers/go.sum @@ -0,0 +1,193 @@ +dario.cat/mergo v1.0.1 h1:Ra4+bf83h2ztPIQYNP99R6m+Y7KfnARDfID+a+vLl4s= +dario.cat/mergo v1.0.1/go.mod h1:uNxQE+84aUszobStD9th8a29P2fMDhsBdgRYvZOxGmk= +github.com/Microsoft/go-winio v0.5.2/go.mod h1:WpS1mjBmmwHBEWmogvA2mj8546UReBk4v8QkMxJ6pZY= +github.com/Microsoft/go-winio v0.6.2 h1:F2VQgta7ecxGYO8k3ZZz3RS8fVIXVxONVUPlNERoyfY= +github.com/Microsoft/go-winio v0.6.2/go.mod h1:yd8OoFMLzJbo9gZq8j5qaps8bJ9aShtEA8Ipt1oGCvU= +github.com/ProtonMail/go-crypto v1.0.0 h1:LRuvITjQWX+WIfr930YHG2HNfjR1uOfyf5vE0kC2U78= +github.com/ProtonMail/go-crypto v1.0.0/go.mod h1:EjAoLdwvbIOoOQr3ihjnSoLZRtE8azugULFRteWMNc0= +github.com/adrg/xdg v0.5.3 h1:xRnxJXne7+oWDatRhR1JLnvuccuIeCoBu2rtuLqQB78= +github.com/adrg/xdg v0.5.3/go.mod h1:nlTsY+NNiCBGCK2tpm09vRqfVzrc2fLmXGpBLF0zlTQ= +github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be h1:9AeTilPcZAjCFIImctFaOjnTIavg87rW78vTPkQqLI8= +github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be/go.mod h1:ySMOLuWl6zY27l47sB3qLNK6tF2fkHG55UZxx8oIVo4= +github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 h1:0CwZNZbxp69SHPdPJAN/hZIm0C4OItdklCFmMRWYpio= +github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs= +github.com/aws/aws-sdk-go v1.55.7 h1:UJrkFq7es5CShfBwlWAC8DA077vp8PyVbQd3lqLiztE= +github.com/aws/aws-sdk-go v1.55.7/go.mod h1:eRwEWoyTWFMVYVQzKMNHWP5/RV4xIUGMQfXQHfHkpNU= +github.com/aws/aws-sdk-go-v2 v1.36.6 h1:zJqGjVbRdTPojeCGWn5IR5pbJwSQSBh5RWFTQcEQGdU= +github.com/aws/aws-sdk-go-v2 v1.36.6/go.mod h1:EYrzvCCN9CMUTa5+6lf6MM4tq3Zjp8UhSGR/cBsjai0= +github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.6.11 h1:12SpdwU8Djs+YGklkinSSlcrPyj3H4VifVsKf78KbwA= +github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.6.11/go.mod h1:dd+Lkp6YmMryke+qxW/VnKyhMBDTYP41Q2Bb+6gNZgY= +github.com/aws/aws-sdk-go-v2/config v1.29.18 h1:x4T1GRPnqKV8HMJOMtNktbpQMl3bIsfx8KbqmveUO2I= +github.com/aws/aws-sdk-go-v2/config v1.29.18/go.mod h1:bvz8oXugIsH8K7HLhBv06vDqnFv3NsGDt2Znpk7zmOU= +github.com/aws/aws-sdk-go-v2/credentials v1.17.71 h1:r2w4mQWnrTMJjOyIsZtGp3R3XGY3nqHn8C26C2lQWgA= +github.com/aws/aws-sdk-go-v2/credentials v1.17.71/go.mod h1:E7VF3acIup4GB5ckzbKFrCK0vTvEQxOxgdq4U3vcMCY= +github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.33 h1:D9ixiWSG4lyUBL2DDNK924Px9V/NBVpML90MHqyTADY= +github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.33/go.mod h1:caS/m4DI+cij2paz3rtProRBI4s/+TCiWoaWZuQ9010= +github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.37 h1:osMWfm/sC/L4tvEdQ65Gri5ZZDCUpuYJZbTTDrsn4I0= +github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.37/go.mod h1:ZV2/1fbjOPr4G4v38G3Ww5TBT4+hmsK45s/rxu1fGy0= +github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.37 h1:v+X21AvTb2wZ+ycg1gx+orkB/9U6L7AOp93R7qYxsxM= +github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.37/go.mod h1:G0uM1kyssELxmJ2VZEfG0q2npObR3BAkF3c1VsfVnfs= +github.com/aws/aws-sdk-go-v2/internal/ini v1.8.3 h1:bIqFDwgGXXN1Kpp99pDOdKMTTb5d2KyU5X/BZxjOkRo= +github.com/aws/aws-sdk-go-v2/internal/ini v1.8.3/go.mod h1:H5O/EsxDWyU+LP/V8i5sm8cxoZgc2fdNR9bxlOFrQTo= +github.com/aws/aws-sdk-go-v2/internal/v4a v1.3.37 h1:XTZZ0I3SZUHAtBLBU6395ad+VOblE0DwQP6MuaNeics= +github.com/aws/aws-sdk-go-v2/internal/v4a v1.3.37/go.mod h1:Pi6ksbniAWVwu2S8pEzcYPyhUkAcLaufxN7PfAUQjBk= +github.com/aws/aws-sdk-go-v2/service/ecr v1.46.0 h1:oyXvdONSO/VmFwEupTO+P5AFFghpNyM2MeYi7FARciM= +github.com/aws/aws-sdk-go-v2/service/ecr v1.46.0/go.mod h1:uDcrAwhZkHtPAFst5Wx7WSAhMi8BvVegEkc0Kg16vUM= +github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.12.4 h1:CXV68E2dNqhuynZJPB80bhPQwAKqBWVer887figW6Jc= +github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.12.4/go.mod h1:/xFi9KtvBXP97ppCz1TAEvU1Uf66qvid89rbem3wCzQ= +github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.7.5 h1:M5/B8JUaCI8+9QD+u3S/f4YHpvqE9RpSkV3rf0Iks2w= +github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.7.5/go.mod h1:Bktzci1bwdbpuLiu3AOksiNPMl/LLKmX1TWmqp2xbvs= +github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.12.18 h1:vvbXsA2TVO80/KT7ZqCbx934dt6PY+vQ8hZpUZ/cpYg= +github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.12.18/go.mod h1:m2JJHledjBGNMsLOF1g9gbAxprzq3KjC8e4lxtn+eWg= +github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.18.18 h1:OS2e0SKqsU2LiJPqL8u9x41tKc6MMEHrWjLVLn3oysg= +github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.18.18/go.mod h1:+Yrk+MDGzlNGxCXieljNeWpoZTCQUQVL+Jk9hGGJ8qM= +github.com/aws/aws-sdk-go-v2/service/s3 v1.84.1 h1:RkHXU9jP0DptGy7qKI8CBGsUJruWz0v5IgwBa2DwWcU= +github.com/aws/aws-sdk-go-v2/service/s3 v1.84.1/go.mod h1:3xAOf7tdKF+qbb+XpU+EPhNXAdun3Lu1RcDrj8KC24I= +github.com/aws/aws-sdk-go-v2/service/secretsmanager v1.35.8 h1:HD6R8K10gPbN9CNqRDOs42QombXlYeLOr4KkIxe2lQs= +github.com/aws/aws-sdk-go-v2/service/secretsmanager v1.35.8/go.mod h1:x66GdH8qjYTr6Kb4ik38Ewl6moLsg8igbceNsmxVxeA= +github.com/aws/aws-sdk-go-v2/service/sso v1.25.6 h1:rGtWqkQbPk7Bkwuv3NzpE/scwwL9sC1Ul3tn9x83DUI= +github.com/aws/aws-sdk-go-v2/service/sso v1.25.6/go.mod h1:u4ku9OLv4TO4bCPdxf4fA1upaMaJmP9ZijGk3AAOC6Q= +github.com/aws/aws-sdk-go-v2/service/ssooidc v1.30.4 h1:OV/pxyXh+eMA0TExHEC4jyWdumLxNbzz1P0zJoezkJc= +github.com/aws/aws-sdk-go-v2/service/ssooidc v1.30.4/go.mod h1:8Mm5VGYwtm+r305FfPSuc+aFkrypeylGYhFim6XEPoc= +github.com/aws/aws-sdk-go-v2/service/sts v1.34.1 h1:aUrLQwJfZtwv3/ZNG2xRtEen+NqI3iesuacjP51Mv1s= +github.com/aws/aws-sdk-go-v2/service/sts v1.34.1/go.mod h1:3wFBZKoWnX3r+Sm7in79i54fBmNfwhdNdQuscCw7QIk= +github.com/aws/smithy-go v1.22.4 h1:uqXzVZNuNexwc/xrh6Tb56u89WDlJY6HS+KC0S4QSjw= +github.com/aws/smithy-go v1.22.4/go.mod h1:t1ufH5HMublsJYulve2RKmHDC15xu1f26kHCp/HgceI= +github.com/bwesterb/go-ristretto v1.2.3/go.mod h1:fUIoIZaG73pV5biE2Blr2xEzDoMj7NFEuV9ekS419A0= +github.com/cloudflare/circl v1.3.3/go.mod h1:5XYMA4rFBvNIrhs50XuiBJ15vF2pZn4nnUKZrLbUZFA= +github.com/cloudflare/circl v1.3.7 h1:qlCDlTPz2n9fu58M0Nh1J/JzcFpfgkFHHX3O35r5vcU= +github.com/cloudflare/circl v1.3.7/go.mod h1:sRTcRWXGLrKw6yIGJ+l7amYJFfAXbZG0kBSc8r4zxgA= +github.com/cyphar/filepath-securejoin v0.3.6 h1:4d9N5ykBnSp5Xn2JkhocYDkOpURL/18CYMpo6xB9uWM= +github.com/cyphar/filepath-securejoin v0.3.6/go.mod h1:Sdj7gXlvMcPZsbhwhQ33GguGLDGQL7h7bg04C/+u9jI= +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM= +github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/elazarl/goproxy v0.0.0-20230808193330-2592e75ae04a h1:mATvB/9r/3gvcejNsXKSkQ6lcIaNec2nyfOdlTBR2lU= +github.com/elazarl/goproxy v0.0.0-20230808193330-2592e75ae04a/go.mod h1:Ro8st/ElPeALwNFlcTpWmkr6IoMFfkjXAvTHpevnDsM= +github.com/emirpasic/gods v1.18.1 h1:FXtiHYKDGKCW2KzwZKx0iC0PQmdlorYgdFG9jPXJ1Bc= +github.com/emirpasic/gods v1.18.1/go.mod h1:8tpGGwCnJ5H4r6BWwaV6OrWmMoPhUl5jm/FMNAnJvWQ= +github.com/gliderlabs/ssh v0.3.7 h1:iV3Bqi942d9huXnzEF2Mt+CY9gLu8DNM4Obd+8bODRE= +github.com/gliderlabs/ssh v0.3.7/go.mod h1:zpHEXBstFnQYtGnB8k8kQLol82umzn/2/snG7alWVD8= +github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 h1:+zs/tPmkDkHx3U66DAb0lQFJrpS6731Oaa12ikc+DiI= +github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376/go.mod h1:an3vInlBmSxCcxctByoQdvwPiA7DTK7jaaFDBTtu0ic= +github.com/go-git/go-billy/v5 v5.5.0 h1:yEY4yhzCDuMGSv83oGxiBotRzhwhNr8VZyphhiu+mTU= +github.com/go-git/go-billy/v5 v5.5.0/go.mod h1:hmexnoNsr2SJU1Ju67OaNz5ASJY3+sHgFRpCtpDCKow= +github.com/go-git/go-git-fixtures/v4 v4.3.2-0.20231010084843-55a94097c399 h1:eMje31YglSBqCdIqdhKBW8lokaMrL3uTkpGYlE2OOT4= +github.com/go-git/go-git-fixtures/v4 v4.3.2-0.20231010084843-55a94097c399/go.mod h1:1OCfN199q1Jm3HZlxleg+Dw/mwps2Wbk9frAWm+4FII= +github.com/go-git/go-git/v5 v5.12.0 h1:7Md+ndsjrzZxbddRDZjF14qK+NN56sy6wkqaVrjZtys= +github.com/go-git/go-git/v5 v5.12.0/go.mod h1:FTM9VKtnI2m65hNI/TenDDDnUf2Q9FHnXYjuz9i5OEY= +github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da h1:oI5xCqsCo564l8iNU+DwB5epxmsaqB+rhGL0m5jtYqE= +github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= +github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +github.com/google/go-github/v66 v66.0.0 h1:ADJsaXj9UotwdgK8/iFZtv7MLc8E8WBl62WLd/D/9+M= +github.com/google/go-github/v66 v66.0.0/go.mod h1:+4SO9Zkuyf8ytMj0csN1NR/5OTR+MfqPp8P8dVlcvY4= +github.com/google/go-querystring v1.1.0 h1:AnCroh3fv4ZBgVIf1Iwtovgjaw/GiKJo8M8yD/fhyJ8= +github.com/google/go-querystring v1.1.0/go.mod h1:Kcdr2DB4koayq7X8pmAG4sNG59So17icRSOU623lUBU= +github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 h1:BQSFePA1RWJOlocH6Fxy8MmwDt+yVQYULKfN0RoTN8A= +github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99/go.mod h1:1lJo3i6rXxKeerYnT8Nvf0QmHCRC1n8sfWVwXF2Frvo= +github.com/jmespath/go-jmespath v0.4.0 h1:BEgLn5cpjn8UN1mAw4NjwDrS35OdebyEtFe+9YPoQUg= +github.com/jmespath/go-jmespath v0.4.0/go.mod h1:T8mJZnbsbmF+m6zOOFylbeCJqk5+pHWvzYPziyZiYoo= +github.com/kevinburke/ssh_config v1.2.0 h1:x584FjTGwHzMwvHx18PXxbBVzfnxogHaAReU4gf13a4= +github.com/kevinburke/ssh_config v1.2.0/go.mod h1:CT57kijsi8u/K/BOFA39wgDQJ9CxiF4nAY/ojJ6r6mM= +github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= +github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= +github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= +github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= +github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= +github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= +github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= +github.com/onsi/gomega v1.27.10 h1:naR28SdDFlqrG6kScpT8VWpu1xWY5nJRCF3XaYyBjhI= +github.com/onsi/gomega v1.27.10/go.mod h1:RsS8tutOdbdgzbPtzzATp12yT7kM5I5aElG3evPbQ0M= +github.com/pjbgf/sha1cd v0.3.0 h1:4D5XXmUUBUl/xQ6IjCkEAbqXskkq/4O7LmGn0AqMDs4= +github.com/pjbgf/sha1cd v0.3.0/go.mod h1:nZ1rrWOcGJ5uZgEEVL1VUM9iRQiZvWdbZjkKyFzPPsI= +github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= +github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U= +github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/rogpeppe/go-internal v1.13.2-0.20241226121412-a5dc8ff20d0a h1:w3tdWGKbLGBPtR/8/oO74W6hmz0qE5q0z9aqSAewaaM= +github.com/rogpeppe/go-internal v1.13.2-0.20241226121412-a5dc8ff20d0a/go.mod h1:S8kfXMp+yh77OxPD4fdM6YUknrZpQxLhvxzS4gDHENY= +github.com/sergi/go-diff v1.3.2-0.20230802210424-5b0b94c5c0d3 h1:n661drycOFuPLCN3Uc8sB6B/s6Z4t2xvBgU1htSHuq8= +github.com/sergi/go-diff v1.3.2-0.20230802210424-5b0b94c5c0d3/go.mod h1:A0bzQcvG0E7Rwjx0REVgAGH58e96+X0MeOfepqsbeW4= +github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= +github.com/skeema/knownhosts v1.2.2 h1:Iug2P4fLmDw9f41PB6thxUkNUkJzB5i+1/exaj40L3A= +github.com/skeema/knownhosts v1.2.2/go.mod h1:xYbVRSPxqBZFrdmDyMmsOs+uX1UZC3nTN3ThzgDxUwo= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= +github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= +github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA= +github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= +github.com/xanzy/ssh-agent v0.3.3 h1:+/15pJfg/RsTxqYcX6fHqOXZwwMP+2VyYWJeWM2qQFM= +github.com/xanzy/ssh-agent v0.3.3/go.mod h1:6dzNDKs0J9rVPHPhaGCukekBHKqfl+L3KghI1Bc68Uw= +github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= +golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= +golang.org/x/crypto v0.3.1-0.20221117191849-2c476679df9a/go.mod h1:hebNnKkNXi2UzZN1eVRvBB7co0a+JxK6XbPiWVs/3J4= +golang.org/x/crypto v0.7.0/go.mod h1:pYwdfH91IfpZVANVyUOhSIPZaFoJGxTFbZhFTx+dXZU= +golang.org/x/crypto v0.32.0 h1:euUpcYgM8WcP71gNpTqQCn6rC2t6ULUPiOzfWaXVVfc= +golang.org/x/crypto v0.32.0/go.mod h1:ZnnJkOaASj8g0AjIduWNlq2NRxL0PlBrbKVyZ6V/Ugc= +golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= +golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= +golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= +golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= +golang.org/x/net v0.2.0/go.mod h1:KqCZLdyyvdV855qA2rE3GC2aiw5xGR5TEjj8smXukLY= +golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= +golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc= +golang.org/x/net v0.34.0 h1:Mb7Mrk043xzHgnRM88suvJFwzVrRfHEHJEl5/71CKw0= +golang.org/x/net v0.34.0/go.mod h1:di0qlW3YNM5oh6GqDGQr92MyTozJPmybPK4Ev/Gm31k= +golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.3.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.29.0 h1:TPYlXGxvx1MGTn2GiZDhnjPA9wZzZeGKHHmKhHYvgaU= +golang.org/x/sys v0.29.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= +golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= +golang.org/x/term v0.2.0/go.mod h1:TVmDHMZPmdnySmBfhjOoOdhjzdE1h4u1VwSiw2l1Nuc= +golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= +golang.org/x/term v0.6.0/go.mod h1:m6U89DPEgQRMq3DNkDClhWw02AUbt2daBVO4cn4Hv9U= +golang.org/x/term v0.28.0 h1:/Ts8HFuMR2E6IP/jlo7QVLZHggjKQbhu/7H0LJFr3Gg= +golang.org/x/term v0.28.0/go.mod h1:Sw/lC2IAUZ92udQNf3WodGtn4k/XoLyZoh8v/8uiwek= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= +golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= +golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= +golang.org/x/text v0.8.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= +golang.org/x/text v0.21.0 h1:zyQAAkrwaneQ066sspRyJaG9VNi/YJ1NfzcGB3hZ/qo= +golang.org/x/text v0.21.0/go.mod h1:4IBbMaMmOPCJ8SecivzSH54+73PCFmPWxNTLm+vZkEQ= +golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= +golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= +golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= +gopkg.in/warnings.v0 v0.1.2 h1:wFXVbFY8DY5/xOe1ECiWdKCzZlxgshcYVNkBHstARME= +gopkg.in/warnings.v0 v0.1.2/go.mod h1:jksf8JmL6Qr/oQM2OXTHunEvvTAsrWBLb6OOjuVWRNI= +gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/lib/project/secrets/client.go b/lib/providers/secrets/client.go similarity index 94% rename from lib/project/secrets/client.go rename to lib/providers/secrets/client.go index 7baa1899..1a0ccd35 100644 --- a/lib/project/secrets/client.go +++ b/lib/providers/secrets/client.go @@ -4,7 +4,7 @@ import ( "fmt" "log/slog" - "github.com/input-output-hk/catalyst-forge/lib/project/secrets/providers" + "github.com/input-output-hk/catalyst-forge/lib/providers/secrets/providers" ) // SecretStore is a store of secret providers. diff --git a/lib/project/secrets/interface.go b/lib/providers/secrets/interface.go similarity index 100% rename from lib/project/secrets/interface.go rename to lib/providers/secrets/interface.go diff --git a/lib/project/secrets/mocks/interface_mock.go b/lib/providers/secrets/mocks/interface_mock.go similarity index 97% rename from lib/project/secrets/mocks/interface_mock.go rename to lib/providers/secrets/mocks/interface_mock.go index 07d4da62..b028a38e 100644 --- a/lib/project/secrets/mocks/interface_mock.go +++ b/lib/providers/secrets/mocks/interface_mock.go @@ -4,8 +4,9 @@ package mocks import ( - "github.com/input-output-hk/catalyst-forge/lib/project/secrets" "sync" + + "github.com/input-output-hk/catalyst-forge/lib/providers/secrets" ) // Ensure, that SecretProviderMock does implement secrets.SecretProvider. diff --git a/lib/project/secrets/providers.go b/lib/providers/secrets/providers.go similarity index 100% rename from lib/project/secrets/providers.go rename to lib/providers/secrets/providers.go diff --git a/lib/project/secrets/providers/aws.go b/lib/providers/secrets/providers/aws.go similarity index 100% rename from lib/project/secrets/providers/aws.go rename to lib/providers/secrets/providers/aws.go diff --git a/lib/project/secrets/providers/aws_mock_test.go b/lib/providers/secrets/providers/aws_mock_test.go similarity index 100% rename from lib/project/secrets/providers/aws_mock_test.go rename to lib/providers/secrets/providers/aws_mock_test.go diff --git a/lib/project/secrets/providers/aws_test.go b/lib/providers/secrets/providers/aws_test.go similarity index 100% rename from lib/project/secrets/providers/aws_test.go rename to lib/providers/secrets/providers/aws_test.go diff --git a/lib/project/secrets/providers/env.go b/lib/providers/secrets/providers/env.go similarity index 100% rename from lib/project/secrets/providers/env.go rename to lib/providers/secrets/providers/env.go diff --git a/lib/project/secrets/providers/env_test.go b/lib/providers/secrets/providers/env_test.go similarity index 100% rename from lib/project/secrets/providers/env_test.go rename to lib/providers/secrets/providers/env_test.go diff --git a/lib/project/secrets/providers/local.go b/lib/providers/secrets/providers/local.go similarity index 100% rename from lib/project/secrets/providers/local.go rename to lib/providers/secrets/providers/local.go diff --git a/lib/project/secrets/providers/local_test.go b/lib/providers/secrets/providers/local_test.go similarity index 100% rename from lib/project/secrets/providers/local_test.go rename to lib/providers/secrets/providers/local_test.go diff --git a/lib/project/secrets/secrets.go b/lib/providers/secrets/secrets.go similarity index 100% rename from lib/project/secrets/secrets.go rename to lib/providers/secrets/secrets.go diff --git a/lib/schema/Earthfile b/lib/schema/Earthfile index 2c65772f..ff75e82a 100644 --- a/lib/schema/Earthfile +++ b/lib/schema/Earthfile @@ -1,7 +1,7 @@ VERSION 0.8 deps: - FROM golang:1.24.0-bookworm + FROM golang:1.24.2-bookworm WORKDIR /work diff --git a/lib/schema/blueprint/global/ci.cue b/lib/schema/blueprint/global/ci.cue index b8c9b38e..00d2b758 100644 --- a/lib/schema/blueprint/global/ci.cue +++ b/lib/schema/blueprint/global/ci.cue @@ -16,7 +16,9 @@ import ( // Registries contains the container registries to push images to. registries?: [...string] + // Release contains the configuration for the release of a project. + release?: #Release + // Secrets contains global secrets that will be passed to all targets. - secrets?:[...common.#Secret] + secrets?: [...common.#Secret] } - diff --git a/lib/schema/blueprint/global/cue_types_gen.go b/lib/schema/blueprint/global/cue_types_gen.go index 8387f3be..8ca5ee91 100644 --- a/lib/schema/blueprint/global/cue_types_gen.go +++ b/lib/schema/blueprint/global/cue_types_gen.go @@ -18,6 +18,9 @@ type CI struct { // Registries contains the container registries to push images to. Registries []string `json:"registries,omitempty"` + // Release contains the configuration for the release of a project. + Release *Release `json:"release,omitempty"` + // Secrets contains global secrets that will be passed to all targets. Secrets []common.Secret `json:"secrets,omitempty"` } @@ -71,6 +74,24 @@ type Global struct { State any/* CUE top */ `json:"state,omitempty"` } +// Release contains the configuration for the release of a project. +type Release struct { + // Docs is the configuration for the docs release type. + Docs *DocsRelease `json:"docs,omitempty"` +} + +// DocsRelease contains the configuration for the docs release type. +type DocsRelease struct { + // Bucket is the name of the S3 bucket to upload the docs to. + Bucket string `json:"bucket"` + + // Path is the subpath within the bucket to upload the docs to. + Path string `json:"path,omitempty"` + + // URL is the base URL to the docs. + Url string `json:"url"` +} + type Repo struct { // Name contains the name of the repository (e.g. "owner/repo-name"). Name string `json:"name"` diff --git a/lib/schema/blueprint/global/release.cue b/lib/schema/blueprint/global/release.cue new file mode 100644 index 00000000..10d59bfa --- /dev/null +++ b/lib/schema/blueprint/global/release.cue @@ -0,0 +1,19 @@ +package global + +// Release contains the configuration for the release of a project. +#Release: { + // Docs is the configuration for the docs release type. + docs?: #DocsRelease +} + +// DocsRelease contains the configuration for the docs release type. +#DocsRelease: { + // Bucket is the name of the S3 bucket to upload the docs to. + bucket: string + + // Path is the subpath within the bucket to upload the docs to. + path?: string | *"" + + // URL is the base URL to the docs. + url: string +} diff --git a/lib/schema/go.mod b/lib/schema/go.mod index 1ddab7d6..2e38b7f5 100644 --- a/lib/schema/go.mod +++ b/lib/schema/go.mod @@ -1,11 +1,10 @@ module github.com/input-output-hk/catalyst-forge/lib/schema -go 1.23.0 +go 1.24.2 require ( cuelang.org/go v0.12.0 github.com/Masterminds/semver/v3 v3.3.1 - github.com/input-output-hk/catalyst-forge/lib/tools v0.0.0 ) require ( @@ -21,6 +20,7 @@ require ( github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect github.com/protocolbuffers/txtpbfmt v0.0.0-20241112170944-20d2c9ebc01d // indirect github.com/rogpeppe/go-internal v1.13.2-0.20241226121412-a5dc8ff20d0a // indirect + github.com/stretchr/testify v1.10.0 // indirect golang.org/x/mod v0.22.0 // indirect golang.org/x/net v0.34.0 // indirect golang.org/x/oauth2 v0.25.0 // indirect diff --git a/lib/schema/go.sum b/lib/schema/go.sum index 65444768..e79d1fd6 100644 --- a/lib/schema/go.sum +++ b/lib/schema/go.sum @@ -2,46 +2,20 @@ cuelabs.dev/go/oci/ociregistry v0.0.0-20241125120445-2c00c104c6e1 h1:mRwydyTyhtR cuelabs.dev/go/oci/ociregistry v0.0.0-20241125120445-2c00c104c6e1/go.mod h1:5A4xfTzHTXfeVJBU6RAUf+QrlfTCW+017q/QiW+sMLg= cuelang.org/go v0.12.0 h1:q4W5I+RtDIA27rslQyyt6sWkXX0YS9qm43+U1/3e0kU= cuelang.org/go v0.12.0/go.mod h1:B4+kjvGGQnbkz+GuAv1dq/R308gTkp0sO28FdMrJ2Kw= -dario.cat/mergo v1.0.0 h1:AGCNq9Evsj31mOgNPcLyXc+4PNABt905YmuqPYYpBWk= -dario.cat/mergo v1.0.0/go.mod h1:uNxQE+84aUszobStD9th8a29P2fMDhsBdgRYvZOxGmk= github.com/Masterminds/semver/v3 v3.3.1 h1:QtNSWtVZ3nBfk8mAOu/B6v7FMJ+NHTIgUPi7rj+4nv4= github.com/Masterminds/semver/v3 v3.3.1/go.mod h1:4V+yj/TJE1HU9XfppCwVMZq3I84lprf4nC11bSS5beM= -github.com/Microsoft/go-winio v0.6.1 h1:9/kr64B9VUZrLm5YYwbGtUJnMgqWVOdUAXu6Migciow= -github.com/Microsoft/go-winio v0.6.1/go.mod h1:LRdKpFKfdobln8UmuiYcKPot9D2v6svN5+sAH+4kjUM= -github.com/ProtonMail/go-crypto v1.0.0 h1:LRuvITjQWX+WIfr930YHG2HNfjR1uOfyf5vE0kC2U78= -github.com/ProtonMail/go-crypto v1.0.0/go.mod h1:EjAoLdwvbIOoOQr3ihjnSoLZRtE8azugULFRteWMNc0= -github.com/adrg/xdg v0.5.3 h1:xRnxJXne7+oWDatRhR1JLnvuccuIeCoBu2rtuLqQB78= -github.com/adrg/xdg v0.5.3/go.mod h1:nlTsY+NNiCBGCK2tpm09vRqfVzrc2fLmXGpBLF0zlTQ= -github.com/cloudflare/circl v1.3.7 h1:qlCDlTPz2n9fu58M0Nh1J/JzcFpfgkFHHX3O35r5vcU= -github.com/cloudflare/circl v1.3.7/go.mod h1:sRTcRWXGLrKw6yIGJ+l7amYJFfAXbZG0kBSc8r4zxgA= github.com/cockroachdb/apd/v3 v3.2.1 h1:U+8j7t0axsIgvQUqthuNm82HIrYXodOV2iWLWtEaIwg= github.com/cockroachdb/apd/v3 v3.2.1/go.mod h1:klXJcjp+FffLTHlhIG69tezTDvdP065naDsHzKhYSqc= -github.com/cyphar/filepath-securejoin v0.2.4 h1:Ugdm7cg7i6ZK6x3xDF1oEu1nfkyfH53EtKeQYTC3kyg= -github.com/cyphar/filepath-securejoin v0.2.4/go.mod h1:aPGpWjXOXUn2NCNjFvBE6aRxGGx79pTxQpKOJNYHHl4= github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM= github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/emicklei/proto v1.13.4 h1:myn1fyf8t7tAqIzV91Tj9qXpvyXXGXk8OS2H6IBSc9g= github.com/emicklei/proto v1.13.4/go.mod h1:rn1FgRS/FANiZdD2djyH7TMA9jdRDcYQ9IEN9yvjX0A= -github.com/emirpasic/gods v1.18.1 h1:FXtiHYKDGKCW2KzwZKx0iC0PQmdlorYgdFG9jPXJ1Bc= -github.com/emirpasic/gods v1.18.1/go.mod h1:8tpGGwCnJ5H4r6BWwaV6OrWmMoPhUl5jm/FMNAnJvWQ= -github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 h1:+zs/tPmkDkHx3U66DAb0lQFJrpS6731Oaa12ikc+DiI= -github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376/go.mod h1:an3vInlBmSxCcxctByoQdvwPiA7DTK7jaaFDBTtu0ic= -github.com/go-git/go-billy/v5 v5.5.0 h1:yEY4yhzCDuMGSv83oGxiBotRzhwhNr8VZyphhiu+mTU= -github.com/go-git/go-billy/v5 v5.5.0/go.mod h1:hmexnoNsr2SJU1Ju67OaNz5ASJY3+sHgFRpCtpDCKow= -github.com/go-git/go-git/v5 v5.12.0 h1:7Md+ndsjrzZxbddRDZjF14qK+NN56sy6wkqaVrjZtys= -github.com/go-git/go-git/v5 v5.12.0/go.mod h1:FTM9VKtnI2m65hNI/TenDDDnUf2Q9FHnXYjuz9i5OEY= github.com/go-quicktest/qt v1.101.0 h1:O1K29Txy5P2OK0dGo59b7b0LR6wKfIhttaAhHUyn7eI= github.com/go-quicktest/qt v1.101.0/go.mod h1:14Bz/f7NwaXPtdYEgzsx46kqSxVwTbzVZsDC26tQJow= -github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da h1:oI5xCqsCo564l8iNU+DwB5epxmsaqB+rhGL0m5jtYqE= -github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 h1:BQSFePA1RWJOlocH6Fxy8MmwDt+yVQYULKfN0RoTN8A= -github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99/go.mod h1:1lJo3i6rXxKeerYnT8Nvf0QmHCRC1n8sfWVwXF2Frvo= -github.com/kevinburke/ssh_config v1.2.0 h1:x584FjTGwHzMwvHx18PXxbBVzfnxogHaAReU4gf13a4= -github.com/kevinburke/ssh_config v1.2.0/go.mod h1:CT57kijsi8u/K/BOFA39wgDQJ9CxiF4nAY/ojJ6r6mM= github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= @@ -58,24 +32,14 @@ github.com/opencontainers/image-spec v1.1.0 h1:8SG7/vwALn54lVB/0yZ/MMwhFrPYtpEHQ github.com/opencontainers/image-spec v1.1.0/go.mod h1:W4s4sFTMaBeK1BQLXbG4AdM2szdn85PY75RI83NrTrM= github.com/pelletier/go-toml/v2 v2.2.3 h1:YmeHyLY8mFWbdkNWwpr+qIL2bEqT0o95WSdkNHvL12M= github.com/pelletier/go-toml/v2 v2.2.3/go.mod h1:MfCQTFTvCcUyyvvwm1+G6H/jORL20Xlb6rzQu9GuUkc= -github.com/pjbgf/sha1cd v0.3.0 h1:4D5XXmUUBUl/xQ6IjCkEAbqXskkq/4O7LmGn0AqMDs4= -github.com/pjbgf/sha1cd v0.3.0/go.mod h1:nZ1rrWOcGJ5uZgEEVL1VUM9iRQiZvWdbZjkKyFzPPsI= github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U= github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/protocolbuffers/txtpbfmt v0.0.0-20241112170944-20d2c9ebc01d h1:HWfigq7lB31IeJL8iy7jkUmU/PG1Sr8jVGhS749dbUA= github.com/protocolbuffers/txtpbfmt v0.0.0-20241112170944-20d2c9ebc01d/go.mod h1:jgxiZysxFPM+iWKwQwPR+y+Jvo54ARd4EisXxKYpB5c= github.com/rogpeppe/go-internal v1.13.2-0.20241226121412-a5dc8ff20d0a h1:w3tdWGKbLGBPtR/8/oO74W6hmz0qE5q0z9aqSAewaaM= github.com/rogpeppe/go-internal v1.13.2-0.20241226121412-a5dc8ff20d0a/go.mod h1:S8kfXMp+yh77OxPD4fdM6YUknrZpQxLhvxzS4gDHENY= -github.com/sergi/go-diff v1.3.2-0.20230802210424-5b0b94c5c0d3 h1:n661drycOFuPLCN3Uc8sB6B/s6Z4t2xvBgU1htSHuq8= -github.com/sergi/go-diff v1.3.2-0.20230802210424-5b0b94c5c0d3/go.mod h1:A0bzQcvG0E7Rwjx0REVgAGH58e96+X0MeOfepqsbeW4= -github.com/skeema/knownhosts v1.2.2 h1:Iug2P4fLmDw9f41PB6thxUkNUkJzB5i+1/exaj40L3A= -github.com/skeema/knownhosts v1.2.2/go.mod h1:xYbVRSPxqBZFrdmDyMmsOs+uX1UZC3nTN3ThzgDxUwo= -github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= -github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= -github.com/xanzy/ssh-agent v0.3.3 h1:+/15pJfg/RsTxqYcX6fHqOXZwwMP+2VyYWJeWM2qQFM= -github.com/xanzy/ssh-agent v0.3.3/go.mod h1:6dzNDKs0J9rVPHPhaGCukekBHKqfl+L3KghI1Bc68Uw= -golang.org/x/crypto v0.32.0 h1:euUpcYgM8WcP71gNpTqQCn6rC2t6ULUPiOzfWaXVVfc= -golang.org/x/crypto v0.32.0/go.mod h1:ZnnJkOaASj8g0AjIduWNlq2NRxL0PlBrbKVyZ6V/Ugc= +github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA= +github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= golang.org/x/mod v0.22.0 h1:D4nJWe9zXqHOmWqj4VMOJhvzj7bEZg4wEYa759z1pH4= golang.org/x/mod v0.22.0/go.mod h1:6SkKJ3Xj0I0BrPOZoBy3bdMptDDU9oJrpohJ3eWZ1fY= golang.org/x/net v0.34.0 h1:Mb7Mrk043xzHgnRM88suvJFwzVrRfHEHJEl5/71CKw0= @@ -93,7 +57,5 @@ golang.org/x/tools v0.29.0/go.mod h1:KMQVMRsVxU6nHCFXrBPhDB8XncLNLM0lIy/F14RP588 gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/warnings.v0 v0.1.2 h1:wFXVbFY8DY5/xOe1ECiWdKCzZlxgshcYVNkBHstARME= -gopkg.in/warnings.v0 v0.1.2/go.mod h1:jksf8JmL6Qr/oQM2OXTHunEvvTAsrWBLb6OOjuVWRNI= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/lib/tools/Earthfile b/lib/tools/Earthfile index ee2df254..03988b1b 100644 --- a/lib/tools/Earthfile +++ b/lib/tools/Earthfile @@ -1,7 +1,7 @@ VERSION 0.8 deps: - FROM golang:1.24.0-bookworm + FROM golang:1.24.2-bookworm WORKDIR /work diff --git a/lib/tools/go.mod b/lib/tools/go.mod index a0c67009..f2c1d36a 100644 --- a/lib/tools/go.mod +++ b/lib/tools/go.mod @@ -1,48 +1,49 @@ module github.com/input-output-hk/catalyst-forge/lib/tools -go 1.22.3 +go 1.24.2 require ( - cuelang.org/go v0.10.0 + cuelang.org/go v0.12.0 github.com/Masterminds/semver/v3 v3.3.1 github.com/adrg/xdg v0.5.3 github.com/earthly/earthly/ast v0.0.2-0.20240228223838-42e8ca204e8a github.com/go-git/go-billy/v5 v5.5.0 github.com/go-git/go-git/v5 v5.12.0 - github.com/google/go-github/v66 v66.0.0 - github.com/stretchr/testify v1.9.0 + github.com/stretchr/testify v1.10.0 ) require ( - dario.cat/mergo v1.0.0 // indirect - github.com/Microsoft/go-winio v0.6.1 // indirect + dario.cat/mergo v1.0.1 // indirect + github.com/Microsoft/go-winio v0.6.2 // indirect github.com/ProtonMail/go-crypto v1.0.0 // indirect github.com/antlr/antlr4/runtime/Go/antlr/v4 v4.0.0-20230219212500-1f9a474cc2dc // indirect github.com/cloudflare/circl v1.3.7 // indirect github.com/cockroachdb/apd/v3 v3.2.1 // indirect - github.com/cyphar/filepath-securejoin v0.2.4 // indirect - github.com/davecgh/go-spew v1.1.1 // indirect + github.com/cyphar/filepath-securejoin v0.3.6 // indirect + github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect github.com/emirpasic/gods v1.18.1 // indirect github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 // indirect github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect - github.com/google/go-querystring v1.1.0 // indirect github.com/google/uuid v1.6.0 // indirect github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 // indirect github.com/kevinburke/ssh_config v1.2.0 // indirect + github.com/pelletier/go-toml/v2 v2.2.3 // indirect github.com/pjbgf/sha1cd v0.3.0 // indirect github.com/pkg/errors v0.9.1 // indirect - github.com/pmezard/go-difflib v1.0.0 // indirect + github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect github.com/sergi/go-diff v1.3.2-0.20230802210424-5b0b94c5c0d3 // indirect github.com/skeema/knownhosts v1.2.2 // indirect github.com/xanzy/ssh-agent v0.3.3 // indirect - golang.org/x/crypto v0.26.0 // indirect - golang.org/x/exp v0.0.0-20230224173230-c95f2b4c22f2 // indirect - golang.org/x/mod v0.20.0 // indirect - golang.org/x/net v0.28.0 // indirect - golang.org/x/sync v0.8.0 // indirect - golang.org/x/sys v0.26.0 // indirect - golang.org/x/text v0.17.0 // indirect - golang.org/x/tools v0.24.0 // indirect + golang.org/x/crypto v0.32.0 // indirect + golang.org/x/exp v0.0.0-20241009180824-f66d83c29e7c // indirect + golang.org/x/mod v0.22.0 // indirect + golang.org/x/net v0.34.0 // indirect + golang.org/x/sys v0.29.0 // indirect + golang.org/x/text v0.21.0 // indirect gopkg.in/warnings.v0 v0.1.2 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) + +replace github.com/input-output-hk/catalyst-forge/lib/providers => ../providers + +replace github.com/input-output-hk/catalyst-forge/lib/schema => ../schema diff --git a/lib/tools/go.sum b/lib/tools/go.sum index b8e42ab4..8da796e0 100644 --- a/lib/tools/go.sum +++ b/lib/tools/go.sum @@ -1,14 +1,14 @@ -cuelabs.dev/go/oci/ociregistry v0.0.0-20240807094312-a32ad29eed79 h1:EceZITBGET3qHneD5xowSTY/YHbNybvMWGh62K2fG/M= -cuelabs.dev/go/oci/ociregistry v0.0.0-20240807094312-a32ad29eed79/go.mod h1:5A4xfTzHTXfeVJBU6RAUf+QrlfTCW+017q/QiW+sMLg= -cuelang.org/go v0.10.0 h1:Y1Pu4wwga5HkXfLFK1sWAYaSWIBdcsr5Cb5AWj2pOuE= -cuelang.org/go v0.10.0/go.mod h1:HzlaqqqInHNiqE6slTP6+UtxT9hN6DAzgJgdbNxXvX8= -dario.cat/mergo v1.0.0 h1:AGCNq9Evsj31mOgNPcLyXc+4PNABt905YmuqPYYpBWk= -dario.cat/mergo v1.0.0/go.mod h1:uNxQE+84aUszobStD9th8a29P2fMDhsBdgRYvZOxGmk= +cuelabs.dev/go/oci/ociregistry v0.0.0-20241125120445-2c00c104c6e1 h1:mRwydyTyhtRX2wXS3mqYWzR2qlv6KsmoKXmlz5vInjg= +cuelabs.dev/go/oci/ociregistry v0.0.0-20241125120445-2c00c104c6e1/go.mod h1:5A4xfTzHTXfeVJBU6RAUf+QrlfTCW+017q/QiW+sMLg= +cuelang.org/go v0.12.0 h1:q4W5I+RtDIA27rslQyyt6sWkXX0YS9qm43+U1/3e0kU= +cuelang.org/go v0.12.0/go.mod h1:B4+kjvGGQnbkz+GuAv1dq/R308gTkp0sO28FdMrJ2Kw= +dario.cat/mergo v1.0.1 h1:Ra4+bf83h2ztPIQYNP99R6m+Y7KfnARDfID+a+vLl4s= +dario.cat/mergo v1.0.1/go.mod h1:uNxQE+84aUszobStD9th8a29P2fMDhsBdgRYvZOxGmk= github.com/Masterminds/semver/v3 v3.3.1 h1:QtNSWtVZ3nBfk8mAOu/B6v7FMJ+NHTIgUPi7rj+4nv4= github.com/Masterminds/semver/v3 v3.3.1/go.mod h1:4V+yj/TJE1HU9XfppCwVMZq3I84lprf4nC11bSS5beM= github.com/Microsoft/go-winio v0.5.2/go.mod h1:WpS1mjBmmwHBEWmogvA2mj8546UReBk4v8QkMxJ6pZY= -github.com/Microsoft/go-winio v0.6.1 h1:9/kr64B9VUZrLm5YYwbGtUJnMgqWVOdUAXu6Migciow= -github.com/Microsoft/go-winio v0.6.1/go.mod h1:LRdKpFKfdobln8UmuiYcKPot9D2v6svN5+sAH+4kjUM= +github.com/Microsoft/go-winio v0.6.2 h1:F2VQgta7ecxGYO8k3ZZz3RS8fVIXVxONVUPlNERoyfY= +github.com/Microsoft/go-winio v0.6.2/go.mod h1:yd8OoFMLzJbo9gZq8j5qaps8bJ9aShtEA8Ipt1oGCvU= github.com/ProtonMail/go-crypto v1.0.0 h1:LRuvITjQWX+WIfr930YHG2HNfjR1uOfyf5vE0kC2U78= github.com/ProtonMail/go-crypto v1.0.0/go.mod h1:EjAoLdwvbIOoOQr3ihjnSoLZRtE8azugULFRteWMNc0= github.com/adrg/xdg v0.5.3 h1:xRnxJXne7+oWDatRhR1JLnvuccuIeCoBu2rtuLqQB78= @@ -25,17 +25,18 @@ github.com/cloudflare/circl v1.3.7 h1:qlCDlTPz2n9fu58M0Nh1J/JzcFpfgkFHHX3O35r5vc github.com/cloudflare/circl v1.3.7/go.mod h1:sRTcRWXGLrKw6yIGJ+l7amYJFfAXbZG0kBSc8r4zxgA= github.com/cockroachdb/apd/v3 v3.2.1 h1:U+8j7t0axsIgvQUqthuNm82HIrYXodOV2iWLWtEaIwg= github.com/cockroachdb/apd/v3 v3.2.1/go.mod h1:klXJcjp+FffLTHlhIG69tezTDvdP065naDsHzKhYSqc= -github.com/cyphar/filepath-securejoin v0.2.4 h1:Ugdm7cg7i6ZK6x3xDF1oEu1nfkyfH53EtKeQYTC3kyg= -github.com/cyphar/filepath-securejoin v0.2.4/go.mod h1:aPGpWjXOXUn2NCNjFvBE6aRxGGx79pTxQpKOJNYHHl4= +github.com/cyphar/filepath-securejoin v0.3.6 h1:4d9N5ykBnSp5Xn2JkhocYDkOpURL/18CYMpo6xB9uWM= +github.com/cyphar/filepath-securejoin v0.3.6/go.mod h1:Sdj7gXlvMcPZsbhwhQ33GguGLDGQL7h7bg04C/+u9jI= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM= +github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/earthly/earthly/ast v0.0.2-0.20240228223838-42e8ca204e8a h1:Z4oatniIQ8EG0JL26cX9cc7IeJUe9Zs7wFetMJpbEhY= github.com/earthly/earthly/ast v0.0.2-0.20240228223838-42e8ca204e8a/go.mod h1:74/Fa5yMVQdnD/a32pXf8CrzH6MfAaXNIFt15MoHuv0= github.com/elazarl/goproxy v0.0.0-20230808193330-2592e75ae04a h1:mATvB/9r/3gvcejNsXKSkQ6lcIaNec2nyfOdlTBR2lU= github.com/elazarl/goproxy v0.0.0-20230808193330-2592e75ae04a/go.mod h1:Ro8st/ElPeALwNFlcTpWmkr6IoMFfkjXAvTHpevnDsM= -github.com/emicklei/proto v1.13.2 h1:z/etSFO3uyXeuEsVPzfl56WNgzcvIr42aQazXaQmFZY= -github.com/emicklei/proto v1.13.2/go.mod h1:rn1FgRS/FANiZdD2djyH7TMA9jdRDcYQ9IEN9yvjX0A= +github.com/emicklei/proto v1.13.4 h1:myn1fyf8t7tAqIzV91Tj9qXpvyXXGXk8OS2H6IBSc9g= +github.com/emicklei/proto v1.13.4/go.mod h1:rn1FgRS/FANiZdD2djyH7TMA9jdRDcYQ9IEN9yvjX0A= github.com/emirpasic/gods v1.18.1 h1:FXtiHYKDGKCW2KzwZKx0iC0PQmdlorYgdFG9jPXJ1Bc= github.com/emirpasic/gods v1.18.1/go.mod h1:8tpGGwCnJ5H4r6BWwaV6OrWmMoPhUl5jm/FMNAnJvWQ= github.com/gliderlabs/ssh v0.3.7 h1:iV3Bqi942d9huXnzEF2Mt+CY9gLu8DNM4Obd+8bODRE= @@ -52,13 +53,8 @@ github.com/go-quicktest/qt v1.101.0 h1:O1K29Txy5P2OK0dGo59b7b0LR6wKfIhttaAhHUyn7 github.com/go-quicktest/qt v1.101.0/go.mod h1:14Bz/f7NwaXPtdYEgzsx46kqSxVwTbzVZsDC26tQJow= github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da h1:oI5xCqsCo564l8iNU+DwB5epxmsaqB+rhGL0m5jtYqE= github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= -github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= -github.com/google/go-github/v66 v66.0.0 h1:ADJsaXj9UotwdgK8/iFZtv7MLc8E8WBl62WLd/D/9+M= -github.com/google/go-github/v66 v66.0.0/go.mod h1:+4SO9Zkuyf8ytMj0csN1NR/5OTR+MfqPp8P8dVlcvY4= -github.com/google/go-querystring v1.1.0 h1:AnCroh3fv4ZBgVIf1Iwtovgjaw/GiKJo8M8yD/fhyJ8= -github.com/google/go-querystring v1.1.0/go.mod h1:Kcdr2DB4koayq7X8pmAG4sNG59So17icRSOU623lUBU= github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 h1:BQSFePA1RWJOlocH6Fxy8MmwDt+yVQYULKfN0RoTN8A= @@ -82,18 +78,19 @@ github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8 github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM= github.com/opencontainers/image-spec v1.1.0 h1:8SG7/vwALn54lVB/0yZ/MMwhFrPYtpEHQb2IpWsCzug= github.com/opencontainers/image-spec v1.1.0/go.mod h1:W4s4sFTMaBeK1BQLXbG4AdM2szdn85PY75RI83NrTrM= -github.com/pelletier/go-toml/v2 v2.2.2 h1:aYUidT7k73Pcl9nb2gScu7NSrKCSHIDE89b3+6Wq+LM= -github.com/pelletier/go-toml/v2 v2.2.2/go.mod h1:1t835xjRzz80PqgE6HHgN2JOsmgYu/h4qDAS4n929Rs= +github.com/pelletier/go-toml/v2 v2.2.3 h1:YmeHyLY8mFWbdkNWwpr+qIL2bEqT0o95WSdkNHvL12M= +github.com/pelletier/go-toml/v2 v2.2.3/go.mod h1:MfCQTFTvCcUyyvvwm1+G6H/jORL20Xlb6rzQu9GuUkc= github.com/pjbgf/sha1cd v0.3.0 h1:4D5XXmUUBUl/xQ6IjCkEAbqXskkq/4O7LmGn0AqMDs4= github.com/pjbgf/sha1cd v0.3.0/go.mod h1:nZ1rrWOcGJ5uZgEEVL1VUM9iRQiZvWdbZjkKyFzPPsI= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= -github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/protocolbuffers/txtpbfmt v0.0.0-20230328191034-3462fbc510c0 h1:sadMIsgmHpEOGbUs6VtHBXRR1OHevnj7hLx9ZcdNGW4= -github.com/protocolbuffers/txtpbfmt v0.0.0-20230328191034-3462fbc510c0/go.mod h1:jgxiZysxFPM+iWKwQwPR+y+Jvo54ARd4EisXxKYpB5c= -github.com/rogpeppe/go-internal v1.12.1-0.20240709150035-ccf4b4329d21 h1:igWZJluD8KtEtAgRyF4x6lqcxDry1ULztksMJh2mnQE= -github.com/rogpeppe/go-internal v1.12.1-0.20240709150035-ccf4b4329d21/go.mod h1:RMRJLmBOqWacUkmJHRMiPKh1S1m3PA7Zh4W80/kWPpg= +github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U= +github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/protocolbuffers/txtpbfmt v0.0.0-20241112170944-20d2c9ebc01d h1:HWfigq7lB31IeJL8iy7jkUmU/PG1Sr8jVGhS749dbUA= +github.com/protocolbuffers/txtpbfmt v0.0.0-20241112170944-20d2c9ebc01d/go.mod h1:jgxiZysxFPM+iWKwQwPR+y+Jvo54ARd4EisXxKYpB5c= +github.com/rogpeppe/go-internal v1.13.2-0.20241226121412-a5dc8ff20d0a h1:w3tdWGKbLGBPtR/8/oO74W6hmz0qE5q0z9aqSAewaaM= +github.com/rogpeppe/go-internal v1.13.2-0.20241226121412-a5dc8ff20d0a/go.mod h1:S8kfXMp+yh77OxPD4fdM6YUknrZpQxLhvxzS4gDHENY= github.com/sergi/go-diff v1.3.2-0.20230802210424-5b0b94c5c0d3 h1:n661drycOFuPLCN3Uc8sB6B/s6Z4t2xvBgU1htSHuq8= github.com/sergi/go-diff v1.3.2-0.20230802210424-5b0b94c5c0d3/go.mod h1:A0bzQcvG0E7Rwjx0REVgAGH58e96+X0MeOfepqsbeW4= github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= @@ -102,8 +99,8 @@ github.com/skeema/knownhosts v1.2.2/go.mod h1:xYbVRSPxqBZFrdmDyMmsOs+uX1UZC3nTN3 github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= -github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= -github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= +github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA= +github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= github.com/xanzy/ssh-agent v0.3.3 h1:+/15pJfg/RsTxqYcX6fHqOXZwwMP+2VyYWJeWM2qQFM= github.com/xanzy/ssh-agent v0.3.3/go.mod h1:6dzNDKs0J9rVPHPhaGCukekBHKqfl+L3KghI1Bc68Uw= github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= @@ -112,14 +109,14 @@ golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5y golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/crypto v0.3.1-0.20221117191849-2c476679df9a/go.mod h1:hebNnKkNXi2UzZN1eVRvBB7co0a+JxK6XbPiWVs/3J4= golang.org/x/crypto v0.7.0/go.mod h1:pYwdfH91IfpZVANVyUOhSIPZaFoJGxTFbZhFTx+dXZU= -golang.org/x/crypto v0.26.0 h1:RrRspgV4mU+YwB4FYnuBoKsUapNIL5cohGAmSH3azsw= -golang.org/x/crypto v0.26.0/go.mod h1:GY7jblb9wI+FOo5y8/S2oY4zWP07AkOJ4+jxCqdqn54= -golang.org/x/exp v0.0.0-20230224173230-c95f2b4c22f2 h1:Jvc7gsqn21cJHCmAWx0LiimpP18LZmUxkT5Mp7EZ1mI= -golang.org/x/exp v0.0.0-20230224173230-c95f2b4c22f2/go.mod h1:CxIveKay+FTh1D0yPZemJVgC/95VzuuOLq5Qi4xnoYc= +golang.org/x/crypto v0.32.0 h1:euUpcYgM8WcP71gNpTqQCn6rC2t6ULUPiOzfWaXVVfc= +golang.org/x/crypto v0.32.0/go.mod h1:ZnnJkOaASj8g0AjIduWNlq2NRxL0PlBrbKVyZ6V/Ugc= +golang.org/x/exp v0.0.0-20241009180824-f66d83c29e7c h1:7dEasQXItcW1xKJ2+gg5VOiBnqWrJc+rq0DPKyvvdbY= +golang.org/x/exp v0.0.0-20241009180824-f66d83c29e7c/go.mod h1:NQtJDoLvd6faHhE7m4T/1IY708gDefGGjR/iUW8yQQ8= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= -golang.org/x/mod v0.20.0 h1:utOm6MM3R3dnawAiJgn0y+xvuYRsm1RKM/4giyfDgV0= -golang.org/x/mod v0.20.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= +golang.org/x/mod v0.22.0 h1:D4nJWe9zXqHOmWqj4VMOJhvzj7bEZg4wEYa759z1pH4= +golang.org/x/mod v0.22.0/go.mod h1:6SkKJ3Xj0I0BrPOZoBy3bdMptDDU9oJrpohJ3eWZ1fY= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= @@ -127,15 +124,15 @@ golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug golang.org/x/net v0.2.0/go.mod h1:KqCZLdyyvdV855qA2rE3GC2aiw5xGR5TEjj8smXukLY= golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc= -golang.org/x/net v0.28.0 h1:a9JDOJc5GMUJ0+UDqmLT86WiEy7iWyIhz8gz8E4e5hE= -golang.org/x/net v0.28.0/go.mod h1:yqtgsTWOOnlGLG9GFRrK3++bGOUEkNBoHZc8MEDWPNg= -golang.org/x/oauth2 v0.22.0 h1:BzDx2FehcG7jJwgWLELCdmLuxk2i+x9UDpSiss2u0ZA= -golang.org/x/oauth2 v0.22.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI= +golang.org/x/net v0.34.0 h1:Mb7Mrk043xzHgnRM88suvJFwzVrRfHEHJEl5/71CKw0= +golang.org/x/net v0.34.0/go.mod h1:di0qlW3YNM5oh6GqDGQr92MyTozJPmybPK4Ev/Gm31k= +golang.org/x/oauth2 v0.25.0 h1:CY4y7XT9v0cRI9oupztF8AgiIu99L/ksR/Xp/6jrZ70= +golang.org/x/oauth2 v0.25.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.8.0 h1:3NFvSEYkUoMifnESzZl15y791HH1qU2xm6eCJU5ZPXQ= -golang.org/x/sync v0.8.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= +golang.org/x/sync v0.10.0 h1:3NQrjDixjgGwUOCaF8w2+VYHv0Ve/vGYSbdkTa98gmQ= +golang.org/x/sync v0.10.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -149,15 +146,15 @@ golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.3.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.26.0 h1:KHjCJyddX0LoSTb3J+vWpupP9p0oznkqVk/IfjymZbo= -golang.org/x/sys v0.26.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.29.0 h1:TPYlXGxvx1MGTn2GiZDhnjPA9wZzZeGKHHmKhHYvgaU= +golang.org/x/sys v0.29.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.2.0/go.mod h1:TVmDHMZPmdnySmBfhjOoOdhjzdE1h4u1VwSiw2l1Nuc= golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= golang.org/x/term v0.6.0/go.mod h1:m6U89DPEgQRMq3DNkDClhWw02AUbt2daBVO4cn4Hv9U= -golang.org/x/term v0.23.0 h1:F6D4vR+EHoL9/sWAWgAR1H2DcHr4PareCbAaCo1RpuU= -golang.org/x/term v0.23.0/go.mod h1:DgV24QBUrK6jhZXl+20l6UWznPlwAHm1Q1mGHtydmSk= +golang.org/x/term v0.28.0 h1:/Ts8HFuMR2E6IP/jlo7QVLZHggjKQbhu/7H0LJFr3Gg= +golang.org/x/term v0.28.0/go.mod h1:Sw/lC2IAUZ92udQNf3WodGtn4k/XoLyZoh8v/8uiwek= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= @@ -165,16 +162,15 @@ golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.8.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= -golang.org/x/text v0.17.0 h1:XtiM5bkSOt+ewxlOE/aE/AKEHibwj/6gvWMl9Rsh0Qc= -golang.org/x/text v0.17.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY= +golang.org/x/text v0.21.0 h1:zyQAAkrwaneQ066sspRyJaG9VNi/YJ1NfzcGB3hZ/qo= +golang.org/x/text v0.21.0/go.mod h1:4IBbMaMmOPCJ8SecivzSH54+73PCFmPWxNTLm+vZkEQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= -golang.org/x/tools v0.24.0 h1:J1shsA93PJUEVaUSaay7UXAyE8aimq3GW0pjlolpa24= -golang.org/x/tools v0.24.0/go.mod h1:YhNqVBIfWHdzvTLs0d8LCuMhkKUgSUKldakyV7W/WDQ= +golang.org/x/tools v0.29.0 h1:Xx0h3TtM9rzQpQuR4dKLrdglAmCEN5Oi+P74JdhdzXE= +golang.org/x/tools v0.29.0/go.mod h1:KMQVMRsVxU6nHCFXrBPhDB8XncLNLM0lIy/F14RP588= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=