From de139943d8272773b5f19ed824d687b0232b9ba3 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Sat, 11 Mar 2023 09:03:03 +0100 Subject: Adding upstream version 0.19.1. Signed-off-by: Daniel Baumann --- .github/workflows/checks.yml | 155 ------------------------------ .github/workflows/ci.yml | 142 +++++++++++++++++++++++++++ .github/workflows/github-release.yml | 14 +++ .github/workflows/publish-docker.yml | 79 +++++++++++++++ .github/workflows/publish-release.yml | 176 ++++++++++++++++++++++++++++++++++ .github/workflows/test-release.yml | 95 ++++++++++++++++++ 6 files changed, 506 insertions(+), 155 deletions(-) delete mode 100644 .github/workflows/checks.yml create mode 100644 .github/workflows/ci.yml create mode 100644 .github/workflows/github-release.yml create mode 100644 .github/workflows/publish-docker.yml create mode 100644 .github/workflows/publish-release.yml create mode 100644 .github/workflows/test-release.yml (limited to '.github/workflows') diff --git a/.github/workflows/checks.yml b/.github/workflows/checks.yml deleted file mode 100644 index 39b3782..0000000 --- a/.github/workflows/checks.yml +++ /dev/null @@ -1,155 +0,0 @@ -name: Tests and Checks - -on: [push, pull_request] - -jobs: - checks: - runs-on: "ubuntu-latest" - strategy: - matrix: - python-version: ["3.6", "3.7", "3.8", "3.9", "3.10", "3.11", pypy-3.9] - os: ["macos-latest", "ubuntu-latest"] - steps: - - uses: actions/checkout@v3.0.2 - with: - ref: ${{ github.event.pull_request.head.sha }} # Checkout pull request HEAD commit instead of merge commit - - # Because gitlint is a tool that uses git itself under the hood, we remove git tracking from the checked out - # code by temporarily renaming the .git directory. - # This is to ensure that the tests don't have a dependency on the version control of gitlint itself. - - name: Temporarily remove git version control from code - run: mv .git ._git - - - name: Setup python - uses: actions/setup-python@v4.2.0 - with: - python-version: ${{ matrix.python-version }} - - - name: Install requirements - run: | - python -m pip install --upgrade pip - pip install -r requirements.txt - pip install -r test-requirements.txt - - - name: Unit Tests - run: ./run_tests.sh - - # Coveralls integration doesn't properly work at this point, also see below - # - name: Coveralls - # env: - # COVERALLS_REPO_TOKEN: ${{ secrets.COVERALLS_REPO_TOKEN }} - # run: coveralls - - # Patch the commit-msg hook to make it work in GH CI - # Specifically, within the commit-msg hook, wrap the invocation of gitlint with `script` - - - name: Patch commit-msg hook - run: | - # Escape " to \" - sed -i -E '/^gitlint/ s/"/\\"/g' gitlint-core/gitlint/files/commit-msg - # Replace `gitlint ` with `script -e -q -c "gitlint "` - sed -i -E 's/^gitlint(.*)/script -e -q -c "\0"/' gitlint-core/gitlint/files/commit-msg - - - name: Integration Tests - run: ./run_tests.sh -i - - # Gitlint no longer uses `sh` by default, but for now we're still supporting the manual enablement of it. - # By setting GITLINT_USE_SH_LIB=1, we test whether this still works. - - name: Integration Tests (GITLINT_USE_SH_LIB=1) - env: - GITLINT_USE_SH_LIB: 1 - run: ./run_tests.sh -i - - - name: Code formatting (black) - run: ./run_tests.sh -f - - - name: PyLint - run: ./run_tests.sh -l - - - name: Build tests - run: ./run_tests.sh --build - - # Coveralls GH Action currently doesn't support current non-LCOV reporting format - # For now, still using Travis for unit test coverage reporting - # https://github.com/coverallsapp/github-action/issues/30 - # - name: Coveralls - # uses: coverallsapp/github-action@master - # with: - # github-token: ${{ secrets.GITHUB_TOKEN }} - - # Re-add git version control so we can run gitlint on itself. - - name: Re-add git version control to code - run: mv ._git .git - - # Run gitlint. Skip during PR runs, since PR commit messages are transient and usually full of gitlint violations. - # PRs get squashed and get a proper commit message during merge. - - name: Gitlint check - run: ./run_tests.sh -g --debug - if: ${{ github.event_name != 'pull_request' }} - - windows-checks: - runs-on: windows-latest - strategy: - matrix: - python-version: ["3.10"] - steps: - - uses: actions/checkout@v3.0.2 - with: - ref: ${{ github.event.pull_request.head.sha }} # Checkout pull request HEAD commit instead of merge commit - - # Because gitlint is a tool that uses git itself under the hood, we remove git tracking from the checked out - # code by temporarily renaming the .git directory. - # This is to ensure that the tests don't have a dependency on the version control of gitlint itself. - - name: Temporarily remove git version control from code - run: Rename-Item .git ._git - - - name: Setup python - uses: actions/setup-python@v4.2.0 - with: - python-version: ${{ matrix.python-version }} - - - name: "Upgrade pip on Python 3" - if: matrix.python-version == '3.10' - run: python -m pip install --upgrade pip - - - name: Install requirements - run: | - pip install -r requirements.txt - pip install -r test-requirements.txt - - - name: gitlint --version - run: gitlint --version - - - name: Tests (sanity) - run: tools\windows\run_tests.bat "gitlint-core\gitlint\tests\cli\test_cli.py::CLITests::test_lint" - - - name: Tests (ignore cli\*) - run: pytest --ignore gitlint-core\gitlint\tests\cli -rw -s gitlint-core - - - name: Tests (test_cli.py only - continue-on-error:true) - run: tools\windows\run_tests.bat "gitlint-core\gitlint\tests\cli\test_cli.py" - continue-on-error: true # Known to fail at this point - - - name: Tests (all - continue-on-error:true) - run: tools\windows\run_tests.bat - continue-on-error: true # Known to fail at this point - - - name: Integration tests (continue-on-error:true) - run: pytest -rw -s qa - continue-on-error: true # Known to fail at this point - - - name: Code formatting (black) - run: black . - - - name: PyLint - run: pylint gitlint-core\gitlint qa --rcfile=".pylintrc" -r n - - # Re-add git version control so we can run gitlint on itself. - - name: Re-add git version control to code - run: Rename-Item ._git .git - - # Run gitlint. Skip during PR runs, since PR commit messages are transient and usually full of gitlint violations. - # PRs get squashed and get a proper commit message during merge. - - name: Gitlint check - run: gitlint --debug - if: ${{ github.event_name != 'pull_request' }} diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..403dcc4 --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,142 @@ +name: Tests and Checks + +# Only run CI on pushes to main and pull requests +# We don't run CI on other branches, but those should be merged into main via a PR anyways which will trigger CI before the merge. +on: + push: + branches: + - main + pull_request: + branches: + - main + +concurrency: + group: ci-${{ github.ref }}-1 + cancel-in-progress: true + +jobs: + checks: + runs-on: "ubuntu-latest" + strategy: + matrix: + python-version: ["3.7", "3.8", "3.9", "3.10", "3.11", pypy-3.9] + os: ["macos-latest", "ubuntu-latest", "windows-latest"] + steps: + - uses: actions/checkout@v3.3.0 + with: + ref: ${{ github.event.pull_request.head.sha }} # Checkout pull request HEAD commit instead of merge commit + fetch-depth: 0 # checkout all history, needed for hatch versioning + + - name: Setup python + uses: actions/setup-python@v4.5.0 + with: + python-version: ${{ matrix.python-version }} + + - name: Install pypa/build + run: python -m pip install build==0.10.0 + + - name: Install Hatch + run: python -m pip install hatch==1.6.3 + + - name: Unit Tests + run: hatch run test:unit-tests + + - name: Code formatting (black) + run: hatch run test:format + + - name: Code linting (ruff) + run: hatch run test:lint + + - name: Install local gitlint for integration tests + run: | + hatch run qa:install-local + + - name: Integration tests (default -> GITLINT_USE_SH_LIB=1) + run: | + hatch run qa:integration-tests + if: matrix.os != 'windows-latest' + + - name: Integration tests (GITLINT_USE_SH_LIB=1) + run: | + hatch run qa:integration-tests + env: + GITLINT_USE_SH_LIB: 1 + if: matrix.os != 'windows-latest' + + - name: Integration tests (GITLINT_QA_USE_SH_LIB=0) + run: | + hatch run qa:integration-tests -k "not(test_commit_hook_continue or test_commit_hook_abort or test_commit_hook_edit)" qa + env: + GITLINT_QA_USE_SH_LIB: 0 + if: matrix.os != 'windows-latest' + + - name: Integration tests (Windows) + run: | + hatch run qa:integration-tests -k "not (test_commit_hook_continue or test_commit_hook_abort or test_commit_hook_edit or test_lint_staged_stdin or test_stdin_file or test_stdin_pipe_empty)" qa + if: matrix.os == 'windows-latest' + + - name: Build test (gitlint) + run: | + python -m build + hatch clean + + - name: Build test (gitlint-core) + run: | + python -m build + hatch clean + working-directory: ./gitlint-core + + - name: Docs build (mkdocs) + run: hatch run docs:build + + # Run gitlint. Skip during PR runs, since PR commit messages are transient and usually full of gitlint violations. + # PRs get squashed and get a proper commit message during merge. + - name: gitlint --debug + run: hatch run dev:gitlint --debug + continue-on-error: ${{ github.event_name == 'pull_request' }} # Don't enforce gitlint in PRs + + - name: Code Coverage (coveralls) + uses: coverallsapp/github-action@master + with: + path-to-lcov: ".coverage.lcov" + github-token: ${{ secrets.GITHUB_TOKEN }} + git-commit: ${{ github.event.pull_request.head.sha }} + flag-name: gitlint-${{ matrix.os }}-${{ matrix.python-version }} + parallel: true + + upload_coveralls: + needs: checks + runs-on: ubuntu-latest + steps: + - name: Upload coverage to coveralls + uses: coverallsapp/github-action@master + with: + path-to-lcov: ".coverage.lcov" + github-token: ${{ secrets.GITHUB_TOKEN }} + parallel-finished: true + + check: # This job does nothing and is only used for the branch protection + if: always() # Ref: https://github.com/marketplace/actions/alls-green#why + + needs: + - upload_coveralls + - checks + + runs-on: ubuntu-latest + + steps: + - name: Decide whether the needed jobs succeeded or failed + uses: re-actors/alls-green@release/v1 + with: + jobs: ${{ toJSON(needs) }} + + # When on main, auto publish dev build + auto-publish-dev: + needs: + - check + if: github.ref == 'refs/heads/main' + uses: ./.github/workflows/publish-release.yml + secrets: inherit # pass all secrets (required to access secrets in a called workflow) + with: + pypi_target: "pypi.org" + repo_release_ref: "main" diff --git a/.github/workflows/github-release.yml b/.github/workflows/github-release.yml new file mode 100644 index 0000000..e5e40c9 --- /dev/null +++ b/.github/workflows/github-release.yml @@ -0,0 +1,14 @@ +name: Github Release Publish +run-name: "Github Release Publish (tag=${{github.ref_name}})" + +on: + release: + types: [published] + +jobs: + publish-release: + uses: ./.github/workflows/publish-release.yml + secrets: inherit # pass all secrets (required to access secrets in a called workflow) + with: + pypi_target: "pypi.org" + repo_release_ref: ${{ github.ref_name }} diff --git a/.github/workflows/publish-docker.yml b/.github/workflows/publish-docker.yml new file mode 100644 index 0000000..092b6b3 --- /dev/null +++ b/.github/workflows/publish-docker.yml @@ -0,0 +1,79 @@ +name: Publish Docker +run-name: "Publish Docker (gitlint_version=${{ inputs.gitlint_version }})" + +on: + workflow_call: + inputs: + gitlint_version: + description: "Gitlint version to build docker image for" + required: true + type: string + docker_image_tag: + description: "Docker image tag" + required: true + type: string + push_to_dockerhub: + description: "Push to dockerhub.com" + required: false + type: boolean + default: false + workflow_dispatch: + inputs: + gitlint_version: + description: "Gitlint version to build docker image for" + type: string + docker_image_tag: + description: "Docker image tag" + required: true + type: choice + options: + - "latest_dev" + - "latest" + - "Use $gitlint_version" + default: "Use $gitlint_version" + push_to_dockerhub: + description: "Push to dockerhub.com" + required: false + type: boolean + default: false + +jobs: + publish_docker: + runs-on: "ubuntu-latest" + steps: + - name: Determine docker tag + id: set_tag + run: | + if [[ "${{ inputs.docker_image_tag }}" == "Use $gitlint_version" ]]; then + echo "docker_image_tag=${{ inputs.gitlint_version }}" >> $GITHUB_OUTPUT + else + echo "docker_image_tag=${{ inputs.docker_image_tag }}" >> $GITHUB_OUTPUT + fi + + - name: Login to Docker Hub + uses: docker/login-action@v2 + with: + username: jorisroovers + password: ${{ secrets.DOCKERHUB_TOKEN }} + + - name: Build docker image + uses: docker/build-push-action@v4 + with: + build-args: GITLINT_VERSION=${{ inputs.gitlint_version }} + tags: jorisroovers/gitlint:${{ steps.set_tag.outputs.docker_image_tag }} + + - name: Test docker image + run: | + gitlint_version=$(docker run --ulimit nofile=1024 -v $(pwd):/repo jorisroovers/gitlint:${{ steps.set_tag.outputs.docker_image_tag }} --version) + [ "$gitlint_version" == "gitlint, version ${{ inputs.gitlint_version }}" ] + + + # This won't actually rebuild the docker image, but just push the previously built and cached image + - name: Push docker image + uses: docker/build-push-action@v4 + with: + push: ${{ inputs.push_to_dockerhub }} + build-args: GITLINT_VERSION=${{ inputs.gitlint_version }} + tags: jorisroovers/gitlint:${{ steps.set_tag.outputs.docker_image_tag }} + if: inputs.push_to_dockerhub + \ No newline at end of file diff --git a/.github/workflows/publish-release.yml b/.github/workflows/publish-release.yml new file mode 100644 index 0000000..22ac4be --- /dev/null +++ b/.github/workflows/publish-release.yml @@ -0,0 +1,176 @@ +name: Publish Release +run-name: "Publish Release (pypi_target=${{ inputs.pypi_target }}, repo_release_ref=${{ inputs.repo_release_ref }})" + +on: + # Trigger release workflow from other workflows (e.g. release dev build as part of CI) + workflow_call: + inputs: + pypi_target: + description: "PyPI repository to publish to" + required: true + type: string + default: "test.pypi.org" + repo_release_ref: + description: "Gitlint git reference to publish release for" + type: string + default: "main" + + # Manually trigger a release + workflow_dispatch: + inputs: + pypi_target: + description: "PyPI repository to publish to" + required: true + type: choice + options: + - "pypi.org" + - "test.pypi.org" + default: "test.pypi.org" + repo_release_ref: + description: "Gitlint git reference to publish release for" + type: string + default: "main" + +jobs: + publish: + timeout-minutes: 15 + runs-on: "ubuntu-latest" + outputs: + gitlint_version: ${{ steps.set_version.outputs.gitlint_version }} + steps: + - name: Setup python + uses: actions/setup-python@v4.5.0 + with: + python-version: "3.11" + + - name: Install pypa/build + run: python -m pip install build==0.10.0 + + - name: Install Hatch + run: python -m pip install hatch==1.6.3 + + - uses: actions/checkout@v3.3.0 + with: + ref: ${{ inputs.repo_release_ref }} + fetch-depth: 0 # checkout all history, needed for hatch versioning + + # Run hatch version once to avoid additional output ("Setting up build environment for missing dependencies") + # during the next step + - name: Hatch version + run: hatch version + + # Hatch versioning is based on git (using hatch-vcs). If there is no explicit tag for the commit we're trying to + # publish, hatch versioning strings will have this format: 0.19.0.dev52+g9f7dc7d + # With the string after '+' being the 'g' of the commit. + # + # However, PyPI doesn't allow '+' in version numbers (no PEP440 local versions allowed on PyPI). + # To work around this, we override the version string by setting the SETUPTOOLS_SCM_PRETEND_VERSION env var + # to the version string without the '+' and everything after it. + # We do this by setting the `gitlint_version` step output here and re-using it later to + # set SETUPTOOLS_SCM_PRETEND_VERSION. + # + # We only actually publish such releases on the main branch to guarantee the dev numbering scheme remains + # unique. + # Note that when a tag *is* present (i.e. v0.19.0), hatch versioning will return the tag name (i.e. 0.19.0) + # and this step has no effect, ie. SETUPTOOLS_SCM_PRETEND_VERSION will be the same as `hatch version`. + - name: Set SETUPTOOLS_SCM_PRETEND_VERSION + id: set_version + run: | + echo "gitlint_version=$(hatch version | cut -d+ -f1)" >> $GITHUB_OUTPUT + + - name: Build (gitlint-core) + run: python -m build + working-directory: ./gitlint-core + env: + SETUPTOOLS_SCM_PRETEND_VERSION: ${{ steps.set_version.outputs.gitlint_version }} + + - name: Build (gitlint) + run: python -m build + env: + SETUPTOOLS_SCM_PRETEND_VERSION: ${{ steps.set_version.outputs.gitlint_version }} + + - name: Publish gitlint-core (pypi.org) + run: hatch publish + working-directory: ./gitlint-core + env: + HATCH_INDEX_USER: ${{ secrets.PYPI_GITLINT_CORE_USERNAME }} + HATCH_INDEX_AUTH: ${{ secrets.PYPI_GITLINT_CORE_PASSWORD }} + if: inputs.pypi_target == 'pypi.org' + + - name: Publish gitlint (pypi.org) + run: hatch publish + env: + HATCH_INDEX_USER: ${{ secrets.PYPI_GITLINT_USERNAME }} + HATCH_INDEX_AUTH: ${{ secrets.PYPI_GITLINT_PASSWORD }} + if: inputs.pypi_target == 'pypi.org' + + - name: Publish gitlint-core (test.pypi.org) + run: hatch publish -r test + working-directory: ./gitlint-core + env: + HATCH_INDEX_USER: ${{ secrets.TEST_PYPI_GITLINT_CORE_USERNAME }} + HATCH_INDEX_AUTH: ${{ secrets.TEST_PYPI_GITLINT_CORE_PASSWORD }} + if: inputs.pypi_target == 'test.pypi.org' + + - name: Publish gitlint (test.pypi.org) + run: hatch publish -r test + env: + HATCH_INDEX_USER: ${{ secrets.TEST_PYPI_GITLINT_USERNAME }} + HATCH_INDEX_AUTH: ${{ secrets.TEST_PYPI_GITLINT_PASSWORD }} + if: inputs.pypi_target == 'test.pypi.org' + + # Wait for gitlint package to be available in PyPI for installation + wait-for-package: + needs: + - publish + runs-on: "ubuntu-latest" + steps: + - name: Install gitlint + uses: nick-fields/retry@v2.8.3 + with: + timeout_minutes: 1 + max_attempts: 10 + command: | + python -m pip install gitlint==${{ needs.publish.outputs.gitlint_version }} + if: inputs.pypi_target == 'pypi.org' + + - name: Install gitlint (test.pypi.org) + uses: nick-fields/retry@v2.8.3 + with: + timeout_minutes: 1 + max_attempts: 10 + command: | + pip install --no-cache-dir -i https://test.pypi.org/simple/ --extra-index-url https://pypi.org/simple gitlint==${{ needs.publish.outputs.gitlint_version }} + if: inputs.pypi_target == 'test.pypi.org' + + - name: gitlint --version + run: | + gitlint --version + [ "$(gitlint --version)" == "gitlint, version ${{ needs.publish.outputs.gitlint_version }}" ] + + # Unfortunately, it's not because the newly published package installation worked once that replication + # has finished amongst all PyPI servers (subsequent installations might still fail). We sleep for 10 min here + # to increase the odds that replication has finished. + - name: Sleep + run: sleep 600 + + test-release: + needs: + - publish + - wait-for-package + uses: ./.github/workflows/test-release.yml + with: + gitlint_version: ${{ needs.publish.outputs.gitlint_version }} + pypi_source: ${{ inputs.pypi_target }} + repo_test_ref: ${{ inputs.repo_release_ref }} + + publish-docker: + needs: + - publish + - test-release + uses: ./.github/workflows/publish-docker.yml + secrets: inherit # pass all secrets (required to access secrets in a called workflow) + with: + gitlint_version: ${{ needs.publish.outputs.gitlint_version }} + docker_image_tag: "latest_dev" + push_to_dockerhub: true diff --git a/.github/workflows/test-release.yml b/.github/workflows/test-release.yml new file mode 100644 index 0000000..caf00dd --- /dev/null +++ b/.github/workflows/test-release.yml @@ -0,0 +1,95 @@ +name: Test Release +run-name: "Test Release (${{ inputs.gitlint_version }}, pypi_source=${{ inputs.pypi_source }}, repo_test_ref=${{ inputs.repo_test_ref }})" +on: + workflow_call: + inputs: + gitlint_version: + description: "Gitlint version to test" + required: true + default: "0.18.0" + type: string + pypi_source: + description: "PyPI repository to use" + required: true + type: string + repo_test_ref: + description: "Git reference to checkout for integration tests" + default: "main" + type: string + workflow_dispatch: + inputs: + gitlint_version: + description: "Gitlint version to test" + required: true + default: "0.18.0" + pypi_source: + description: "PyPI repository to use" + required: true + type: choice + options: + - "pypi.org" + - "test.pypi.org" + default: "pypi.org" + repo_test_ref: + description: "Git reference to checkout for integration tests" + default: "main" + +jobs: + test-release: + timeout-minutes: 10 + runs-on: "ubuntu-latest" + strategy: + matrix: + python-version: ["3.7", "3.8", "3.9", "3.10", "3.11", pypy-3.9] + os: ["macos-latest", "ubuntu-latest", "windows-latest"] + steps: + - name: Setup python + uses: actions/setup-python@v4.5.0 + with: + python-version: ${{ matrix.python-version }} + + - name: Install Hatch + run: python -m pip install hatch==1.6.3 + + - name: Install gitlint + run: | + python -m pip install gitlint==${{ inputs.gitlint_version }} + if: inputs.pypi_source == 'pypi.org' + + - name: Install gitlint (test.pypi.org) + run: | + pip install --no-cache-dir -i https://test.pypi.org/simple/ --extra-index-url https://pypi.org/simple gitlint==${{ inputs.gitlint_version }} + if: inputs.pypi_source == 'test.pypi.org' + + - name: gitlint --version + run: | + gitlint --version + [ "$(gitlint --version)" == "gitlint, version ${{ inputs.gitlint_version }}" ] + + - uses: actions/checkout@v3.3.0 + with: + ref: ${{ inputs.repo_test_ref }} + + - name: Integration tests (default -> GITLINT_USE_SH_LIB=1) + run: | + hatch run qa:integration-tests + if: matrix.os != 'windows-latest' + + - name: Integration tests (GITLINT_USE_SH_LIB=1) + run: | + hatch run qa:integration-tests + env: + GITLINT_USE_SH_LIB: 1 + if: matrix.os != 'windows-latest' + + - name: Integration tests (GITLINT_QA_USE_SH_LIB=0) + run: | + hatch run qa:integration-tests -k "not(test_commit_hook_continue or test_commit_hook_abort or test_commit_hook_edit)" qa + env: + GITLINT_QA_USE_SH_LIB: 0 + if: matrix.os != 'windows-latest' + + - name: Integration tests (Windows) + run: | + hatch run qa:integration-tests -k "not (test_commit_hook_continue or test_commit_hook_abort or test_commit_hook_edit or test_lint_staged_stdin or test_stdin_file or test_stdin_pipe_empty)" qa + if: matrix.os == 'windows-latest' -- cgit v1.2.3