diff --git a/.github/actions/audit-changelog/action.yml b/.github/actions/audit-changelog/action.yml index cc878fae..fb878fcf 100644 --- a/.github/actions/audit-changelog/action.yml +++ b/.github/actions/audit-changelog/action.yml @@ -1,5 +1,5 @@ name: "Audit changelog" -description: "Get metadata about a changelog, including the expected file path, and if it exists" +description: "Get metadata about a changelog" inputs: version: @@ -17,6 +17,11 @@ outputs: runs: using: composite steps: + - name: "[DEBUG] Inputs" + shell: bash + run: | + echo version : ${{ inputs.version }} + - name: "Parse version: `${{ inputs.version }}`" id: semver uses: dbt-labs/actions/parse-semver@v1.1.0 diff --git a/.github/actions/audit-github-commit/action.yml b/.github/actions/audit-github-commit/action.yml index 5d623884..852293b8 100644 --- a/.github/actions/audit-github-commit/action.yml +++ b/.github/actions/audit-github-commit/action.yml @@ -23,6 +23,11 @@ outputs: runs: using: composite steps: + - name: "[DEBUG] Inputs" + shell: bash + run: | + echo sha : ${{ inputs.sha }} + - name: "Check if a release exists for `${{ inputs.sha }}`" id: commit env: @@ -37,7 +42,7 @@ runs: shell: bash run: | echo sha : ${{ inputs.sha }} - echo tag : ${{ steps.check_release_commit.outputs.tag_name }} - echo release-id : ${{ steps.check_release_commit.outputs.id }} - echo pre-release : ${{ steps.check_release_commit.outputs.prerelease }} - echo commitish : ${{ steps.check_release_commit.outputs.target_commitish }} + echo tag : ${{ steps.commit.outputs.tag_name }} + echo release-id : ${{ steps.commit.outputs.id }} + echo pre-release : ${{ steps.commit.outputs.prerelease }} + echo commitish : ${{ steps.commit.outputs.target_commitish }} diff --git a/.github/actions/audit-github-tag/action.yml b/.github/actions/audit-github-tag/action.yml index 1118a505..77a8f608 100644 --- a/.github/actions/audit-github-tag/action.yml +++ b/.github/actions/audit-github-tag/action.yml @@ -23,7 +23,13 @@ outputs: runs: using: composite steps: - - name: "Check if `${{ inputs.tag }}` exists in `${{ inputs.repo-url }}`" + - name: "[DEBUG] Inputs" + shell: bash + run: | + echo tag : ${{ inputs.tag }} + echo repo-url : ${{ inputs.repo-url }} + + - name: "Set: exists" id: tag shell: bash run: | @@ -38,15 +44,15 @@ runs: with: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - - name: "Get the commit associated with `${{ inputs.tag }}`" + - name: "Set: sha" id: commit if: ${{ fromJSON(steps.tag.outputs.exists) == true }} shell: bash run: | - sha=$(jq -r '.targetCommitish' <<< "$output") + sha=$(jq -r '.targetCommitish' <<< "${{ steps.tag.outputs.results }}") echo "sha=$sha" >> $GITHUB_OUTPUT - - name: "Check if `${{ inputs.tag }}` is a draft release" + - name: "Set: is-draft" id: draft if: ${{ fromJSON(steps.tag.outputs.exists) == true }} shell: bash diff --git a/.github/actions/audit-github-team/action.yml b/.github/actions/audit-github-team/action.yml index 6923cb8c..fdaca6ba 100644 --- a/.github/actions/audit-github-team/action.yml +++ b/.github/actions/audit-github-team/action.yml @@ -1,10 +1,10 @@ name: "Audit GitHub team" -description: "Get metadata about a GitHub team, such as a list of team members" +description: "Get metadata about a GitHub team" inputs: organization: description: "The GitHub organization that owns the team" - required: true + default: "dbt-labs" team: description: "The name of the team" required: true @@ -17,11 +17,19 @@ outputs: runs: using: composite steps: - - name: "Set: output file name" + - name: "[DEBUG] Inputs" + shell: bash + run: | + echo organization : ${{ inputs.organization }} + echo team : ${{ inputs.team }} + + - name: "Create output file name" id: output-file + shell: bash run: echo "name=output_$GITHUB_RUN_ID.json" >> $GITHUB_OUTPUT - - name: "Get team membership for `${{ inputs.organization }}/${{ inputs.team }}`" + - name: "Get team membership" + shell: bash run: | url = orgs/${{ inputs.organization }}/teams/${{ inputs.team }}/members header = Accept: application/vnd.github+json @@ -29,18 +37,19 @@ runs: - name: "Parse team membership" id: members - shell: + shell: bash run: | team_list=$(jq -r '.[].login' ${{ steps.output-file.outputs.name }}) team_list_single=$(echo $team_list | tr '\n' ' ') echo "membership=$team_list_single" >> $GITHUB_OUTPUT + - name: "Delete the output file" + shell: bash + run: rm ${{ steps.output-file.outputs.name }} + - name: "[DEBUG] Parse team membership" shell: bash run: | echo organization : ${{ inputs.organization }} echo team : ${{ inputs.team }} echo members : ${{ steps.members.outputs.membership }} - - - name: "Delete the output file" - run: rm ${{ steps.output-file.outputs.name }} diff --git a/.github/actions/create-temp-branch/action.yml b/.github/actions/create-temp-branch/action.yml index cce80b4c..6fe53ceb 100644 --- a/.github/actions/create-temp-branch/action.yml +++ b/.github/actions/create-temp-branch/action.yml @@ -14,8 +14,14 @@ outputs: runs: using: composite steps: + - name: "[DEBUG] Inputs" + shell: bash + run: | + echo branch-stub : ${{ inputs.branch-stub }} + - name: "Create a unique branch name" id: branch + shell: bash run: | name="${{ inputs.branch-stub }}" name+="$(date +'%Y-%m-%d')/$GITHUB_RUN_ID" diff --git a/.github/actions/commit/action.yml b/.github/actions/github-commit/action.yml similarity index 53% rename from .github/actions/commit/action.yml rename to .github/actions/github-commit/action.yml index 8da59ece..0ecab9fb 100644 --- a/.github/actions/commit/action.yml +++ b/.github/actions/github-commit/action.yml @@ -12,17 +12,16 @@ inputs: description: "The email for the commit" default: "buildbot@fishtownanalytics.com" -outputs: - path: - description: "The file path to the change log, relative to the repo root" - value: ${{ steps.path.outputs.path }} - exists: - description: "Does the changelog exist?" - value: ${{ steps.exists.outputs.exists }} - runs: using: composite steps: + - name: "[DEBUG] Inputs" + shell: bash + run: | + echo message : ${{ inputs.message }} + echo user : ${{ inputs.user }} + echo email : ${{ inputs.email }} + - name: "Commit and push changes" shell: bash run: | @@ -30,5 +29,12 @@ runs: git config user.email "${{ inputs.email }}" git pull git add . - git commit -m "${{ inputs.message }}" + git commit -m "[automated] ${{ inputs.message }}" git push + + - name: "[INFO] Committed and pushed changes" + shell: bash + run: | + title="Committed and pushed changes" + message="Committed and pushed changes back up to remote" + echo "::notice title=${{ env.NOTIFICATION_PREFIX }}: $title::$message" diff --git a/.github/actions/github-merge/action.yml b/.github/actions/github-merge/action.yml new file mode 100644 index 00000000..efe7464c --- /dev/null +++ b/.github/actions/github-merge/action.yml @@ -0,0 +1,59 @@ +name: "Merge GitHub branch" +description: "Merge one branch into another on GitHub" + +inputs: + source-branch: + description: "The source branch to be merged" + required: true + target-branch: + description: "The target branch to receive the merge" + required: true + message: + description: "Commit message for the merge" + required: true + delete-source-branch: + description: "Will delete the source branch after merging" + default: "true" + +outputs: + sha: + description: "The commit SHA for the merge" + value: ${{ steps.merge-sha.outputs.sha }} + +runs: + using: composite + steps: + # TODO: are we comfortable passing our bot token to this third party action? + - name: "Merge `${{ inputs.source-branch }}` into `${{ inputs.target-branch }}`" + uses: everlytic/branch-merge@1.1.5 + with: + source_ref: ${{ inputs.source-branch }} + target_branch: ${{ inputs.target-branch }} + commit_message_template: "[automated] ${{ inputs.message }}" + github_token: ${{ secrets.FISHTOWN_BOT_PAT }} + + - name: "Checkout `${{ inputs.branch }}`" + uses: actions/checkout@v3 + with: + ref: ${{ inputs.target-branch }} + + # TODO: see if everlytic/branch-merge has outputs that have this information + - name: "Get commit SHA for the merge" + id: merge-sha + shell: bash + run: | + git pull + echo "sha=$(git rev-parse HEAD)" >> $GITHUB_OUTPUT + + # TODO: see if everlytic/branch-merge has options to do this + - name: "Delete `${{ inputs.source-branch }}`" + if: ${{ fromJSON(inputs.delete-source-branch) }} + shell: bash + run: git push origin -d ${{ inputs.source-branch }} + + - name: "[INFO] Merged changes" + shell: bash + run: | + title="Merged changes" + message="${{ inputs.source-branch }} was merged into ${{ inputs.target-branch }} with sha ${{ steps.merge-sha.outputs.sha }}" + echo "::notice title=${{ env.NOTIFICATION_PREFIX }}: $title::$message" diff --git a/.github/actions/log-info/action.yml b/.github/actions/log-info/action.yml new file mode 100644 index 00000000..f6ea0cdc --- /dev/null +++ b/.github/actions/log-info/action.yml @@ -0,0 +1,22 @@ +name: "Raise a notification" +description: "Raises a notification to the workflow summary in a standardized pattern" + +inputs: + title: + description: "The notification title" + required: true + message: + description: "The detailed message" + required: true + prefix: + description: "The parent process raising the notification" + default: "INFO" + +runs: + using: composite + steps: + - shell: bash + run: 'echo "::notice title=$TITLE::$MESSAGE"' + env: + TITLE: "[${{ inputs.prefix }}]: ${{ inputs.title }}" + MESSAGE: ${{ inputs.message }} diff --git a/.github/actions/publish-github-draft/action.yml b/.github/actions/publish-github-draft/action.yml index 11d8dc23..8506d94b 100644 --- a/.github/actions/publish-github-draft/action.yml +++ b/.github/actions/publish-github-draft/action.yml @@ -1,71 +1,32 @@ -name: "Publish to GitHub as draft release" -description: "Publish artifacts from an archive to GitHub as a draft release" +name: "Publish GitHub draft release as full release" +description: "Publish an existing draft release as a non-draft release" inputs: - archive-name: - description: "Name of the archive containing the artifacts, leave blank if local" - default: "" tag: - description: "The release tag to publish under" + description: "The tag to publish (i.e. v1.0.0b1)" required: true repo-url: description: "The URL to the repo (https://github.com/dbt-labs/dbt-adapters" required: true - sha: - description: "Commit SHA being released" - required: true - changelog-path: - description: "Path to the release notes" - required: true runs: using: composite steps: - - name: "Download artifacts from `${{ inputs.archive-name }}`" - if: ${{ !(inputs.archive-name == "" }} - uses: actions/download-artifact@v4 - with: - name: ${{ inputs.archive-name }} - path: dist/ - - - name: "[INFO] Downloaded artifacts" - if: ${{ !(inputs.archive-name == "" }} - shell: bash - run: | - title="Downloaded artifacts" - message="Downloaded artifacts from ${{ inputs.archive-name }}" - echo "::notice title=${{ env.NOTIFICATION_PREFIX }}: $title::$message" - - - name: "[DEBUG] Found artifacts" - shell: bash - working-directory: ${{ inputs.working-dir }} - run: echo $(ls ./dist) - - - name: "Set: pre-release" - id: pre-release + - name: "[DEBUG] Inputs" shell: bash run: | - if ${{ contains(inputs.tag, 'rc') || contains(inputs.tag, 'b') || contains(inputs.tag, 'a') }} - then - echo "pre-release=--prerelease" >> $GITHUB_OUTPUT - fi + echo tag : ${{ inputs.tag }} + echo repo-url : ${{ inputs.repo-url }} - - name: "Publish artifacts to GitHub as draft release" + - name: "Publish `${{ inputs.tag }}` as full release" shell: bash - run: | - gh release create $TAG ./dist/* --title "$TITLE" --notes-file $RELEASE_NOTES --target $COMMIT $PRERELEASE --draft --repo ${{ inputs.repo-url }} + run: gh release edit ${{ inputs.tag }} --repo ${{ inputs.repo-url }} --draft=false env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - TAG: ${{ inputs.tag }} - TITLE: ${{ github.event.repository.name }} ${{ inputs.tag }} - RELEASE_NOTES: ${{ inputs.changelog-path }} - COMMIT: ${{ inputs.sha }} - PRERELEASE: ${{ steps.pre-release.outputs.pre-release }} - DRAFT: ${{ inputs.draft-flag }} - - name: "[INFO] Published artifacts to GitHub as draft release" + - name: "[INFO] Published draft as full release" shell: bash run: | - title="Published artifacts to GitHub as draft release" - message="artifacts: $(ls ./dist) tag: ${{ inputs.tag }} pre-release: ${{ steps.prerelease.outputs.prerelease }}" + title="Released draft as non-draft release on GitHub" + message="tag: ${{ inputs.tag }} repo: ${{ inputs.repo-url }}" echo "::notice title=${{ env.NOTIFICATION_PREFIX }}: $title::$message" diff --git a/.github/actions/publish-github-full/action.yml b/.github/actions/publish-github-full/action.yml deleted file mode 100644 index 8258c764..00000000 --- a/.github/actions/publish-github-full/action.yml +++ /dev/null @@ -1,26 +0,0 @@ -name: "Publish GitHub draft release as full release" -description: "Publish an existing draft release as a non-draft release" - -inputs: - tag: - description: "The tag to publish (i.e. v1.0.0b1)" - required: true - repo-url: - description: "The URL to the repo (https://github.com/dbt-labs/dbt-adapters" - required: true - -runs: - using: composite - steps: - - name: "Publish `${{ inputs.tag }}` as full release" - shell: bash - run: gh release edit ${{ inputs.tag }} --draft=false --repo ${{ inputs.repo-url }} - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - - - name: "[INFO] Published draft as full release" - shell: bash - run: | - title="Released draft as non-draft release on GitHub" - message="tag: ${{ inputs.tag }} repo: ${{ inputs.repo-url }}" - echo "::notice title=${{ env.NOTIFICATION_PREFIX }}: $title::$message" diff --git a/.github/actions/publish-github/action.yml b/.github/actions/publish-github/action.yml new file mode 100644 index 00000000..6042357c --- /dev/null +++ b/.github/actions/publish-github/action.yml @@ -0,0 +1,91 @@ +name: "Publish to GitHub as draft release" +description: "Publish artifacts from an archive to GitHub as a draft release" + +inputs: + archive-name: + description: "Name of the archive containing the artifacts, leave blank if local" + default: "" + tag: + description: "The release tag to publish under" + required: true + repo-url: + description: "The URL to the repo (e.g. https://github.com/dbt-labs/dbt-adapters)" + required: true + sha: + description: "Commit SHA being released" + required: true + changelog-path: + description: "Path to the release notes" + required: true + is-draft: + description: "Indicates that this is a draft release" + required: true + +runs: + using: composite + steps: + - name: "Set: pre-release" + id: pre-release + shell: bash + run: | + if ${{ contains(inputs.tag, 'rc') || contains(inputs.tag, 'b') || contains(inputs.tag, 'a' || contains(inputs.tag, 'dev') }} + then + echo "pre-release=--prerelease" >> $GITHUB_OUTPUT + fi + + - name: "Set: draft" + id: draft + shell: bash + run: | + if ${{ fromJSON(inputs.is-draft) }} + then + echo "draft=--draft" >> $GITHUB_OUTPUT + fi + + - name: "[DEBUG] Inputs" + shell: bash + run: | + echo archive-name : ${{ inputs.archive-name }} + echo tag : ${{ inputs.tag }} + echo repo-url : ${{ inputs.repo-url }} + echo sha : ${{ inputs.sha }} + echo changelog-path : ${{ inputs.changelog-path }} + echo is-draft : ${{ inputs.is-draft }} + echo pre-release : ${{ steps.pre-release.outputs.pre-release }} + echo draft : ${{ steps.draft.outputs.draft }} + + - name: "Download artifacts from `${{ inputs.archive-name }}`" + if: ${{ !(inputs.archive-name == "" }} + uses: actions/download-artifact@v4 + with: + name: ${{ inputs.archive-name }} + path: dist/ + + - name: "[INFO] Downloaded artifacts" + if: ${{ !(inputs.archive-name == "" }} + uses: ./.github/actions/log-info + with: + title: "Downloaded artifacts" + message: "${{ inputs.archive-name }} contained: $(ls ./dist)" + prefix: ${{ env.NOTIFICATION_PREFIX }} + + - name: "Publish artifacts to GitHub as draft release" + shell: bash + run: gh release create $TAG $ARTIFACTS --repo $REPO --title "$TITLE" --notes-file $RELEASE_NOTES --target $COMMIT $PRERELEASE $DRAFT + env: + TAG: ${{ inputs.tag }} + ARTIFACTS: "./dist/*" + REPO: ${{ inputs.repo-url }} + TITLE: ${{ github.event.repository.name }} ${{ inputs.tag }} + RELEASE_NOTES: ${{ inputs.changelog-path }} + COMMIT: ${{ inputs.sha }} + PRERELEASE: ${{ steps.pre-release.outputs.pre-release }} + DRAFT: ${{ steps.draft.outputs.draft }} + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + + - name: "[INFO] Published artifacts to GitHub as draft release" + uses: ./.github/actions/log-info + with: + title: "Published artifacts to GitHub as draft release" + message: "tag: ${{ inputs.tag }} pre-release: ${{ steps.pre-release.outputs.pre-release }} artifacts: $(ls ./dist)" + prefix: ${{ env.NOTIFICATION_PREFIX }} diff --git a/.github/actions/publish-pypi/action.yml b/.github/actions/publish-pypi/action.yml index ad92107b..472b42ca 100644 --- a/.github/actions/publish-pypi/action.yml +++ b/.github/actions/publish-pypi/action.yml @@ -5,7 +5,7 @@ inputs: archive-name: description: "Name of the archive containing the artifacts, leave blank if local" default: "" - repository-url: + index-url: description: "The url for the PyPI index" required: true working-dir: @@ -15,6 +15,13 @@ inputs: runs: using: composite steps: + - name: "[DEBUG] Inputs" + shell: bash + run: | + echo archive-name : ${{ inputs.archive-name }} + echo index-url : ${{ inputs.index-url }} + echo working-dir : ${{ inputs.working-dir }} + - name: "Download artifacts from `${{ inputs.archive-name }}`" if: ${{ !(inputs.archive-name == "" }} uses: actions/download-artifact@v4 @@ -38,7 +45,7 @@ runs: - name: "Publish artifacts to PyPI" uses: pypa/gh-action-pypi-publish@release/v1 with: - repository-url: ${{ inputs.repository-url }} + repository-url: ${{ inputs.index-url }} packages-dir: ${{ inputs.working-dir }}dist/ - name: "[INFO] Published artifacts to PyPI" diff --git a/.github/actions/setup-changie/action.yml b/.github/actions/setup-changie/action.yml index 3a82dd25..55e994e1 100644 --- a/.github/actions/setup-changie/action.yml +++ b/.github/actions/setup-changie/action.yml @@ -8,9 +8,8 @@ runs: shell: bash run: echo "/home/linuxbrew/.linuxbrew/bin:/home/linuxbrew/.linuxbrew/sbin" >> $GITHUB_PATH - - name: "Install `linuxbrew` packages" + - name: "Install `changie`" shell: bash run: | - brew install pre-commit brew tap miniscruff/changie https://github.com/miniscruff/changie brew install changie diff --git a/.github/actions/setup-environment/action.yml b/.github/actions/setup-environment/action.yml new file mode 100644 index 00000000..80433cd3 --- /dev/null +++ b/.github/actions/setup-environment/action.yml @@ -0,0 +1,28 @@ +name: "Setup environment" +description: "Setup a python environment with `hatch` as the default build frontend" + +inputs: + python-version: + description: "The version of python to install" + default: "3.8" + setup-build-command: + description: "The command to setup build dependencies" + default: "python -m pip install hatch" + +runs: + using: composite + steps: + - name: "[DEBUG] Inputs" + shell: bash + run: | + echo python-version : ${{ inputs.python-version }} + echo setup-build-command : ${{ inputs.setup-build-command }} + + - name: "Set up python ${{ inputs.python-version }}" + uses: actions/setup-python@v5 + with: + python-version: ${{ inputs.python-version }} + + - name: "Install build dependencies" + shell: bash + run: ${{ inputs.setup-build-command }} diff --git a/.github/actions/setup-hatch/action.yml b/.github/actions/setup-hatch/action.yml deleted file mode 100644 index 8c45ec98..00000000 --- a/.github/actions/setup-hatch/action.yml +++ /dev/null @@ -1,22 +0,0 @@ -name: "Setup `hatch`" -description: "Setup a python environment with `hatch` installed" - -inputs: - setup-command: - description: "The command to setup development dependencies" - default: "python -m pip install hatch" - python-version: - description: "The version of python to install" - default: "3.11" - -runs: - using: composite - steps: - - name: "Set up python ${{ inputs.python-version }}" - uses: actions/setup-python@v5 - with: - python-version: ${{ inputs.python-version }} - - - name: "Install build dependencies" - shell: bash - run: ${{ inputs.setup-command }} diff --git a/.github/workflows/build-artifacts.yml b/.github/workflows/build-artifacts.yml new file mode 100644 index 00000000..13e08bbb --- /dev/null +++ b/.github/workflows/build-artifacts.yml @@ -0,0 +1,112 @@ +name: "Build artifacts" +run-name: "Build `${{ inputs.package }}==${{ inputs.version}}` from `${{ inputs.branch }}` for deployment to `${{ deploy-environment }}`" + +on: + workflow_call: + inputs: + branch: + description: "The branch being used to build the package" + type: string + default: "main" + package: + description: "The name of the package being built" + type: string + version: + description: "The release version number (i.e. 1.0.0b1)" + type: string + required: true + deploy-environment: + description: "The environment where this package will be deployed" + type: string + default: "prod" + outputs: + archive-name: ${{ jobs.calculated-inputs.outputs.archive-name }} + workflow_dispatch: + inputs: + branch: + description: "The branch being used to build the package" + type: string + default: "main" + package: + description: "The name of the package being built" + type: choice + options: + - "dbt-adapters" + - "dbt-tests-adapter" + version: + description: "The release version number (i.e. 1.0.0b1)" + type: string + required: true + deploy-environment: + description: "The environment where this package will be deployed" + type: environment + +permissions: read-all + +# don't try to build the same version of the same package, the archive name could collide +concurrency: + group: ${{ github.workflow }}-${{ inputs.package }}-${{ inputs.version }}-${{ inputs.deploy-environment }} + cancel-in-progress: true + +defaults: + run: + shell: bash + +env: + NOTIFICATION_PREFIX: "[Build]" + +jobs: + calculated-inputs: + name: "Calculated inputs" + runs-on: ubuntu-latest + outputs: + archive-name: ${{ steps.archive.outputs.name }} + working-dir: ${{ steps.working-dir.outputs.path }} + steps: + - name: "Set: archive-name" + id: archive + shell: bash + run: | + name=${{ inputs.package }}-${{ inputs.version }}-${{ inputs.deploy-environment }} + echo "name=$name" >> $GITHUB_OUTPUT + + - name: "Set: working-dir" + id: working-dir + shell: bash + run: | + if [[ ${{ inputs.package }} == "dbt-tests-adapter" ]] + then + path="./dbt-tests-adapter/" + else + path="./" + fi + echo "path=$path" >> $GITHUB_OUTPUT + + - name: "[DEBUG] Inputs" + run: | + echo package : ${{ inputs.package }} + echo branch : ${{ inputs.branch }} + echo version : ${{ inputs.version }} + echo deploy-environment : ${{ inputs.deploy-environment }} + echo archive-name : ${{ steps.archive.outputs.name }} + echo working-dir : ${{ steps.working-dir.outputs.path }} + echo NOTIFICATION_PREFIX : ${{ env.NOTIFICATION_PREFIX }} + + build: + name: "Build the artifacts" + needs: [calculated-inputs] + runs-on: ubuntu-latest + steps: + - name: "Check out `${{ inputs.branch }}`" + uses: actions/checkout@v4 + with: + ref: ${{ inputs.branch }} + + - name: "Setup `hatch`" + uses: ./.github/actions/setup-environment + + - name: "Build `${{ inputs.package }}`" + uses: ./.github/actions/build + with: + archive-name: ${{ needs.calculated-inputs.outputs.archive-name }} + working-dir: ${{ needs.calculated-inputs.outputs.working-dir }} diff --git a/.github/workflows/generate-changelog.yml b/.github/workflows/build-changelog.yml similarity index 81% rename from .github/workflows/generate-changelog.yml rename to .github/workflows/build-changelog.yml index 51a91ef8..4e2dfa86 100644 --- a/.github/workflows/generate-changelog.yml +++ b/.github/workflows/build-changelog.yml @@ -1,9 +1,4 @@ -# **what?** -# Merge individual changelogs to generate the final changelog -# -# **when?** -# Call when ready to kick off a build and release, gets used automatically by `release.yml` -name: "Generate changelog" +name: "Build changelog" run-name: "Merge changelogs into one changelog on ${{ inputs.branch }} for ${{ inputs.version }}" on: @@ -55,25 +50,15 @@ defaults: shell: bash env: - NOTIFICATION_PREFIX: "[Generate changelog]" + NOTIFICATION_PREFIX: "[Build changelog]" jobs: - debug-inputs: - name: "[DEBUG] Inputs" - runs-on: ubuntu-latest - steps: - - name: "[DEBUG] Inputs" - run: | - echo branch : ${{ inputs.branch }} - echo version : ${{ inputs.version }} - echo NOTIFICATION_PREFIX : ${{ env.NOTIFICATION_PREFIX }} - - audit-changelog: - name: "Audit changelog" + calculated-inputs: + name: "Calculated inputs" runs-on: ubuntu-latest outputs: changelog-path: ${{ steps.audit-changelog.outputs.path }} - exists: ${{ steps.audit-changelog.outputs.exists }} + changelog-exists: ${{ steps.audit-changelog.outputs.exists }} steps: - name: "Check out `${{ inputs.branch }}`" uses: actions/checkout@v4 @@ -89,21 +74,17 @@ jobs: with: version: ${{ inputs.version }} - skip-changelog: - name: "Skip changelog generation" - if: ${{ needs.audit-changelog.outputs.exists }} - runs-on: ubuntu-latest - needs: [audit-changelog] - steps: - - name: "[INFO] Skipped changelog generation" + - name: "[DEBUG] Inputs" run: | - title="Skipped changelog" - message="The changelog already exists for version ${{ inputs.version }}: ${{ needs.audit-changelog.outputs.path }}" - echo "::notice title=${{ env.NOTIFICATION_PREFIX }}: $title::$message" + echo branch : ${{ inputs.branch }} + echo version : ${{ inputs.version }} + echo changelog-path : ${{ steps.audit-changelog.outputs.path }} + echo changelog-exists : ${{ steps.audit-changelog.outputs.exists }} + echo NOTIFICATION_PREFIX : ${{ env.NOTIFICATION_PREFIX }} generate-changelog: name: "Generate changelog" - if: ${{ !needs.audit-changelog.outputs.exists }} + if: ${{ !needs.calculated-inputs.outputs.changelog-exists }} runs-on: ubuntu-latest needs: [audit-changelog] steps: @@ -122,35 +103,44 @@ jobs: version: ${{ inputs.version }} - name: "Get Core team membership" - id: core_membership + id: core-membership uses: ./.github/actions/audit-github-team with: - organization: "dbt-labs" team: "core-group" env: GH_TOKEN: ${{ secrets.IT_TEAM_MEMBERSHIP }} - - name: "Set Core team membership for changie contributors exclusion" - id: set_team_membership + - name: "Set Core team membership for `changie` contributors exclusion" + id: set-team-membership run: echo "CHANGIE_CORE_TEAM=${{ steps.core_membership.outputs.members }}" >> $GITHUB_ENV - name: "Generate changelog" run: | + # this is a pre-release if [[ ${{ steps.semver.outputs.is_prerelease }} -eq 1 ]] then changie batch ${{ steps.semver.outputs.base_version }} --move-dir '${{ steps.semver.outputs.base_version }}' --prerelease ${{ steps.semver.outputs.prerelease }} + + # this is a final release with associated pre-releases elif [[ -d ".changes/${{ steps.semver.outputs.base_version }}" ]] then changie batch ${{ steps.semver.outputs.base_version }} --include '${{ steps.semver.outputs.base_version }}' --remove-prereleases - else # releasing a final patch with no prereleases + + # this is a final release with no associated pre-releases + else changie batch ${{ needs.audit-changelog.outputs.base_version }} fi + changie merge + - name: "Remove trailing whitespace and extra newlines" + continue-on-error: true + run: hatch run lint:pre-commit --files dbt/adapters/__about__.py CHANGELOG.md .changes/* + - name: "Check changelog generated successfully" run: | title="Generate changelog" - if [[ -f ${{ needs.audit-changelog.outputs.changelog_path }} ]] + if [[ -f ${{ needs.calculated-inputs.outputs.changelog-path }} ]] then message="Changelog file created successfully" echo "::notice title=${{ env.NOTIFICATION_PREFIX }}: $title::$message" @@ -160,17 +150,25 @@ jobs: exit 1 fi - - name: "Remove trailing whitespace and extra newlines" - continue-on-error: true - run: hatch run lint:pre-commit --files dbt/adapters/__about__.py CHANGELOG.md .changes/* - - name: "Commit and push changes" - uses: ./.github/actions/commit + uses: ./.github/actions/github-commit with: - message: "[automated] generate changelog for ${{ inputs.version }}" + message: "generate changelog for ${{ inputs.version }}" - name: "[INFO] Generated changelog" run: | title="Generated changelog" - message="Generated changelog for version ${{ inputs.version }}: ${{ needs.audit-changelog.outputs.path }}" + message="Generated changelog for version ${{ inputs.version }}: ${{ needs.calculated-inputs.outputs.changelog-path }}" + echo "::notice title=${{ env.NOTIFICATION_PREFIX }}: $title::$message" + + skip-changelog: + name: "Skip changelog generation" + if: ${{ needs.calculated-inputs.outputs.changelog-exists }} + runs-on: ubuntu-latest + needs: [audit-changelog] + steps: + - name: "[INFO] Skipped changelog generation" + run: | + title="Skipped changelog" + message="The changelog already exists for version ${{ inputs.version }}: ${{ needs.calculated-inputs.outputs.changelog-path }}" echo "::notice title=${{ env.NOTIFICATION_PREFIX }}: $title::$message" diff --git a/.github/workflows/bump-version.yml b/.github/workflows/build-version-bump.yml similarity index 58% rename from .github/workflows/bump-version.yml rename to .github/workflows/build-version-bump.yml index 194857da..37af14ba 100644 --- a/.github/workflows/bump-version.yml +++ b/.github/workflows/build-version-bump.yml @@ -1,8 +1,8 @@ -name: "Bump version" +name: "Version bump" run-name: "Bump branch `${{ inputs.branch }}` to `${{ inputs.version }}`" on: - workflow_dispatch: + workflow_call: inputs: branch: description: "The branch to bump" @@ -10,11 +10,16 @@ on: default: "main" version: description: "The version to bump to" + type: string required: true working-dir: description: "The working directory, useful for mono-repos" + type: string default: "./" - workflow_call: + outputs: + current-version: ${{ jobs.bump-version.outputs.version }} + bumped: ${{ jobs.bump-version.outputs.bumped }} + workflow_dispatch: inputs: branch: description: "The branch to bump" @@ -22,15 +27,10 @@ on: default: "main" version: description: "The version to bump to" - type: string required: true working-dir: description: "The working directory, useful for mono-repos" - type: string default: "./" - outputs: - current-version: ${{ jobs.bump-version.outputs.version }} - bumped: ${{ jobs.bump-version.outputs.bumped }} permissions: write-all @@ -40,26 +40,15 @@ concurrency: cancel-in-progress: true env: - NOTIFICATION_PREFIX: "[Bump version]" + NOTIFICATION_PREFIX: "[Version bump]" jobs: - debug-inputs: - name: "[DEBUG] Inputs" - runs-on: ubuntu-latest - steps: - - name: "[DEBUG] Inputs" - run: | - echo branch : ${{ inputs.branch }} - echo version : ${{ inputs.version }} - echo working-dir : ${{ inputs.working-dir }} - echo NOTIFICATION_PREFIX : ${{ env.NOTIFICATION_PREFIX }} - - bump-version: - name: "Bump `${{ inputs.branch}}` to `${{ inputs.version }}`" + calculated-inputs: + name: "Calculated inputs" runs-on: ubuntu-latest outputs: current-version: ${{ steps.current-version.outputs.version }} - bumped: ${{ steps.current-version.outputs.bumped }} + needs-version-bump: ${{ steps.version-bump.outputs.needs-version-bump }} steps: - name: "Check out `${{ inputs.branch }}`" uses: actions/checkout@v4 @@ -67,41 +56,71 @@ jobs: ref: ${{ inputs.branch }} - name: "Setup `hatch`" - uses: ./.github/actions/setup-hatch + uses: ./.github/actions/setup-environment - - name: "Current version" + - name: "Set: current-version" id: current-version shell: bash + run: echo "version=$(hatch version)" >> $GITHUB_OUTPUT + working-directory: ${{ inputs.working-dir }} + + - name: "Set: need-to-bump" + id: version-bump + shell: bash run: | - echo "version=$(hatch version)" >> $GITHUB_OUTPUT - if [[ $(hatch version) == "${{ inputs.version }} ]] + if [[ ${{ steps.current-version.outputs.version }} == "${{ inputs.version }} ]] then - echo "bumped=false" >> $GITHUB_OUTPUT + echo "needs-version-bump=false" >> $GITHUB_OUTPUT else - echo "bumped=true" >> $GITHUB_OUTPUT + echo "needs-version-bump=true" >> $GITHUB_OUTPUT fi - - name: "Bump version" - if: ${{ steps.current-version.outputs.version != inputs.version }} + - name: "[DEBUG] Parameters" + run: | + echo branch : ${{ inputs.branch }} + echo version : ${{ inputs.version }} + echo working-dir : ${{ inputs.working-dir }} + echo current-version : ${{ steps.current-version.outputs.version }} + echo need-to-bump : ${{ steps.version-bump.outputs.needs-version-bump }} + echo NOTIFICATION_PREFIX : ${{ env.NOTIFICATION_PREFIX }} + + bump-version: + name: "Bump version" + if: ${{ fromJSON(needs.calculated-inputs.outputs.needs-version-bump) }} + needs: [calculated-inputs] + runs-on: ubuntu-latest + steps: + - name: "Check out `${{ inputs.branch }}`" + uses: actions/checkout@v4 + with: + ref: ${{ inputs.branch }} + + - name: "Setup `hatch`" + uses: ./.github/actions/setup-environment + + - name: "Bump version to `${{ inputs.version }}`" shell: bash run: hatch version ${{ inputs.version }} working-directory: ${{ inputs.working-dir }} - name: "Commit and push changes" - if: ${{ steps.current-version.outputs.version != inputs.version }} - uses: ./.github/actions/commit + uses: ./.github/actions/github-commit with: - message: "[automated] bump version to ${{ inputs.version }}" + message: "bump version to ${{ inputs.version }}" - name: "[INFO] Bumped version" - if: ${{ steps.current-version.outputs.version != inputs.version }} run: | title="Bumped version" - message="Bumped from ${{ steps.current-version.outputs.version }} to ${{ inputs.version }}" + message="Bumped version from ${{ needs.calculated-inputs.outputs.current-version }} to ${{ inputs.version }}" echo "::notice title=${{ env.NOTIFICATION_PREFIX }}: $title::$message" + skip-version-bump: + name: "Skip version bump" + if: ${{ !fromJSON(needs.calculated-inputs.outputs.needs-version-bump) }} + needs: [calculated-inputs] + runs-on: ubuntu-latest + steps: - name: "[INFO] Skipped version bump" - if: ${{ steps.current-version.outputs.version == inputs.version }} run: | title="Skipped version bump" message="${{ inputs.branch }} is already at version ${{ inputs.version }}" diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml deleted file mode 100644 index 83d0cd39..00000000 --- a/.github/workflows/build.yml +++ /dev/null @@ -1,106 +0,0 @@ -name: "Build" -run-name: "Build `${{ inputs.package }}==${{ inputs.version}}` from `${{ inputs.branch }}` for deployment to `${{ deploy-to }}`" - -on: - workflow_call: - inputs: - package: - description: "Choose what to publish (dbt-adapters, dbt-tests-adapter)" - type: string - branch: - description: "Choose what branch to build from" - type: string - default: "main" - version: - description: "The release version number (i.e. 1.0.0b1)" - type: string - required: true - deploy-to: - description: "Choose where to publish" - type: string - default: prod - outputs: - archive-name: ${{ jobs.build.outputs.archive-name }} - workflow_dispatch: - inputs: - package: - description: "Choose what to build" - type: choice - options: - - dbt-adapters - - dbt-tests-adapter - branch: - description: "Choose what branch to build from" - type: string - default: "main" - version: - description: "The release version number (i.e. 1.0.0b1)" - type: string - required: true - deploy-to: - description: "Choose where to publish" - type: choice - options: - - prod - - test - -permissions: read-all - -# don't try to build the same version of the same package, the archive name could collide -concurrency: - group: ${{ github.workflow }}-${{ inputs.package }}-${{ inputs.version }}-${{ inputs.deploy-to }} - cancel-in-progress: true - -defaults: - run: - shell: bash - -env: - NOTIFICATION_PREFIX: "[Build]" - -jobs: - debug-inputs: - name: "[DEBUG] Inputs" - runs-on: ubuntu-latest - steps: - - name: "[DEBUG] Inputs" - run: | - echo package : ${{ inputs.package }} - echo branch : ${{ inputs.branch }} - echo version : ${{ inputs.version }} - echo deploy-to : ${{ inputs.deploy-to }} - echo NOTIFICATION_PREFIX : ${{ env.NOTIFICATION_PREFIX }} - - build: - name: "Build the artifacts" - runs-on: ubuntu-latest - outputs: - archive-name: ${{ steps.archive.outputs.archive-name }} - steps: - - name: "Check out `${{ inputs.branch }}`" - uses: actions/checkout@v4 - with: - ref: ${{ inputs.branch }} - - - name: "Create the archive name" - id: archive - shell: bash - run: | - name=${{ inputs.package }}-${{ inputs.version }}-${{ inputs.deploy-to }} - echo "name=$name" >> $GITHUB_OUTPUT - - - name: "Setup `hatch`" - uses: ./.github/actions/setup-hatch - - - name: "Build `dbt-adapters`" - if: ${{ inputs.package == 'dbt-adapters' }} - uses: ./.github/actions/build - with: - archive-name: ${{ steps.archive.outputs.name }} - - - name: "Build `dbt-tests-adapter`" - if: ${{ inputs.package == 'dbt-tests-adapter' }} - uses: ./.github/actions/build - with: - archive-name: ${{ steps.archive.outputs.name }} - working-dir: "./dbt-tests-adapter/" diff --git a/.github/workflows/check-changelog-entry.yml b/.github/workflows/check-changelog-entry.yml new file mode 100644 index 00000000..f7196bcb --- /dev/null +++ b/.github/workflows/check-changelog-entry.yml @@ -0,0 +1,35 @@ +name: "Changelog entry" + +on: + # run on pull_request_target because this workflow requires secrets to post comments + pull_request_target: + branches: + - "main" + - "*.latest" + # this is a cheap check, any change should trigger it + types: + - opened + - reopened + - labeled + - unlabeled + - synchronize + # we are only concerned about functional code changes, i.e. code changes that will appear in production + paths-ignore: + - ".changes/**" + - ".github/**" + - "tests/**" + - "third-party-stubs/**" + - "**.md" + - "**.yml" + +permissions: + contents: read + pull-requests: write + +jobs: + changelog: + uses: dbt-labs/actions/.github/workflows/changelog-existence.yml@main + with: + changelog_comment: "Thank you for your pull request! We could not find a changelog entry for this change. For details on how to document a change, see [the contributing guide](https://github.com/dbt-labs/dbt-adapters/blob/main/CONTRIBUTING.md#adding-changelog-entry)." + skip_label: "Skip Changelog" + secrets: inherit # this is only acceptable because we own the action we're calling diff --git a/.github/workflows/code-quality.yml b/.github/workflows/check-code-quality.yml similarity index 62% rename from .github/workflows/code-quality.yml rename to .github/workflows/check-code-quality.yml index 52fe0daf..80c9eaa3 100644 --- a/.github/workflows/code-quality.yml +++ b/.github/workflows/check-code-quality.yml @@ -1,36 +1,22 @@ name: "Code quality" on: - push: + pull_request: branches: - "main" - "*.latest" - pull_request: workflow_call: inputs: branch: description: "The branch to run code quality on" type: string default: "main" - lint-command: - description: "The lint command to run" - type: string - default: "hatch run lint:all" - typecheck-command: - description: "The typecheck command to run" - type: string - default: "hatch run typecheck:all" workflow_dispatch: inputs: branch: description: "The branch to run code quality on" + type: string default: "main" - lint-command: - description: "The lint command to run" - default: "hatch run lint:all" - typecheck-command: - description: "The typecheck command to run" - default: "hatch run typecheck:all" permissions: read-all @@ -40,7 +26,7 @@ defaults: # cancel the previous code quality run if a new one starts with the same parameters concurrency: - group: ${{ github.workflow }}-${{ github.event_name }}-${{ contains(github.event_name, 'workflow') && inputs.branch || contains(github.event_name, 'pull_request') && github.event.pull_request.head.ref || github.sha }} + group: ${{ github.workflow }}-${{ contains(github.event_name, 'workflow') && inputs.branch || contains(github.event_name, 'pull_request') && github.event.pull_request.head.ref }} cancel-in-progress: true env: @@ -61,14 +47,14 @@ jobs: - name: "Check out `${{ inputs.branch }}`" uses: actions/checkout@v4 with: - ref: ${{ contains(github.event_name, 'workflow') && inputs.branch || contains(github.event_name, 'pull_request') && github.event.pull_request.head.ref || github.sha }} + ref: ${{ contains(github.event_name, 'workflow') && inputs.branch || contains(github.event_name, 'pull_request') && github.event.pull_request.head.ref }} persist-credentials: false - name: "Setup `hatch`" uses: ./.github/actions/setup-hatch - name: "Run linters" - run: ${{ inputs.lint-command }} + run: hatch run lint:all - name: "Run typechecks" - run: ${{ inputs.typecheck-command }} + run: hatch run typecheck:all diff --git a/.github/workflows/check-for-changelog-entry.yml b/.github/workflows/check-for-changelog-entry.yml deleted file mode 100644 index b83bd11e..00000000 --- a/.github/workflows/check-for-changelog-entry.yml +++ /dev/null @@ -1,39 +0,0 @@ -# **what?** -# Checks that a file has been committed under the /.changes directory -# as a new CHANGELOG entry. Cannot check for a specific filename as -# it is dynamically generated by change type and timestamp. -# This workflow runs on pull_request_target because it requires -# secrets to post comments. - -# **why?** -# Ensure code change gets reflected in the CHANGELOG. - -# **when?** -# This will run for all PRs going into main. It will -# run when they are opened, reopened, when any label is added or removed -# and when new code is pushed to the branch. The action will get -# skipped if the 'Skip Changelog' label is present is any of the labels. - -name: "Check for changelog entry" - -on: - pull_request: - types: [opened, reopened, labeled, unlabeled, synchronize] - paths-ignore: ['.changes/**', '.github/**', 'tests/**', 'third-party-stubs/**', '**.md', '**.yml'] - workflow_dispatch: - -defaults: - run: - shell: bash - -permissions: - contents: read - pull-requests: write - -jobs: - changelog: - uses: dbt-labs/actions/.github/workflows/changelog-existence.yml@main - with: - changelog_comment: 'Thank you for your pull request! We could not find a changelog entry for this change. For details on how to document a change, see [the contributing guide](https://github.com/dbt-labs/dbt-adapters/blob/main/CONTRIBUTING.md#adding-changelog-entry).' - skip_label: 'Skip Changelog' - secrets: inherit # this is only acceptable because we own the action we're calling diff --git a/.github/workflows/unit-tests.yml b/.github/workflows/check-unit-tests.yml similarity index 89% rename from .github/workflows/unit-tests.yml rename to .github/workflows/check-unit-tests.yml index 6ff00368..71db48a3 100644 --- a/.github/workflows/unit-tests.yml +++ b/.github/workflows/check-unit-tests.yml @@ -1,21 +1,20 @@ name: "Unit tests" on: - push: + pull_request: branches: - "main" - "*.latest" - pull_request: - workflow_dispatch: + workflow_call: inputs: branch: - description: "Choose what branch to test" + description: "The branch to run unit tests on" type: string default: "main" - workflow_call: + workflow_dispatch: inputs: branch: - description: "Choose what branch to test" + description: "The branch to run unit tests on" type: string default: "main" @@ -23,7 +22,7 @@ permissions: read-all # will cancel previous workflows triggered by the same event and for the same ref for PRs or same SHA otherwise concurrency: - group: ${{ github.workflow }}-${{ github.event_name }}-${{ contains(github.event_name, 'workflow_') && inputs.branch || contains(github.event_name, 'pull_request') && github.event.pull_request.head.ref || github.sha }} + group: ${{ github.workflow }}-${{ github.event_name }}-${{ contains(github.event_name, 'workflow_') && inputs.branch || contains(github.event_name, 'pull_request') && github.event.pull_request.head.ref }} cancel-in-progress: true env: @@ -44,7 +43,7 @@ jobs: echo branch : ${{ inputs.branch }} echo NOTIFICATION_PREFIX : ${{ env.NOTIFICATION_PREFIX }} - - name: "Check out `${{ contains(github.event_name, 'workflow_') && inputs.branch || contains(github.event_name, 'pull_request') && github.event.pull_request.head.ref || github.sha }}`" + - name: "Check out `${{ contains(github.event_name, 'workflow_') && inputs.branch || contains(github.event_name, 'pull_request') && github.event.pull_request.head.ref }}`" uses: actions/checkout@v4 with: ref: ${{ contains(github.event_name, 'workflow_') && inputs.branch || contains(github.event_name, 'pull_request') && github.event.pull_request.head.ref || github.sha }} diff --git a/.github/workflows/resubmit-for-triage.yml b/.github/workflows/issues-resubmit-for-triage.yml similarity index 87% rename from .github/workflows/resubmit-for-triage.yml rename to .github/workflows/issues-resubmit-for-triage.yml index 3020509c..2b3237a5 100644 --- a/.github/workflows/resubmit-for-triage.yml +++ b/.github/workflows/issues-resubmit-for-triage.yml @@ -9,15 +9,10 @@ # **when?** # This will run when a comment is added to an issue and that issue has an `awaiting_response` label. - name: "Resubmit for triage" on: issue_comment -defaults: - run: - shell: bash - permissions: issues: write @@ -28,4 +23,4 @@ jobs: with: add_label: "triage" remove_label: "awaiting_response" - secrets: inherit # this is only acceptable because we own the action we're calling + secrets: inherit diff --git a/.github/workflows/issues-stale.yml b/.github/workflows/issues-stale.yml new file mode 100644 index 00000000..7360c9e1 --- /dev/null +++ b/.github/workflows/issues-stale.yml @@ -0,0 +1,24 @@ +# **what?** +# 1. Label issues and PRs which breach the threshold in our stale policy. +# This will notify participants that they will be closed soon. +# Any activity on the issue will remove the label. +# 2. Close issues or PRs which were previously marked as stale. +# +# **why?** +# Avoid triaging and working issues which are no longer relevant + +# **when?** +# Once a day +name: "Stale" + +on: + schedule: + - cron: "30 1 * * *" + +permissions: + issues: write + pull-requests: write + +jobs: + stale: + uses: dbt-labs/actions/.github/workflows/stale-bot-matrix.yml@main diff --git a/.github/workflows/publish-github.yml b/.github/workflows/publish-github.yml index a3350395..738eaaef 100644 --- a/.github/workflows/publish-github.yml +++ b/.github/workflows/publish-github.yml @@ -6,96 +6,83 @@ # 5. If this is deployed to prod, mark the draft release (created in this run or previously) as a full release. # # **when?** -# 1. Call after a successful build. Build artifacts should be ready to release.defaults: +# 1. Call after a successful build. Build artifacts should be ready to release. # They need to either live in a dist/ directory locally, or an archive name needs to be provided. -# 2. Call to publish a draft release to become a full release. No archive or artifacts are needed in this case. +# 2. Call to publish a draft release to become a full release. No archive, artifacts, or changelog path are needed in this case. name: "Publish to GitHub" -run-name: "Publish `${{ version }}` to GitHub in ${{ deploy-to }}" +run-name: "Publish `${{ version }}` to GitHub in ${{ deploy-environment }}" on: - workflow_dispatch: + workflow_call: inputs: - archive-name: - description: "Name of the archive containing the artifacts, leave blank if local or publishing draft to full" - type: string - default: "" version: description: "The release version number (i.e. 1.0.0b1)" type: string required: true sha: - description: "Commit SHA being released" - type: string - required: true - changelog-path: - description: "Path to the release notes" + description: "The SHA for the commit being released" type: string required: true - deploy-to: - description: "Choose where to publish" - type: environment - workflow_call: - inputs: archive-name: description: "Name of the archive containing the artifacts, leave blank if local or publishing draft to full" type: string default: "" + changelog-path: + description: "Path to the release notes, leave blank if publishing draft to full" + type: string + default: "" + deploy-environment: + description: "Choose where to publish" + type: string + default: "prod" + workflow_dispatch: + inputs: version: description: "The release version number (i.e. 1.0.0b1)" type: string required: true sha: - description: "Commit SHA being released" + description: "The SHA for the commit being released" type: string required: true + archive-name: + description: "Name of the archive containing the artifacts, leave blank if local or publishing draft to full" + type: string + default: "" changelog-path: - description: "Path to the release notes" + description: "Path to the release notes, leave blank if publishing draft to full" type: string - required: true - deploy-to: + default: "" + deploy-environment: description: "Choose where to publish" - type: string - default: "prod" + type: environment permissions: contents: write # will cancel previous workflows triggered by the same event and for the same package and environment concurrency: - group: ${{ github.workflow }}-${{ inputs.archive-name }}-${{ inputs.version }}-${{ inputs.deploy-to }} + group: ${{ github.workflow }}-${{ inputs.archive-name }}-${{ inputs.version }}-${{ inputs.deploy-environment }} cancel-in-progress: true env: - REPO_LINK: ${{ github.server_url }}/${{ github.repository }} NOTIFICATION_PREFIX: "[Publish - GitHub]" jobs: - debug-inputs: - name: "[DEBUG] Inputs" - runs-on: ubuntu-latest - steps: - - name: "[DEBUG] Inputs" - run: | - echo archive-name : ${{ inputs.archive-name }} - echo version : ${{ inputs.version }} - echo sha : ${{ inputs.sha }} - echo changelog-path : ${{ inputs.changelog-path }} - echo deploy-to : ${{ inputs.deploy-to }} - echo REPO_LINK : ${{ env.REPO_LINK }} - echo NOTIFICATION_PREFIX : ${{ env.NOTIFICATION_PREFIX }} - - publish: - name: "Publish to GitHub" + calculated-inputs: + name: "Calculated inputs" runs-on: ubuntu-latest outputs: - exists: ${{ steps.release_check.outputs.exists }} - draft_exists: ${{ steps.release_check.outputs.draft_exists }} - tag: ${{ steps.set_tag.outputs.tag }} + tag: ${{ steps.tag.outputs.tag }} + tag-sha: ${{ steps.tag-metadata.outputs.sha }} + tag-exists: ${{ steps.tag-metadata.outputs.exists }} + tag-is-draft: ${{ steps.tag-metadata.outputs.is-draft }} + commit-tag: ${{ steps.commit-metadata.outputs.tag }} steps: - name: "Check out `main`" uses: actions/checkout@v4 - - name: "Create tag" + - name: "Set: tag" id: tag shell: bash run: echo "tag=v${{ inputs.version }}" >> $GITHUB_OUTPUT @@ -114,47 +101,93 @@ jobs: with: tag: ${{ inputs.sha }} - - name: "[INFO] Release already exists" - if: ${{ fromJSON(steps.tag-metadata.outputs.exists) == true }} && ${{ steps.tag-metadata.outputs.sha }} == ${{ inputs.sha }} + - name: "[DEBUG] Inputs" + run: | + echo archive-name : ${{ inputs.archive-name }} + echo version : ${{ inputs.version }} + echo sha : ${{ inputs.sha }} + echo changelog-path : ${{ inputs.changelog-path }} + echo deploy-environment : ${{ inputs.deploy-environment }} + echo tag : ${{ steps.tag.outputs.tag }} + echo tag-sha : ${{ steps.tag-metadata.outputs.sha }} + echo tag-exists : ${{ steps.tag-metadata.outputs.exists }} + echo tag-is-draft : ${{ steps.tag-metadata.outputs.is-draft }} + echo commit-tag : ${{ steps.commit-metadata.outputs.tag }} + echo NOTIFICATION_PREFIX : ${{ env.NOTIFICATION_PREFIX }} + + validation: + name: "Validate input scenarios" + needs: [calculated-inputs] + runs-on: ubuntu-latest + steps: + - name: "[INFO] Exit gracefully if the tag exists and it's a full release" + if: ${{ fromJSON(needs.calculated-inputs.outputs.tag-exists) && !fromJSON(needs.calculated-inputs.outputs.tag-is-draft) }} run: | - title="Tag already exists, skip publishing artifacts" - message="Tag ${{ steps.tag.outputs.tag }} already exists and is associated with the commit ${{ steps.tag-metadata.outputs.sha }}." + title="Full release already exists" + message="`${{ needs.calculated-inputs.outputs.tag }}` already exists as a full release and is associated with the commit ${{ needs.calculated-inputs.outputs.tag-sha }}." echo "::notice title=${{ env.NOTIFICATION_PREFIX }}: $title::$message" + exit 0 - - name: "[ERROR] Exit if the tag exists and is associated with a different commit than the one provided" - if: ${{ fromJSON(steps.tag-metadata.outputs.exists) == true }} && ${{ steps.tag-metadata.outputs.sha }} != ${{ inputs.sha }} + - name: "[ERROR] Exit with error if the tag exists and is associated with a different commit than the one provided" + if: ${{ fromJSON(needs.calculated-inputs.outputs.tag-exists) }} && ${{ needs.calculated-inputs.outputs.tag-sha }} != ${{ inputs.sha }} shell: bash run: | - title="Tag ${{ inputs.tag }} already exists with a different commit!" + title="Tag `v${{ inputs.version }}` already exists with a different commit!" message="Existing commit: {{ steps.tag-metadata.outputs.sha }} New commit: ${{ inputs.sha }}. Exiting." echo "::error title=${{ env.NOTIFICATION_PREFIX }}: $title::$message" exit 1 - - name: "[ERROR] Exit if the commit is associated with a different tag than the version that was provided" - if: ${{ fromJSON(steps.tag-metadata.outputs.exists) == false }} && ${{ steps.commit-metadata.outputs.tag != '' }} + - name: "[ERROR] Exit with error if the commit is associated with a different tag than the version that was provided" + if: ${{ needs.calculated-inputs.outputs.commit-tag != '' }} && ${{ needs.calculated-inputs.outputs.commit-tag != needs.calculated-inputs.outputs.tag }} run: | title="Commit ${{ inputs.sha }} is already associated with a different tag!" - message="Existing tag: ${{ steps.commit-metadata.outputs.tag }} New tag: ${{ steps.tag.outputs.tag }}" + message="Existing tag: ${{ needs.calculated-inputs.outputs.commit-tag }} New tag: ${{ needs.calculated-inputs.outputs.tag }}" echo "::error title=${{ env.NOTIFICATION_PREFIX }}: $title::$message" exit 1 - - name: "Publish to GitHub as draft release" - if: fromJSON(steps.tag-metadata.outputs.exists) == false + new-tag: + name: "Publish draft release to GitHub" + needs: [calculated-inputs, validation] + if: ${{ !fromJSON(needs.calculated-inputs.outputs.tag-exists) }} + runs-on: ubuntu-latest + steps: + - name: "Check out `main`" + uses: actions/checkout@v4 + + - name: "Publish to GitHub as a draft release" uses: ./.github/actions/publish-github-draft with: - archive-name: ${{ inputs.archive-name }} - tag: ${{ needs.check-release-exists.outputs.tag }} - repo-url: ${{ env.REPO_LINK }} + repo-url: ${{ github.server_url }}/${{ github.repository }} + tag: ${{ needs.calculated-inputs.outputs.tag }} sha: ${{ inputs.sha }} - changelog-path: ${{ inputs.changelog_path }} - - - name: "Publish draft release as full release" - if: >- - inputs.deploy-to == "prod" && ( - fromJSON(steps.tag-metadata.outputs.exists) == false || - fromJSON(steps.tag-metadata.outputs.is-draft) == true - ) + archive-name: ${{ inputs.archive-name }} + changelog-path: ${{ inputs.changelog-path }} + + - name: "[INFO] Published to GitHub as a draft release" + run: | + title="Published to GitHub as a draft release" + message="${{ needs.calculated-inputs.outputs.tag }} was created as a draft release with the commit ${{ inputs.sha }}." + echo "::notice title=${{ env.NOTIFICATION_PREFIX }}: $title::$message" + + existing-tag: + name: "Publish GitHub draft as full release" + # require publish-draft to cover the scenario where a production release is being created without an existing draft release + needs: [calculated-inputs, validation, publish-draft] + # allow for publish-draft to be skipped, e.g. if this is a production release where the draft already existed + if: ${{ !failure() && inputs.deploy-environment == "prod" }} + runs-on: ubuntu-latest + steps: + - name: "Check out `main`" + uses: actions/checkout@v4 + + - name: "Publish draft release as a full release" uses: ./.github/actions/publish-github-full with: - tag: ${{ steps.tag.output.tag }} - repo-url: ${{ env.REPO_LINK }} + repo-url: ${{ github.server_url }}/${{ github.repository }} + tag: ${{ needs.calculated-inputs.outputs.tag }} + + - name: "[INFO] Published draft release as a full release" + run: | + title="Published draft release as a full release" + message="`${{ needs.calculated-inputs.outputs.tag }}` was published as a full release." + echo "::notice title=${{ env.NOTIFICATION_PREFIX }}: $title::$message" diff --git a/.github/workflows/publish-pypi.yml b/.github/workflows/publish-pypi.yml index 4710b3d3..a34b6c29 100644 --- a/.github/workflows/publish-pypi.yml +++ b/.github/workflows/publish-pypi.yml @@ -5,7 +5,7 @@ # Call after a successful build. Build artifacts should be ready to release.defaults: # They need to either live in a dist/ directory locally, or an archive name needs to be provided. name: "Publish to PyPI" -run-name: "Publish `${{ version }}` to PyPI in ${{ deploy-to }}" +run-name: "Publish `${{ version }}` to PyPI in ${{ deploy-environment }}" on: workflow_dispatch: @@ -17,7 +17,7 @@ on: description: "The release version number (i.e. 1.0.0b1)" type: string required: true - deploy-to: + deploy-environment: description: "Choose where to publish" type: environment workflow_call: @@ -30,7 +30,7 @@ on: description: "The release version number (i.e. 1.0.0b1)" type: string required: true - deploy-to: + deploy-environment: description: "Choose where to publish" type: string default: "prod" @@ -40,7 +40,7 @@ permissions: # will cancel previous workflows triggered by the same event and for the same package and environment concurrency: - group: ${{ github.workflow }}-${{ inputs.archive-name }}-${{ inputs.version }}-${{ inputs.deploy-to }} + group: ${{ github.workflow }}-${{ inputs.archive-name }}-${{ inputs.version }}-${{ inputs.deploy-environment }} cancel-in-progress: true env: @@ -55,7 +55,7 @@ jobs: run: | echo archive-name : ${{ inputs.archive-name }} echo version : ${{ inputs.version }} - echo deploy-to : ${{ inputs.deploy-to }} + echo deploy-environment : ${{ inputs.deploy-environment }} echo PYPI_PROJECT_URL : ${{ vars.PYPI_PROJECT_URL }} echo PYPI_REPOSITORY_URL : ${{ vars.PYPI_REPOSITORY_URL }} @@ -63,7 +63,7 @@ jobs: name: "Publish to PyPI" runs-on: ubuntu-latest environment: - name: ${{ inputs.deploy-to }} + name: ${{ inputs.deploy-environment }} url: ${{ vars.PYPI_PROJECT_URL }} steps: - name: "Check out `main`" diff --git a/.github/workflows/release-branch-create.yml b/.github/workflows/release-branch-create.yml index f99b5f1b..5fda905e 100644 --- a/.github/workflows/release-branch-create.yml +++ b/.github/workflows/release-branch-create.yml @@ -63,5 +63,3 @@ jobs: uses: ./.github/actions/create-temp-branch with: branch-stub: "release/${{ inputs.version }}/" - env: - NOTIFICATION_PREFIX: "[create release branch]" diff --git a/.github/workflows/release-branch-merge.yml b/.github/workflows/release-branch-merge.yml index e619ceef..7d8f362d 100644 --- a/.github/workflows/release-branch-merge.yml +++ b/.github/workflows/release-branch-merge.yml @@ -7,15 +7,19 @@ on: branch: description: "The base branch receiving the changes" type: string - default: "main" + required: true release-branch: description: "The branch containing the release changes" type: string - default: "main" + required: true + deploy-environment: + description: "Choose where to publish" + type: string + required: true outputs: sha: description: "The sha associated with this merge" - value: ${{ jobs.merge-release-branch.outputs.sha }} + value: ${{ jobs.merge.outputs.sha }} # this is the permission that allows creating a new release to both GitHub and PyPI permissions: @@ -27,10 +31,6 @@ concurrency: group: ${{ github.workflow }}-${{ inputs.branch }}-${{ inputs.release-branch }} cancel-in-progress: true -defaults: - run: - shell: bash - env: NOTIFICATION_PREFIX: "[Merge release branch]" @@ -45,41 +45,30 @@ jobs: echo release-branch : ${{ inputs.release-branch }} echo NOTIFICATION_PREFIX : ${{ env.NOTIFICATION_PREFIX }} - merge-release-branch: + merge: name: "Merge `${{ inputs.release-branch }}` into `${{ inputs.branch }}`" runs-on: ubuntu-latest needs: [temp-branch] outputs: - sha: ${{ steps.release-sha.outputs.sha }} + sha: ${{ steps.merge.outputs.sha }} || ${{ steps.test-merge.outputs.sha }} steps: - name: "Checkout `${{ inputs.release-branch }}`" uses: actions/checkout@v4 with: - ref: ${{ inputs.temp-branch }} + ref: ${{ inputs.release-branch }} - name: "Merge `${{ inputs.release-branch }}` into `${{ inputs.branch }}`" - uses: everlytic/branch-merge@1.1.5 - with: - source_ref: ${{ inputs.release-branch }} - target_branch: ${{ inputs.branch }} - github_token: ${{ secrets.FISHTOWN_BOT_PAT }} - commit_message_template: "[automated] merge {source_ref} into {target_branch} for a release" - - - name: "Checkout `${{ inputs.branch }}`" - uses: actions/checkout@v3 + if: ${{ inputs.deploy-environment == "prod" }} + id: merge + uses: ./.github/actions/github-merge with: - ref: ${{ inputs.branch }} - - # TODO: see if everlytic/branch-merge has outputs that have this information - - name: "Get commit SHA for the merge" - id: release-sha - run: echo "sha=$(git rev-parse HEAD)" >> $GITHUB_OUTPUT - - - name: "Delete `${{ inputs.release-branch }}`" - run: git push origin -d ${{ inputs.release-branch }} + source-branch: ${{ inputs.release-branch }} + target-branch: ${{ inputs.branch }} + message: "merge {source_ref} into {target_branch} for a release" - - name: "[INFO] Merged changes" + - name: "Get HEAD sha for test release" + id: test-merge + shell: bash run: | - title="Merged changes" - message="The ${{ inputs.release-branch }} branch was merged into ${{ inputs.branch }} with sha ${{ steps.release-sha.outputs.sha }}" - echo "::notice title=${{ env.NOTIFICATION_PREFIX }}: $title::$message" + git pull + echo "sha=$(git rev-parse HEAD)" >> $GITHUB_OUTPUT diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index ff8baf70..01382506 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -2,43 +2,43 @@ name: "Release" run-name: "Release `${{ inputs.package }}==${{ inputs.version }}` to `${{ inputs.deploy-to }}`" on: - workflow_dispatch: + workflow_call: inputs: - package: - description: "Choose what to release" - type: choice - options: - - "dbt-adapters" - - "dbt-tests-adapter" branch: description: "Choose what branch to release from" type: string default: "main" + package: + description: "Choose what to release" + type: string + default: "dbt-adapters" version: description: "The release version number (i.e. 1.0.0b1)" type: string required: true - deploy-to: + deploy-environment: description: "Choose where to publish" - type: environment - workflow_call: - inputs: - package: - description: "Choose what to release" type: string - default: "dbt-adapters" + default: "prod" + workflow_dispatch: + inputs: branch: description: "Choose what branch to release from" type: string default: "main" + package: + description: "Choose what to release" + type: choice + options: + - "dbt-adapters" + - "dbt-tests-adapter" version: description: "The release version number (i.e. 1.0.0b1)" type: string required: true - deploy-to: + deploy-environment: description: "Choose where to publish" - type: string - default: "prod" + type: environment # this is the permission that allows creating a new release to both GitHub and PyPI permissions: @@ -47,7 +47,7 @@ permissions: # deploying the same version of a package to the same environment should override any previous deployment with those attributes concurrency: - group: ${{ github.workflow }}-${{ inputs.package }}-${{ inputs.version }}-${{ inputs.deploy-to }} + group: ${{ github.workflow }}-${{ inputs.package }}-${{ inputs.version }}-${{ inputs.deploy-environment }} cancel-in-progress: true defaults: @@ -55,7 +55,7 @@ defaults: shell: bash jobs: - release-inputs: + calculated-inputs: name: "Release inputs" runs-on: ubuntu-latest outputs: @@ -66,7 +66,7 @@ jobs: - name: "Computed inputs" id: computed-inputs run: | - archive_name=${{ inputs.package }}-${{ inputs.version_number }}-${{ inputs.deploy-to }} + archive_name=${{ inputs.package }}-${{ inputs.version_number }}-${{ inputs.deploy-environment }} working_dir="./" run_unit_tests=true @@ -82,25 +82,25 @@ jobs: - name: "[DEBUG] Inputs" run: | - echo package : ${{ inputs.package }} - echo branch : ${{ inputs.branch }} - echo version : ${{ inputs.version }} - echo deploy-to : ${{ inputs.deploy-to }} - echo archive-name : ${{ steps.release-inputs.outputs.archive-name }} - echo working-dir : ${{ steps.release-inputs.outputs.working-dir }} - echo run-unit-tests : ${{ steps.release-inputs.outputs.run-unit-tests }} + echo branch : ${{ inputs.branch }} + echo package : ${{ inputs.package }} + echo version : ${{ inputs.version }} + echo deploy-environment : ${{ inputs.deploy-environment }} + echo archive-name : ${{ steps.release-inputs.outputs.archive-name }} + echo working-dir : ${{ steps.release-inputs.outputs.working-dir }} + echo run-unit-tests : ${{ steps.release-inputs.outputs.run-unit-tests }} code-quality: name: "Run code quality" - uses: dbt-labs/dbt-adapters/.github/workflows/code-quality.yml + uses: dbt-labs/dbt-adapters/.github/workflows/check-code-quality.yml@update-workflows with: branch: ${{ inputs.branch }} unit-tests: name: "Run unit tests" - needs: [release-inputs] - if: ${{ fromJSON(needs.release-inputs.outputs.run-unit-tests) == true }} - uses: dbt-labs/dbt-adapters/.github/workflows/unit-tests.yml@update-workflows + needs: [calculated-inputs] + if: ${{ fromJSON(needs.calculated-inputs.outputs.run-unit-tests) }} + uses: dbt-labs/dbt-adapters/.github/workflows/check-unit-tests.yml@update-workflows with: branch: ${{ inputs.branch }} @@ -112,69 +112,70 @@ jobs: version: ${{ inputs.version }} secrets: inherit - bump-version: + version-bump: name: "Bump the version" - uses: dbt-labs/dbt-adapters/.github/workflows/bump-version.yml@update-workflows - needs: [release-branch, release-inputs] + uses: dbt-labs/dbt-adapters/.github/workflows/build-version-bump.yml@update-workflows + needs: [release-branch, calculated-inputs] with: branch: ${{ needs.release-branch.outputs.branch }} version: ${{ inputs.version }} working-dir: ${{ needs.release-inputs.outputs.working-dir }} secrets: inherit - generate-changelog: + changelog: name: "Generate a new changelog" needs: [release-branch] - uses: dbt-labs/dbt-adapters/.github/workflows/generate-changelog.yml@update-workflows + uses: dbt-labs/dbt-adapters/.github/workflows/build-changelog.yml@update-workflows with: branch: ${{ needs.release-branch.outputs.branch }} version: ${{ inputs.version }} secrets: inherit - merge-changes: - name: "Merge the version bump and changelog updates" + build-artifacts: + name: "Build the artifacts" + if: ${{ !failure() && !cancelled() }} needs: [ - release-branch, - bump-version, - generate-changelog, code-quality, unit-tests, + release-branch, + version-bump, + changelog, ] - if: ${{ !failure() && !cancelled() && (needs.bump-version.outputs.bumped || needs.generate-changelog.outputs.created) }} + uses: dbt-labs/dbt-adapters/.github/workflows/build-artifacts.yml@update-workflows + with: + branch: ${{ needs.release-branch.outputs.branch }} + package: ${{ inputs.package }} + version: ${{ inputs.version }} + deploy-to: ${{ inputs.deploy-environment }} + + merge-changes: + name: "Merge the version bump and changelog updates" + needs: [build-artifacts, version-bump, changelog] + if: ${{ !failure() && !cancelled() && inputs.deploy-environment == "prod" && (needs.version-bump.outputs.bumped || needs.changelog.outputs.created) }} uses: dbt-labs/dbt-adapters/.github/workflows/release-branch-merge.yml@update-workflows with: branch: ${{ inputs.branch }} - temp-branch: ${{ needs.release-branch.outputs.branch }} + release-branch: ${{ needs.release-branch.outputs.branch }} secrets: inherit - build-artifacts: - name: "Build the artifacts" - if: ${{ !failure() && !cancelled() }} - needs: [merge-changes, release-inputs] - uses: dbt-labs/dbt-adapters/.github/workflows/build.yml@update-workflows - with: - package: ${{ inputs.package }} - version: ${{ inputs.version }} - deploy-to: ${{ inputs.deploy-to }} - publish-github: name: "Publish the artifacts to GitHub" if: ${{ !failure() && !cancelled() && inputs.package == 'dbt-adapters' }} - needs: [build-artifacts, merge-changes] + needs: [build-artifacts, changelog, merge-changes] uses: dbt-labs/dbt-adapters/.github/workflows/publish-github.yml@update-workflows with: archive-name: ${{ needs.build-artifacts.outputs.archive-name }} version: ${{ inputs.version }} + deploy-to: ${{ inputs.deploy-environment }} sha: ${{ needs.merge-changes.outputs.sha }} - changelog-path: ${{ needs.bump-version-generate-changelog.outputs.changelog_path }} - deploy-to: ${{ inputs.deploy-to }} + changelog-path: ${{ needs.changelog.outputs.changelog-path }} - publish-0pypi: + publish-pypi: name: "Publish the artifacts to PyPI" if: ${{ !failure() && !cancelled() }} - needs: [build-artifacts] - uses: dbt-labs/dbt-adapters/.github/workflows/publish-github.yml@update-workflows + needs: [build-artifacts, merge-changes] + uses: dbt-labs/dbt-adapters/.github/workflows/publish-pypi.yml@update-workflows with: archive-name: ${{ needs.build-artifacts.outputs.archive-name }} version: ${{ inputs.version }} - deploy-to: ${{ inputs.deploy-to }} + deploy-to: ${{ inputs.deploy-environment }} diff --git a/.github/workflows/stale.yml b/.github/workflows/stale.yml deleted file mode 100644 index 75a14dd4..00000000 --- a/.github/workflows/stale.yml +++ /dev/null @@ -1,30 +0,0 @@ -# **what?** -# For issues that have been open for awhile without activity, label -# them as stale with a warning that they will be closed out. If -# anyone comments to keep the issue open, it will automatically -# remove the stale label and keep it open. - -# Stale label rules: -# awaiting_response, more_information_needed -> 90 days -# good_first_issue, help_wanted -> 360 days (a year) -# tech_debt -> 720 (2 years) -# all else defaults -> 180 days (6 months) - -# **why?** -# To keep the repo in a clean state from issues that aren't relevant anymore - -# **when?** -# Once a day - -name: "Close stale issues and PRs" -on: - schedule: - - cron: "30 1 * * *" - -permissions: - issues: write - pull-requests: write - -jobs: - stale: - uses: dbt-labs/actions/.github/workflows/stale-bot-matrix.yml@main