Update to Fast API 0.139 #771
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: ci | |
| on: | |
| pull_request: | |
| push: | |
| branches: [develop, main] | |
| tags: ["[0-9]+.[0-9]+.[0-9]+*"] | |
| workflow_dispatch: | |
| inputs: | |
| generate_changelog: | |
| description: Run the changelog generation job | |
| type: boolean | |
| default: false | |
| publish_to_pypi: | |
| description: Publish Python package to PyPI | |
| type: boolean | |
| default: false | |
| permissions: | |
| contents: read | |
| env: | |
| DOCKER_BUILDKIT: "1" | |
| HATCH_ENV_TYPE_VIRTUAL_PATH: ".venv" | |
| HATCH_ENV: "ci" | |
| HATCH_VERSION: ">=1.17,<1.18" | |
| PIPX_VERSION: ">=1.16,<1.17" | |
| REPO_NAME: inboard | |
| jobs: | |
| python: | |
| runs-on: ubuntu-latest | |
| strategy: | |
| matrix: | |
| python-version: ["3.10", "3.11", "3.12", "3.13"] | |
| steps: | |
| - uses: actions/checkout@v6 | |
| - uses: actions/setup-python@v6 | |
| with: | |
| python-version: ${{ matrix.python-version }} | |
| - name: Set up pip cache | |
| if: runner.os == 'Linux' | |
| uses: actions/cache@v5 | |
| with: | |
| path: ~/.cache/pip | |
| key: ${{ runner.os }}-pip-${{ hashFiles('pyproject.toml') }} | |
| restore-keys: ${{ runner.os }}-pip- | |
| - name: Install pipx for Python ${{ matrix.python-version }} | |
| run: python -m pip install "pipx$PIPX_VERSION" | |
| - name: Install Hatch | |
| run: pipx install "hatch$HATCH_VERSION" | |
| - name: Install dependencies | |
| run: hatch env create ${{ env.HATCH_ENV }} | |
| - name: Test virtualenv location | |
| run: | | |
| EXPECTED_VIRTUALENV_PATH="$GITHUB_WORKSPACE/$HATCH_ENV_TYPE_VIRTUAL_PATH" | |
| INSTALLED_VIRTUALENV_PATH=$(hatch env find) | |
| echo "The virtualenv should be at $EXPECTED_VIRTUALENV_PATH." | |
| echo "Hatch is using a virtualenv at $INSTALLED_VIRTUALENV_PATH." | |
| case "$INSTALLED_VIRTUALENV_PATH" in | |
| "$EXPECTED_VIRTUALENV_PATH") echo "Correct Hatch virtualenv." ;; | |
| *) echo "Incorrect Hatch virtualenv." && exit 1 ;; | |
| esac | |
| - name: Test that Git tag version and Python package version match | |
| if: github.ref_type == 'tag' && matrix.python-version == '3.13' | |
| run: | | |
| GIT_TAG_VERSION=$GITHUB_REF_NAME | |
| PACKAGE_VERSION=$(hatch version) | |
| echo "The Python package version is $PACKAGE_VERSION." | |
| echo "The Git tag version is $GIT_TAG_VERSION." | |
| if [ "$PACKAGE_VERSION" = "$GIT_TAG_VERSION" ]; then | |
| echo "Versions match." | |
| else | |
| echo "Versions do not match." && exit 1 | |
| fi | |
| - name: Run Hatch script for code quality checks | |
| run: hatch run ${{ env.HATCH_ENV }}:check | |
| - name: Run tests | |
| run: | | |
| hatch run ${{ env.HATCH_ENV }}:coverage run | |
| coverage_files_after_run=$(find . -name '.coverage*' | wc -l) | |
| sleep_time=10 | |
| sleep "$sleep_time" | |
| coverage_files_after_sleep=$(find . -name '.coverage*' | wc -l) | |
| echo "[INFO] Verifying that coverage.py has stopped generating .coverage files. | |
| [INFO] Number of coverage files after coverage run: $coverage_files_after_run | |
| [INFO] Number of coverage files after $sleep_time second sleep: $coverage_files_after_sleep | |
| " | |
| if [ "$coverage_files_after_sleep" -gt "$coverage_files_after_run" ]; then | |
| echo "[ERROR] Unexpected .coverage files detected." | |
| exit 1 | |
| fi | |
| timeout-minutes: 8 | |
| - name: Enforce test coverage | |
| run: | | |
| hatch run ${{ env.HATCH_ENV }}:coverage combine -q | |
| hatch run ${{ env.HATCH_ENV }}:coverage report | |
| - name: Build Python package | |
| run: hatch build | |
| - name: Upload Python package artifacts | |
| if: github.ref_type == 'tag' && matrix.python-version == '3.13' | |
| uses: actions/upload-artifact@v7 | |
| with: | |
| if-no-files-found: error | |
| name: ${{ env.REPO_NAME }}-${{ github.ref_name }} | |
| path: dist | |
| docker: | |
| runs-on: ubuntu-latest | |
| needs: [python] | |
| permissions: | |
| packages: write | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| linux-version: ["alpine", "trixie", "slim-trixie"] | |
| python-version: ["3.10", "3.11", "3.12", "3.13"] | |
| steps: | |
| - uses: actions/checkout@v6 | |
| - uses: actions/setup-python@v6 | |
| with: | |
| python-version: ${{ matrix.python-version }} | |
| - name: Set up versions and Docker tags for Python and Alpine Linux | |
| id: setup | |
| run: | | |
| LINUX_VERSION=${{ matrix.linux-version }} | |
| linux_version_without_debian_release_name="${LINUX_VERSION/trixie/}" | |
| linux_tag="${linux_version_without_debian_release_name%-}" | |
| LINUX_TAG="${linux_tag:+-$linux_tag}" | |
| PYTHON_VERSION=${{ matrix.python-version }} | |
| PYTHON_TAG="-python$PYTHON_VERSION" | |
| echo "LINUX_VERSION=$LINUX_VERSION" >> $GITHUB_ENV | |
| echo "LINUX_TAG=$LINUX_TAG" >> $GITHUB_ENV | |
| echo "PYTHON_VERSION=$PYTHON_VERSION" >> $GITHUB_ENV | |
| echo "PYTHON_TAG=$PYTHON_TAG" >> $GITHUB_ENV | |
| - name: Build Docker images | |
| run: | | |
| docker build . --rm --target base \ | |
| --build-arg BUILDKIT_INLINE_CACHE=1 \ | |
| --build-arg HATCH_VERSION="$HATCH_VERSION" \ | |
| --build-arg LINUX_VERSION="$LINUX_VERSION" \ | |
| --build-arg PIPX_VERSION="$PIPX_VERSION" \ | |
| --build-arg PYTHON_VERSION="$PYTHON_VERSION" \ | |
| --cache-from ghcr.io/br3ndonland/inboard \ | |
| -t ghcr.io/br3ndonland/inboard:base"$LINUX_TAG" | |
| docker build . --rm --target starlette \ | |
| --build-arg BUILDKIT_INLINE_CACHE=1 \ | |
| --build-arg HATCH_VERSION="$HATCH_VERSION" \ | |
| --build-arg LINUX_VERSION="$LINUX_VERSION" \ | |
| --build-arg PIPX_VERSION="$PIPX_VERSION" \ | |
| --build-arg PYTHON_VERSION="$PYTHON_VERSION" \ | |
| -t ghcr.io/br3ndonland/inboard:starlette"$LINUX_TAG" | |
| docker build . --rm --target fastapi \ | |
| --build-arg BUILDKIT_INLINE_CACHE=1 \ | |
| --build-arg HATCH_VERSION="$HATCH_VERSION" \ | |
| --build-arg LINUX_VERSION="$LINUX_VERSION" \ | |
| --build-arg PIPX_VERSION="$PIPX_VERSION" \ | |
| --build-arg PYTHON_VERSION="$PYTHON_VERSION" \ | |
| -t ghcr.io/br3ndonland/inboard:fastapi"$LINUX_TAG" | |
| - name: Smoke test Docker containers | |
| run: | | |
| handle_error_code() { | |
| case "$1" in | |
| 2) : "Request timed out" ;; | |
| 3) : "Unexpected HTTP 3xx redirection" ;; | |
| 4) : "HTTP 4xx client error" ;; | |
| 5) : "HTTP 5xx server error" ;; | |
| 6) : "Exceeded max number of redirects" ;; | |
| *) : "Other error code $1" ;; | |
| esac | |
| echo "[ERROR] error code: $_" >&2 | |
| return "$1" | |
| } | |
| smoke_test() { | |
| echo "[INFO] Running smoke test of $*." | |
| if curl --fail --max-time 5 --no-keepalive --no-progress-meter "$@"; then | |
| echo | |
| echo "[INFO] Smoke test of $* passed." | |
| else | |
| local error_code="$?" | |
| echo | |
| echo "[ERROR] Smoke test of $* failed." >&2 | |
| handle_error_code "$error_code" | |
| fi | |
| } | |
| smoke_test_xfail() { | |
| echo "[INFO] Running smoke test of $* that is expected to fail." | |
| if ! curl --fail --max-time 5 --no-keepalive --no-progress-meter "$@"; then | |
| echo | |
| echo "[INFO] Smoke test of $* expected to fail." | |
| else | |
| echo | |
| echo "[ERROR] Smoke test of $* should have failed!" >&2 | |
| return 1 | |
| fi | |
| } | |
| test_gunicorn_in_docker() { | |
| local container_name=$1 expected_message | |
| local -i worker_count | |
| echo "[INFO] Docker container logs from $container_name:" | |
| docker logs "$container_name" | |
| if [[ $container_name == *asgi ]]; then | |
| expected_message="Using worker: asgi" | |
| else | |
| expected_message="Using worker:" | |
| fi | |
| grep -q "$expected_message" <(docker logs "$container_name") | |
| echo "[INFO] Gunicorn control interface (gunicornc) stats from $container_name:" | |
| docker exec "$container_name" gunicornc -c "show stats" | |
| worker_count=$(docker exec "$container_name" gunicornc -c "show stats" -j | jq -r '.workers_current') | |
| if [ $worker_count -lt 1 ]; then | |
| echo "[ERROR] Gunicorn control interface (gunicornc) reports $worker_count workers spawned." >&2 | |
| return 1 | |
| fi | |
| } | |
| test_virtualenv_location_in_docker() { | |
| local container_name=$1 docker_virtualenv docker_python expected_virtualenv expected_python | |
| expected_virtualenv="/app/$HATCH_ENV_TYPE_VIRTUAL_PATH" | |
| expected_python="$expected_virtualenv/bin/python" | |
| echo "[INFO] The Hatch virtualenv should be at $expected_virtualenv." | |
| echo "[INFO] The Python executable should be at $expected_python." | |
| docker_virtualenv=$(docker exec "$container_name" hatch env find) | |
| docker_python=$(docker exec "$container_name" which python) | |
| case "$docker_virtualenv" in | |
| "$expected_virtualenv") echo "[INFO] Correct Hatch virtualenv $docker_virtualenv for $container_name." ;; | |
| *) echo "[ERROR] Incorrect Hatch virtualenv $docker_virtualenv for $container_name." >&2 && return 1 ;; | |
| esac | |
| case "$docker_python" in | |
| "$expected_python") echo "[INFO] Correct Python $docker_python for $container_name." ;; | |
| *) echo "[ERROR] Incorrect Python $docker_python for $container_name." >&2 && return 1 ;; | |
| esac | |
| } | |
| main() { | |
| local container_name=$1 container_tag worker_class | |
| local -i host_port=10101 | |
| echo "[INFO] Testing $container_name." | |
| echo | |
| container_tag=$(echo "$container_name" | cut -d - -f 2) | |
| [[ $container_name == *asgi ]] && worker_class=asgi | |
| docker run -d -p $host_port:80 --name "$container_name" \ | |
| -e "BASIC_AUTH_USERNAME=test_user" \ | |
| -e "BASIC_AUTH_PASSWORD=r4ndom_bUt_memorable" \ | |
| -e "LOG_FORMAT=gunicorn" \ | |
| -e "LOG_LEVEL=debug" \ | |
| ${worker_class:+-e "WORKER_CLASS=asgi"} \ | |
| ghcr.io/br3ndonland/inboard:"$container_tag$LINUX_TAG" | |
| sleep 5 | |
| test_virtualenv_location_in_docker "$container_name" | |
| test_gunicorn_in_docker "$container_name" | |
| smoke_test http://localhost:$host_port | |
| if [[ $container_name == *fastapi* || $container_name == *starlette* ]]; then | |
| smoke_test --user test_user:r4ndom_bUt_memorable http://localhost:$host_port/status | |
| smoke_test_xfail --user test_user:incorrect_password http://localhost:$host_port/status | |
| smoke_test_xfail http://localhost:$host_port/status | |
| fi | |
| docker stop "$container_name" | |
| } | |
| container_names=( | |
| inboard-base | |
| inboard-starlette | |
| inboard-fastapi | |
| inboard-base-gunicorn-asgi | |
| inboard-starlette-gunicorn-asgi | |
| inboard-fastapi-gunicorn-asgi | |
| ) | |
| for container_name in "${container_names[@]}"; do | |
| main "$container_name" | |
| done | |
| - name: Log in to Docker registry | |
| if: > | |
| github.ref_type == 'tag' || | |
| github.ref == 'refs/heads/develop' || | |
| github.ref == 'refs/heads/main' | |
| run: | | |
| echo ${{ secrets.GITHUB_TOKEN }} | docker login ghcr.io \ | |
| -u ${{ github.actor }} --password-stdin | |
| - name: Tag and push Docker images with latest tags | |
| if: > | |
| matrix.python-version == '3.13' && | |
| ( | |
| github.ref_type == 'tag' || | |
| github.ref == 'refs/heads/develop' || | |
| github.ref == 'refs/heads/main' | |
| ) | |
| run: | | |
| docker push ghcr.io/br3ndonland/inboard:base"$LINUX_TAG" | |
| docker push ghcr.io/br3ndonland/inboard:starlette"$LINUX_TAG" | |
| docker push ghcr.io/br3ndonland/inboard:fastapi"$LINUX_TAG" | |
| docker tag \ | |
| ghcr.io/br3ndonland/inboard:fastapi"$LINUX_TAG" \ | |
| ghcr.io/br3ndonland/inboard:latest"$LINUX_TAG" | |
| docker push ghcr.io/br3ndonland/inboard:latest"$LINUX_TAG" | |
| - name: Tag and push Docker images with Python version | |
| if: github.ref_type == 'tag' || github.ref == 'refs/heads/main' | |
| run: | | |
| docker tag \ | |
| ghcr.io/br3ndonland/inboard:base"$LINUX_TAG" \ | |
| ghcr.io/br3ndonland/inboard:base"$PYTHON_TAG$LINUX_TAG" | |
| docker tag \ | |
| ghcr.io/br3ndonland/inboard:starlette"$LINUX_TAG" \ | |
| ghcr.io/br3ndonland/inboard:starlette"$PYTHON_TAG$LINUX_TAG" | |
| docker tag \ | |
| ghcr.io/br3ndonland/inboard:fastapi"$LINUX_TAG" \ | |
| ghcr.io/br3ndonland/inboard:fastapi"$PYTHON_TAG$LINUX_TAG" | |
| docker push ghcr.io/br3ndonland/inboard:base"$PYTHON_TAG$LINUX_TAG" | |
| docker push ghcr.io/br3ndonland/inboard:starlette"$PYTHON_TAG$LINUX_TAG" | |
| docker push ghcr.io/br3ndonland/inboard:fastapi"$PYTHON_TAG$LINUX_TAG" | |
| - name: Tag and push Docker images with Git tag | |
| if: github.ref_type == 'tag' | |
| run: | | |
| GIT_TAG_FULL=${{ github.ref_name }} | |
| GIT_TAG_MAJOR_MINOR=$(echo "$GIT_TAG_FULL" | cut -d '.' -f 1-2) | |
| for GIT_TAG in "$GIT_TAG_FULL" "$GIT_TAG_MAJOR_MINOR"; do | |
| docker tag \ | |
| ghcr.io/br3ndonland/inboard:"base$LINUX_TAG" \ | |
| ghcr.io/br3ndonland/inboard:"base-$GIT_TAG$LINUX_TAG" | |
| docker tag \ | |
| ghcr.io/br3ndonland/inboard:"starlette$LINUX_TAG" \ | |
| ghcr.io/br3ndonland/inboard:"starlette-$GIT_TAG$LINUX_TAG" | |
| docker tag \ | |
| ghcr.io/br3ndonland/inboard:"fastapi$LINUX_TAG" \ | |
| ghcr.io/br3ndonland/inboard:"fastapi-$GIT_TAG$LINUX_TAG" | |
| docker tag \ | |
| ghcr.io/br3ndonland/inboard:"base$LINUX_TAG" \ | |
| ghcr.io/br3ndonland/inboard:"base-$GIT_TAG$PYTHON_TAG$LINUX_TAG" | |
| docker tag \ | |
| ghcr.io/br3ndonland/inboard:"starlette$LINUX_TAG" \ | |
| ghcr.io/br3ndonland/inboard:"starlette-$GIT_TAG$PYTHON_TAG$LINUX_TAG" | |
| docker tag \ | |
| ghcr.io/br3ndonland/inboard:"fastapi$LINUX_TAG" \ | |
| ghcr.io/br3ndonland/inboard:"fastapi-$GIT_TAG$PYTHON_TAG$LINUX_TAG" | |
| docker tag \ | |
| ghcr.io/br3ndonland/inboard:"base$LINUX_TAG" \ | |
| ghcr.io/br3ndonland/inboard:"$GIT_TAG-base$LINUX_TAG" | |
| docker tag \ | |
| ghcr.io/br3ndonland/inboard:"starlette$LINUX_TAG" \ | |
| ghcr.io/br3ndonland/inboard:"$GIT_TAG-starlette$LINUX_TAG" | |
| docker tag \ | |
| ghcr.io/br3ndonland/inboard:"fastapi$LINUX_TAG" \ | |
| ghcr.io/br3ndonland/inboard:"$GIT_TAG-fastapi$LINUX_TAG" | |
| docker tag \ | |
| ghcr.io/br3ndonland/inboard:"base$LINUX_TAG" \ | |
| ghcr.io/br3ndonland/inboard:"$GIT_TAG-base$PYTHON_TAG$LINUX_TAG" | |
| docker tag \ | |
| ghcr.io/br3ndonland/inboard:"starlette$LINUX_TAG" \ | |
| ghcr.io/br3ndonland/inboard:"$GIT_TAG-starlette$PYTHON_TAG$LINUX_TAG" | |
| docker tag \ | |
| ghcr.io/br3ndonland/inboard:"fastapi$LINUX_TAG" \ | |
| ghcr.io/br3ndonland/inboard:"$GIT_TAG-fastapi$PYTHON_TAG$LINUX_TAG" | |
| docker push ghcr.io/br3ndonland/inboard:"base-$GIT_TAG$LINUX_TAG" | |
| docker push ghcr.io/br3ndonland/inboard:"starlette-$GIT_TAG$LINUX_TAG" | |
| docker push ghcr.io/br3ndonland/inboard:"fastapi-$GIT_TAG$LINUX_TAG" | |
| docker push ghcr.io/br3ndonland/inboard:"base-$GIT_TAG$PYTHON_TAG$LINUX_TAG" | |
| docker push ghcr.io/br3ndonland/inboard:"starlette-$GIT_TAG$PYTHON_TAG$LINUX_TAG" | |
| docker push ghcr.io/br3ndonland/inboard:"fastapi-$GIT_TAG$PYTHON_TAG$LINUX_TAG" | |
| docker push ghcr.io/br3ndonland/inboard:"$GIT_TAG-base$LINUX_TAG" | |
| docker push ghcr.io/br3ndonland/inboard:"$GIT_TAG-starlette$LINUX_TAG" | |
| docker push ghcr.io/br3ndonland/inboard:"$GIT_TAG-fastapi$LINUX_TAG" | |
| docker push ghcr.io/br3ndonland/inboard:"$GIT_TAG-base$PYTHON_TAG$LINUX_TAG" | |
| docker push ghcr.io/br3ndonland/inboard:"$GIT_TAG-starlette$PYTHON_TAG$LINUX_TAG" | |
| docker push ghcr.io/br3ndonland/inboard:"$GIT_TAG-fastapi$PYTHON_TAG$LINUX_TAG" | |
| done | |
| docker-cleanup: | |
| environment: | |
| name: Production | |
| deployment: false | |
| if: github.ref_type == 'tag' || github.ref == 'refs/heads/main' | |
| needs: [python, docker] | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: dataaxiom/ghcr-cleanup-action@v1 | |
| with: | |
| delete-untagged: true | |
| token: ${{ secrets.GH_PAT }} | |
| pypi: | |
| environment: | |
| name: PyPI | |
| url: https://pypi.org/project/${{ env.REPO_NAME }}/${{ github.ref_name }} | |
| if: >- | |
| (github.event_name == 'push' && github.ref_type == 'tag') || | |
| (github.event_name == 'workflow_dispatch' && inputs.publish_to_pypi == true) | |
| needs: [python, docker] | |
| permissions: | |
| id-token: write | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: Download Python package artifacts | |
| uses: actions/download-artifact@v8 | |
| with: | |
| merge-multiple: true | |
| name: ${{ env.REPO_NAME }}-${{ github.ref_name }} | |
| path: dist | |
| - name: Publish Python package to PyPI | |
| uses: pypa/gh-action-pypi-publish@cef221092ed1bacb1cc03d23a2d87d1d172e277b # v1.14.0 | |
| changelog: | |
| environment: | |
| name: Production | |
| deployment: false | |
| if: >- | |
| (github.event_name == 'push' && github.ref_type == 'tag') || | |
| (github.event_name == 'workflow_dispatch' && inputs.generate_changelog == true) | |
| needs: [python, docker] | |
| permissions: | |
| contents: write | |
| pull-requests: write | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@v6 | |
| with: | |
| fetch-depth: 0 | |
| ref: develop | |
| - name: Generate changelog from Git tags | |
| run: | | |
| echo '--- | |
| icon: lucide/clipboard-clock | |
| --- | |
| # Changelog | |
| ' >docs/changelog.md | |
| GIT_LOG_FORMAT='## %(subject) - %(taggerdate:short) | |
| %(contents:body)' | |
| git tag -l --sort=-taggerdate:iso --format="$GIT_LOG_FORMAT" >>docs/changelog.md | |
| - name: Fix changelog | |
| run: | | |
| # Fix changelog | |
| # | |
| # The previous step in the GitHub Actions job generates a changelog | |
| # from Git tag messages and writes the output to Markdown documents. | |
| # https://github.com/br3ndonland/inboard/commit/b15efff7fc45759983743411fcbbd52415eb5455 | |
| # | |
| # Some post-processing of these Git tag messages may be necessary in order | |
| # for them to render properly from the Markdown documents. One reason for | |
| # this post-processing is to handle "dunders" (double underscores). | |
| # | |
| # Dunder names like `__init__` have special meaning in Python. | |
| # https://docs.python.org/3/reference/datamodel.html#specialnames | |
| # https://docs.python.org/3/reference/lexical_analysis.html | |
| # | |
| # Dunders also make text bold in Markdown unless escaped with backslashes | |
| # or enclosed in backticks. When the document is transformed to HTML, the | |
| # backticks are transformed to HTML code elements. | |
| # | |
| # Some early changelog entries in this project did not enclose dunders in | |
| # backticks. When the text from these entries is formatted as Markdown and | |
| # rendered, text within dunders like `__init__` shows up as "init" in bold | |
| # because Markdown parsers read it as equivalent to `**init**`. To avoid | |
| # having these dunder names converted to bold text, the GitHub Actions job | |
| # runs a `sed` command to escape the dunders, like \_\_init\_\_. | |
| # | |
| # The changelog entry for the update to Gunicorn 23.0.0 mentions a | |
| # security vulnerability that was fixed, but this vulnerability was | |
| # actually fixed in Gunicorn 22.0.0 and described in the changelog | |
| # for inboard 0.68.0. This step removes the duplicate info. | |
| # https://github.com/br3ndonland/inboard/pull/117 | |
| ESCAPE_DUNDERS='s:(\s|\/)(__)(all|init|token)(__)(\s|\.py|\(\)){0,1}:\1\\_\\_\3\\_\\_\5:g' | |
| REPLACEMENT='There are several breaking changes noted in the\n[Gunicorn changelog](https://gunicorn.org/news/).' | |
| sed -Ei "$ESCAPE_DUNDERS" "docs/changelog.md" | |
| sed -Ei \ | |
| -e "s|\[Changes\]\(https://docs.gunicorn.org/en/latest/news.html\) include|$REPLACEMENT|g" \ | |
| -e "s|a fix for a high-severity security vulnerability \(CVE-2024-1135,||g" \ | |
| -e "s|\[GHSA-w3h3-4rj7-4ph4\]\(https://github.com/advisories/GHSA-w3h3-4rj7-4ph4\)\)\.||g" \ | |
| -e "s|There are several breaking changes noted in the Gunicorn changelog\.||g" \ | |
| "docs/changelog.md" | |
| sed -Ei -z "s|\n\n\n||g" "docs/changelog.md" | |
| sed -Ei "s|because that the|because the|g" "docs/changelog.md" | |
| sed -Ei "s|Update to FastAPI 0.132$|**Update to FastAPI 0.132** (78d137c30911901aaa6faf50d522a11a3b3988d7)|g" "docs/changelog.md" | |
| - name: Format changelog with Prettier | |
| run: npx -s -y prettier@'^3' --write docs/changelog.md | |
| - name: Set PR and commit title | |
| id: set-title | |
| run: | | |
| if [ "$GITHUB_REF_TYPE" = 'tag' ]; then | |
| title="Update changelog for version $GITHUB_REF_NAME" | |
| else | |
| most_recent_tag=$(git describe --abbrev=0 --tags) | |
| title="Update changelog for version $most_recent_tag" | |
| fi | |
| echo "title=$title" >>"$GITHUB_OUTPUT" | |
| - name: Create pull request with updated changelog | |
| uses: peter-evans/create-pull-request@v8 | |
| with: | |
| add-paths: | | |
| docs/changelog.md | |
| body: | | |
| Automated changes by [create-pull-request](https://github.com/peter-evans/create-pull-request) GitHub action | |
| [skip ci] | |
| branch: create-pull-request/${{ github.ref_name }} | |
| commit-message: | | |
| ${{ steps.set-title.outputs.title }} | |
| [skip ci] | |
| sign-commits: true | |
| title: ${{ steps.set-title.outputs.title }} |