From 1eada18b10d73acbb77a34e4280621a19d50df87 Mon Sep 17 00:00:00 2001 From: Ringo De Smet Date: Mon, 9 Sep 2024 14:04:14 +0200 Subject: [PATCH] Release workflow based on pulumi/ci-mgmt --- .github/actions/setup-tools/action.yml | 4 +- .github/workflows/publish.yml | 168 +++++++++++++++++++ .github/workflows/release.yml | 221 +++++++++++-------------- 3 files changed, 269 insertions(+), 124 deletions(-) create mode 100644 .github/workflows/publish.yml diff --git a/.github/actions/setup-tools/action.yml b/.github/actions/setup-tools/action.yml index ec2ddde..642d1d2 100644 --- a/.github/actions/setup-tools/action.yml +++ b/.github/actions/setup-tools/action.yml @@ -9,7 +9,7 @@ inputs: pulumicli pulumictl schema-tools - node + nodejs python dotnet java @@ -48,7 +48,7 @@ runs: repo: pulumi/schema-tools - name: Setup Node - if: inputs.tools == 'all' || contains(inputs.tools, 'node') + if: inputs.tools == 'all' || contains(inputs.tools, 'nodejs') uses: actions/setup-node@v4 with: node-version: 20.x diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml new file mode 100644 index 0000000..e7cd6c0 --- /dev/null +++ b/.github/workflows/publish.yml @@ -0,0 +1,168 @@ +# WARNING: This file is autogenerated - changes will be overwritten if not made via https://github.com/pulumi/ci-mgmt +name: Publish + +on: + workflow_call: + inputs: + version: + required: true + type: string + isPrerelease: + required: true + type: boolean + skipGoSdk: + default: false + type: boolean + description: Skip publishing & verifying the Go SDK + +env: + IS_PRERELEASE: ${{ inputs.isPrerelease }} + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} + NPM_TOKEN: ${{ secrets.NPM_TOKEN }} + NUGET_PUBLISH_KEY: ${{ secrets.NUGET_PUBLISH_KEY }} + PUBLISH_REPO_PASSWORD: ${{ secrets.OSSRH_PASSWORD }} + PUBLISH_REPO_USERNAME: ${{ secrets.OSSRH_USERNAME }} + PULUMI_ACCESS_TOKEN: ${{ secrets.PULUMI_ACCESS_TOKEN }} + PULUMI_API: https://api.pulumi-staging.io + PULUMI_GO_DEP_ROOT: ${{ github.workspace }}/.. + PULUMI_LOCAL_NUGET: ${{ github.workspace }}/nuget + PYPI_PASSWORD: ${{ secrets.PYPI_API_TOKEN }} + PYPI_USERNAME: __token__ + SIGNING_KEY: ${{ secrets.JAVA_SIGNING_KEY }} + SIGNING_KEY_ID: ${{ secrets.JAVA_SIGNING_KEY_ID }} + SIGNING_PASSWORD: ${{ secrets.JAVA_SIGNING_PASSWORD }} + TF_APPEND_USER_AGENT: pulumi + +jobs: + publish: + name: publish + runs-on: ubuntu-latest + steps: + - name: Validate prerelease + if: inputs.isPrerelease == false && (contains(inputs.version, '-') || contains(inputs.version, '+')) + run: echo "Can't publish a prerelease version as a stable release. This is likely a bug in the calling workflow." && exit 1 + - name: Validate skipGoSdk + if: inputs.skipGoSdk && inputs.isPrerelease == false + run: echo "Can't skip Go SDK for stable releases. This is likely a bug in the calling workflow." && exit 1 + - name: Checkout Repo + uses: actions/checkout@v4 + - name: Setup tools + uses: ./.github/actions/setup-tools + with: + tools: pulumictl, pulumicli, go, schema-tools + - name: Configure AWS Credentials + uses: aws-actions/configure-aws-credentials@v4 + with: + aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }} + aws-region: us-east-2 + aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }} + role-duration-seconds: 7200 + role-external-id: upload-pulumi-release + role-session-name: acme@githubActions + role-to-assume: ${{ secrets.AWS_UPLOAD_ROLE_ARN }} + - name: Create dist directory + run: mkdir -p dist + - name: Download provider assets + uses: actions/download-artifact@v4 + with: + pattern: pulumi-resource-acme-v${{ inputs.version }}-* + path: dist + # Don't create a directory for each artifact + merge-multiple: true + - name: Calculate checksums + working-directory: dist + run: shasum ./*.tar.gz > pulumi-acme_${{ inputs.version }}_checksums.txt + - name: Get Schema Change Summary + id: schema-summary + shell: bash + run: | + # Get latest stable release. Return only first column from result (tag). + LAST_VERSION=$(gh release view --repo pulumiverse/pulumi-acme --json tagName -q .tagName || echo "No stable release" ) + { + echo 'summary<> "$GITHUB_OUTPUT" + - name: Upload Provider Binaries + run: aws s3 cp dist s3://get.pulumi.com/releases/plugins/ --recursive + - name: Create GH Release + uses: softprops/action-gh-release@v1 + if: inputs.isPrerelease == false + with: + tag_name: v${{ inputs.version }} + prerelease: ${{ inputs.isPrerelease }} + # We keep pre-releases as drafts so they're not visible until we manually publish them. + draft: ${{ inputs.isPrerelease }} + body: ${{ steps.schema-summary.outputs.summary }} + generate_release_notes: true + files: dist/* + env: + GITHUB_TOKEN: ${{ secrets.PULUMI_BOT_TOKEN }} + + publish_sdk: + name: publish_sdk + needs: publish + runs-on: ubuntu-latest + steps: + - name: Checkout Repo + uses: actions/checkout@v4 + - name: Setup tools + uses: ./.github/actions/setup-tools + with: + tools: pulumictl, pulumicli, go, node, dotnet, python, java + - name: Publish SDKs + uses: pulumi/pulumi-package-publisher@v0.0.20 + with: + sdk: all,!java + version: ${{ inputs.version }} + - name: Download Go SDK + uses: ./.github/actions/download-sdk + with: + language: go + - uses: pulumi/publish-go-sdk-action@v1 + if: inputs.skipGoSdk == false + with: + repository: ${{ github.repository }} + base-ref: ${{ github.sha }} + source: sdk + path: sdk + version: ${{ inputs.version }} + additive: false + # Avoid including other language SDKs & artifacts in the commit + files: | + go.* + go/** + !*.tar.gz + + clean_up_release_labels: + name: Clean up release labels + # Only run for non-prerelease, if the publish_go_sdk job was successful or skipped + if: inputs.isPrerelease == false + + needs: publish_sdk + runs-on: ubuntu-latest + steps: + - name: Checkout Repo + uses: actions/checkout@v4 + - name: Clean up release labels + uses: pulumi/action-release-by-pr-label@main + with: + command: "clean-up-release-labels" + repo: ${{ github.repository }} + commit: ${{ github.sha }} + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + + verify_release: + name: verify_release + needs: publish_sdk + uses: ./.github/workflows/verify-release.yml + secrets: inherit + with: + providerVersion: ${{ inputs.version }} + # Prelease is run often but we only have 5 concurrent macos runners, so we only test after the stable release. + enableMacosRunner: ${{ inputs.isPrerelease == false }} + skipGoSdk: ${{ inputs.skipGoSdk }} diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 6252c52..5da29ea 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -1,142 +1,119 @@ +# WARNING: This file is autogenerated - changes will be overwritten if not made via https://github.com/pulumi/ci-mgmt name: release on: push: tags: - - v*.*.* - -permissions: - contents: write - id-token: write + - v*.*.* + - "!v*.*.*-**" env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} NPM_TOKEN: ${{ secrets.NPM_TOKEN }} NUGET_PUBLISH_KEY: ${{ secrets.NUGET_PUBLISH_KEY }} - NUGET_FEED_URL: https://api.nuget.org/v3/index.json - PROVIDER: acme + PUBLISH_REPO_PASSWORD: ${{ secrets.OSSRH_PASSWORD }} + PUBLISH_REPO_USERNAME: ${{ secrets.OSSRH_USERNAME }} + PULUMI_ACCESS_TOKEN: ${{ secrets.PULUMI_ACCESS_TOKEN }} + PULUMI_API: https://api.pulumi-staging.io PULUMI_GO_DEP_ROOT: ${{ github.workspace }}/.. PULUMI_LOCAL_NUGET: ${{ github.workspace }}/nuget - PYPI_PASSWORD: ${{ secrets.PYPI_PASSWORD }} - PYPI_USERNAME: "__token__" - PUBLISH_PYPI: true - PUBLISH_NPM: true - PUBLISH_NUGET: true - DOTNETVERSION: | - 6.0.x - 3.1.301 - GOVERSION: 1.22.x - GRADLEVERSION: "7.6" - JAVAVERSION: "11" - NODEVERSION: 20.x - PYTHONVERSION: 3.11.8 - + PYPI_PASSWORD: ${{ secrets.PYPI_API_TOKEN }} + PYPI_USERNAME: __token__ + SIGNING_KEY: ${{ secrets.JAVA_SIGNING_KEY }} + SIGNING_KEY_ID: ${{ secrets.JAVA_SIGNING_KEY_ID }} + SIGNING_PASSWORD: ${{ secrets.JAVA_SIGNING_PASSWORD }} + TF_APPEND_USER_AGENT: pulumi jobs: - publish_binary: + prerequisites: + uses: ./.github/workflows/prerequisites.yml + secrets: inherit + with: + default_branch: ${{ github.event.repository.default_branch }} + is_pr: ${{ github.event_name == 'pull_request' }} + is_automated: ${{ github.actor == 'dependabot[bot]' }} + + build_provider: + uses: ./.github/workflows/build_provider.yml + needs: prerequisites + secrets: inherit + with: + version: ${{ needs.prerequisites.outputs.version }} + + build_sdk: + name: build_sdk + needs: prerequisites + uses: ./.github/workflows/build_sdk.yml + secrets: inherit + with: + version: ${{ needs.prerequisites.outputs.version }} + + lint: + name: lint + uses: ./.github/workflows/lint.yml + secrets: inherit + license_check: + name: License Check + uses: ./.github/workflows/license.yml + secrets: inherit + + publish: name: publish - runs-on: ubuntu-latest - steps: - - name: Checkout Repo - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 - - name: Unshallow clone for tags - run: git fetch --prune --unshallow --tags - - name: Install Go - uses: actions/setup-go@0a12ed9d6a96ab950c8f026ed9f722fe0da7ef32 # v5.0.2 - with: - go-version: ${{ env.GOVERSION }} - - name: Install pulumictl - uses: jaxxstorm/action-install-gh-release@25d5e2dd555cd74f1fab9ac1e6ea117acde2c0c4 # v1.12.0 - with: - repo: pulumi/pulumictl - - name: Set PreRelease Version - run: echo "GORELEASER_CURRENT_TAG=v$(pulumictl get version --language generic)" >> $GITHUB_ENV - - uses: sigstore/cosign-installer@59acb6260d9c0ba8f4a2f9d9b48431a222b68e20 # v3.5.0 - - uses: anchore/sbom-action/download-syft@e8d2a6937ecead383dfe75190d104edd1f9c5751 # v0.16.0 - - name: Run GoReleaser - uses: goreleaser/goreleaser-action@286f3b13b1b49da4ac219696163fb8c1c93e1200 # v6.0.0 - with: - args: -p 3 release --clean - version: latest - - name: Create tag - uses: actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea # v7.0.1 - with: - script: | - github.rest.git.createRef({ - owner: context.repo.owner, - repo: context.repo.repo, - ref: 'refs/tags/sdk/${{ github.ref_name }}', - sha: context.sha - }) - strategy: - fail-fast: true + needs: + - prerequisites + - build_provider + - test + - license_check + uses: ./.github/workflows/publish.yml + secrets: inherit + with: + version: ${{ needs.prerequisites.outputs.version }} + isPrerelease: false - publish_sdk: - name: Publish SDKs + test: + name: test + needs: + - prerequisites + - build_sdk + permissions: + contents: read + id-token: write runs-on: ubuntu-latest - needs: publish_binary + env: + PROVIDER_VERSION: ${{ needs.prerequisites.outputs.version }} steps: - - name: Checkout Repo - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 - - name: Unshallow clone for tags - run: git fetch --prune --unshallow --tags - - name: Install Go - uses: actions/setup-go@0a12ed9d6a96ab950c8f026ed9f722fe0da7ef32 # v5.0.2 - with: - go-version: ${{ env.GOVERSION }} - - name: Install pulumictl - uses: jaxxstorm/action-install-gh-release@25d5e2dd555cd74f1fab9ac1e6ea117acde2c0c4 # v1.12.0 - with: - repo: pulumi/pulumictl - - name: Install Pulumi CLI - uses: pulumi/action-install-pulumi-cli@b374ceb6168550de27c6eba92e01c1a774040e11 # v2.0.0 - - name: Setup Node - uses: actions/setup-node@60edb5dd545a775178f52524783378180af0d1f8 # v4.0.2 - with: - node-version: ${{ env.NODEVERSION }} - registry-url: ${{env.NPM_REGISTRY_URL}} - - name: Setup DotNet - uses: actions/setup-dotnet@6bd8b7f7774af54e05809fcc5431931b3eb1ddee # v4.0.1 - with: - dotnet-version: ${{ env.DOTNETVERSION }} - - name: Setup Python - uses: actions/setup-python@39cd14951b08e74b54015e9e001cdefcf80e669f # v5.1.1 - with: - python-version: ${{ env.PYTHONVERSION }} - - name: Build SDK - run: make build_${{ matrix.language }} - - name: Check worktree clean - run: | - git update-index -q --refresh - if ! git diff-files --quiet; then - >&2 echo "error: working tree is not clean, aborting!" - git status - git diff - exit 1 - fi - - if: ${{ matrix.language == 'python' && env.PUBLISH_PYPI == 'true' }} - name: Publish package to PyPI - uses: pypa/gh-action-pypi-publish@ec4db0b4ddc65acdf4bff5fa45ac92d78b56bdf0 # v1.9.0 - with: - user: ${{ env.PYPI_USERNAME }} - password: ${{ env.PYPI_PASSWORD }} - packages_dir: ${{github.workspace}}/sdk/python/bin/dist - - if: ${{ matrix.language == 'nodejs' && env.PUBLISH_NPM == 'true' }} - uses: JS-DevTools/npm-publish@19c28f1ef146469e409470805ea4279d47c3d35c # v3.1.1 - with: - access: "public" - token: ${{ env.NPM_TOKEN }} - package: ${{github.workspace}}/sdk/nodejs/bin/package.json - provenance: true - - if: ${{ matrix.language == 'dotnet' && env.PUBLISH_NUGET == 'true' }} - name: publish nuget package - run: | - dotnet nuget push ${{github.workspace}}/sdk/dotnet/bin/Debug/*.nupkg -s ${{ env.NUGET_FEED_URL }} -k ${{ env.NUGET_PUBLISH_KEY }} - echo "done publishing packages" + - name: Checkout Repo + uses: actions/checkout@v4 + - name: Setup tools + uses: ./.github/actions/setup-tools + with: + tools: pulumictl, pulumicli, ${{ matrix.language }} + - name: Download bin + uses: ./.github/actions/download-bin + - run: dotnet nuget add source ${{ github.workspace }}/nuget + - name: Download SDK + uses: ./.github/actions/download-sdk + with: + language: ${{ matrix.language }} + - name: Update path + run: echo "${{ github.workspace }}/bin" >> "$GITHUB_PATH" + - name: Install Python deps + run: |- + pip3 install virtualenv==20.0.23 + pip3 install pipenv + - name: Install dependencies + run: make install_${{ matrix.language}}_sdk + - name: Install gotestfmt + uses: GoTestTools/gotestfmt-action@v2 + with: + token: ${{ secrets.GITHUB_TOKEN }} + version: v2.5.0 + - name: Run tests + run: cd examples && go test -v -json -count=1 -cover -timeout 2h -tags=${{ matrix.language }} -parallel 4 . 2>&1 | tee /tmp/gotest.log | gotestfmt strategy: - fail-fast: true + fail-fast: false matrix: language: - - nodejs - - python - - dotnet - - go + - dotnet + - go + - nodejs + - python