diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml index 4c8e2f92..8be2b791 100644 --- a/.github/workflows/codeql.yml +++ b/.github/workflows/codeql.yml @@ -41,7 +41,7 @@ jobs: steps: - name: Harden Runner - uses: step-security/harden-runner@1b05615854632b887b69ae1be8cbefe72d3ae423 # v2.6.0 + uses: step-security/harden-runner@63c24ba6bd7ba022e95695ff85de572c04a18142 # v2.7.0 with: disable-sudo: true egress-policy: block @@ -53,11 +53,11 @@ jobs: objects.githubusercontent.com:443 - name: Checkout repository - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 + uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4 # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL - uses: github/codeql-action/init@74483a38d39275f33fcff5f35b679b5ca4a26a99 # v2.22.5 + uses: github/codeql-action/init@d39d31e687223d841ef683f52467bd88e9b21c14 # v3.25.3 with: languages: ${{ matrix.language }} # If you wish to specify custom queries, you can do so here or in a config file. @@ -67,7 +67,7 @@ jobs: # Autobuild attempts to build any compiled languages (C/C++, C#, or Java). # If this step fails, then you should remove it and run the build manually (see below) - name: Autobuild - uses: github/codeql-action/autobuild@74483a38d39275f33fcff5f35b679b5ca4a26a99 # v2.22.5 + uses: github/codeql-action/autobuild@d39d31e687223d841ef683f52467bd88e9b21c14 # v3.25.3 # â„šī¸ Command-line programs to run using the OS shell. # 📚 See https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsrun @@ -80,6 +80,6 @@ jobs: # ./location_of_script_within_repo/buildscript.sh - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@74483a38d39275f33fcff5f35b679b5ca4a26a99 # v2.22.5 + uses: github/codeql-action/analyze@d39d31e687223d841ef683f52467bd88e9b21c14 # v3.25.3 with: category: "/language:${{matrix.language}}" diff --git a/.github/workflows/conformance.yml b/.github/workflows/conformance.yml index 886b65f7..80ad8afb 100644 --- a/.github/workflows/conformance.yml +++ b/.github/workflows/conformance.yml @@ -16,7 +16,7 @@ jobs: python: ['3.7', '3.8', '3.9', '3.10', '3.11', '3.12'] steps: - name: Harden Runner - uses: step-security/harden-runner@1b05615854632b887b69ae1be8cbefe72d3ae423 # v2.6.0 + uses: step-security/harden-runner@63c24ba6bd7ba022e95695ff85de572c04a18142 # v2.7.0 with: disable-sudo: true egress-policy: block @@ -30,10 +30,10 @@ jobs: storage.googleapis.com:443 - name: Checkout code - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 + uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4 - name: Setup Python - uses: actions/setup-python@65d7f2d534ac1bc67fcd62888c5f4f3d2cb2b236 # v4.7.1 + uses: actions/setup-python@82c7e631bb3cdc910f68e0081d67478d79c6982d # v5.1.0 with: python-version: ${{ matrix.python }} @@ -41,7 +41,7 @@ jobs: run: python -m pip install -e . - name: Setup Go - uses: actions/setup-go@93397bea11091df50f3d7e59dc26a7711a8bcfbe # v4.1.0 + uses: actions/setup-go@0c52d547c9bc32b1aa3301fd7a9cb496313a4491 # v5.0.0 with: go-version: '1.20' diff --git a/.github/workflows/dependency-review.yml b/.github/workflows/dependency-review.yml index 088ebccf..a79373ca 100644 --- a/.github/workflows/dependency-review.yml +++ b/.github/workflows/dependency-review.yml @@ -17,7 +17,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Harden Runner - uses: step-security/harden-runner@1b05615854632b887b69ae1be8cbefe72d3ae423 # v2.6.0 + uses: step-security/harden-runner@63c24ba6bd7ba022e95695ff85de572c04a18142 # v2.7.0 with: disable-sudo: true egress-policy: block @@ -25,6 +25,6 @@ jobs: api.github.com:443 github.com:443 - name: 'Checkout Repository' - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 + uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4 - name: 'Dependency Review' - uses: actions/dependency-review-action@6c5ccdad469c9f8a2996bfecaec55a631a347034 # v3.1.0 + uses: actions/dependency-review-action@5bbc3ba658137598168acb2ab73b21c432dd411b # v4.2.5 diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index a504c985..d560d95f 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -12,7 +12,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Harden Runner - uses: step-security/harden-runner@1b05615854632b887b69ae1be8cbefe72d3ae423 # v2.6.0 + uses: step-security/harden-runner@63c24ba6bd7ba022e95695ff85de572c04a18142 # v2.7.0 with: disable-sudo: true egress-policy: block @@ -21,9 +21,9 @@ jobs: github.com:443 pypi.org:443 - - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 + - uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4 - name: Setup Python - uses: actions/setup-python@65d7f2d534ac1bc67fcd62888c5f4f3d2cb2b236 # v4.7.1 + uses: actions/setup-python@82c7e631bb3cdc910f68e0081d67478d79c6982d # v5.1.0 - name: Install tox run: python -m pip install tox - name: Lint diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 65779b28..63b9f7f8 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -13,22 +13,22 @@ jobs: runs-on: ubuntu-latest steps: - name: Harden Runner - uses: step-security/harden-runner@1b05615854632b887b69ae1be8cbefe72d3ae423 # v2.6.0 + uses: step-security/harden-runner@63c24ba6bd7ba022e95695ff85de572c04a18142 # v2.7.0 with: egress-policy: audit # TODO: change to 'egress-policy: block' after couple of runs - name: Checkout - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 + uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4 with: ref: ${{ github.event.release.tag_name }} - name: Install Python - uses: actions/setup-python@65d7f2d534ac1bc67fcd62888c5f4f3d2cb2b236 # v4.7.1 + uses: actions/setup-python@82c7e631bb3cdc910f68e0081d67478d79c6982d # v5.1.0 - name: Install build dependencies run: python -m pip install -U setuptools build wheel - name: Build distributions run: python -m build - name: Publish - uses: pypa/gh-action-pypi-publish@79739dc2f2bf6bcfd21ecf9af9f06bd643dbeeae # main + uses: pypa/gh-action-pypi-publish@c12cc61414480c03e10ea76e2a0a1a17d6c764e2 # main with: user: __token__ password: ${{ secrets.PYPI_API_TOKEN }} diff --git a/.github/workflows/scorecard.yml b/.github/workflows/scorecard.yml index 7130693e..150d7e49 100644 --- a/.github/workflows/scorecard.yml +++ b/.github/workflows/scorecard.yml @@ -26,7 +26,7 @@ jobs: steps: - name: Harden Runner - uses: step-security/harden-runner@1b05615854632b887b69ae1be8cbefe72d3ae423 # v2.6.0 + uses: step-security/harden-runner@63c24ba6bd7ba022e95695ff85de572c04a18142 # v2.7.0 with: disable-sudo: true egress-policy: block @@ -44,7 +44,7 @@ jobs: - name: "Checkout code" - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 + uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4 with: persist-credentials: false @@ -61,6 +61,6 @@ jobs: # Upload the results to GitHub's code scanning dashboard. - name: "Upload to code-scanning" - uses: github/codeql-action/upload-sarif@74483a38d39275f33fcff5f35b679b5ca4a26a99 # v2.22.5 + uses: github/codeql-action/upload-sarif@d39d31e687223d841ef683f52467bd88e9b21c14 # v3.25.3 with: sarif_file: results.sarif diff --git a/.github/workflows/unit.yml b/.github/workflows/unit.yml index de31a760..f396ca2c 100644 --- a/.github/workflows/unit.yml +++ b/.github/workflows/unit.yml @@ -13,10 +13,26 @@ jobs: matrix: python: ['3.7', '3.8', '3.9', '3.10', '3.11', '3.12'] platform: [ubuntu-latest, macos-latest, windows-latest] + # Python <= 3.9 is not available on macos-14 + # Workaround for https://github.com/actions/setup-python/issues/696 + exclude: + - platform: macos-latest + python: '3.9' + - platform: macos-latest + python: '3.8' + - platform: macos-latest + python: '3.7' + include: + - platform: macos-latest + python: '3.9' + - platform: macos-13 + python: '3.8' + - platform: macos-13 + python: '3.7' runs-on: ${{ matrix.platform }} steps: - name: Harden Runner - uses: step-security/harden-runner@1b05615854632b887b69ae1be8cbefe72d3ae423 # v2.6.0 + uses: step-security/harden-runner@63c24ba6bd7ba022e95695ff85de572c04a18142 # v2.7.0 with: disable-sudo: true egress-policy: block @@ -29,9 +45,9 @@ jobs: registry-1.docker.io:443 - name: Checkout - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 + uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4 - name: Use Python ${{ matrix.python }} - uses: actions/setup-python@65d7f2d534ac1bc67fcd62888c5f4f3d2cb2b236 # v4.7.1 + uses: actions/setup-python@82c7e631bb3cdc910f68e0081d67478d79c6982d # v5.1.0 with: python-version: ${{ matrix.python }} - name: Install tox diff --git a/CHANGELOG.md b/CHANGELOG.md index 32fe2c35..23665c2e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,13 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [3.6.0](https://github.com/GoogleCloudPlatform/functions-framework-python/compare/v3.5.0...v3.6.0) (2024-04-29) + + +### Features + +* avoid long running process when request timeout ([#309](https://github.com/GoogleCloudPlatform/functions-framework-python/issues/309)) ([3a0cdb8](https://github.com/GoogleCloudPlatform/functions-framework-python/commit/3a0cdb8ba1065510d8ca0f2bcabd484cd3ffaaf6)) + ## [3.5.0](https://github.com/GoogleCloudPlatform/functions-framework-python/compare/v3.4.0...v3.5.0) (2023-11-28) diff --git a/setup.py b/setup.py index 51a3e27c..6ee9902f 100644 --- a/setup.py +++ b/setup.py @@ -25,7 +25,7 @@ setup( name="functions-framework", - version="3.5.0", + version="3.6.0", description="An open source FaaS (Function as a service) framework for writing portable Python functions -- brought to you by the Google Cloud Functions team.", long_description=long_description, long_description_content_type="text/markdown", @@ -33,16 +33,15 @@ author="Google LLC", author_email="googleapis-packages@google.com", classifiers=[ - "Development Status :: 3 - Alpha", + "Development Status :: 5 - Production/Stable ", "Intended Audience :: Developers", "License :: OSI Approved :: Apache Software License", - "Programming Language :: Python :: 3", - "Programming Language :: Python :: 3.5", - "Programming Language :: Python :: 3.6", "Programming Language :: Python :: 3.7", "Programming Language :: Python :: 3.8", "Programming Language :: Python :: 3.9", "Programming Language :: Python :: 3.10", + "Programming Language :: Python :: 3.11", + "Programming Language :: Python :: 3.12", ], keywords="functions-framework", packages=find_packages(where="src"), diff --git a/src/functions_framework/__init__.py b/src/functions_framework/__init__.py index ece4f446..8c23e5c0 100644 --- a/src/functions_framework/__init__.py +++ b/src/functions_framework/__init__.py @@ -65,9 +65,9 @@ def write(self, out): def cloud_event(func: CloudEventFunction) -> CloudEventFunction: """Decorator that registers cloudevent as user function signature type.""" - _function_registry.REGISTRY_MAP[ - func.__name__ - ] = _function_registry.CLOUDEVENT_SIGNATURE_TYPE + _function_registry.REGISTRY_MAP[func.__name__] = ( + _function_registry.CLOUDEVENT_SIGNATURE_TYPE + ) @functools.wraps(func) def wrapper(*args, **kwargs): @@ -105,9 +105,9 @@ def wrapper(*args, **kwargs): def http(func: HTTPFunction) -> HTTPFunction: """Decorator that registers http as user function signature type.""" - _function_registry.REGISTRY_MAP[ - func.__name__ - ] = _function_registry.HTTP_SIGNATURE_TYPE + _function_registry.REGISTRY_MAP[func.__name__] = ( + _function_registry.HTTP_SIGNATURE_TYPE + ) @functools.wraps(func) def wrapper(*args, **kwargs): diff --git a/src/functions_framework/_http/gunicorn.py b/src/functions_framework/_http/gunicorn.py index 3a9c545b..009a06b7 100644 --- a/src/functions_framework/_http/gunicorn.py +++ b/src/functions_framework/_http/gunicorn.py @@ -21,14 +21,15 @@ class GunicornApplication(gunicorn.app.base.BaseApplication): def __init__(self, app, host, port, debug, **options): self.options = { "bind": "%s:%s" % (host, port), - "workers": 1, - "threads": (os.cpu_count() or 1) * 4, - "timeout": 0, + "workers": os.environ.get("WORKERS", (os.cpu_count() or 1) * 4), + "threads": os.environ.get("THREADS", 1), + "timeout": os.environ.get("CLOUD_RUN_TIMEOUT_SECONDS", 300), "loglevel": "error", "limit_request_line": 0, } self.options.update(options) self.app = app + super().__init__() def load_config(self): diff --git a/src/functions_framework/_typed_event.py b/src/functions_framework/_typed_event.py index 40e715ae..413c8f05 100644 --- a/src/functions_framework/_typed_event.py +++ b/src/functions_framework/_typed_event.py @@ -48,9 +48,9 @@ def register_typed_event(decorator_type, func): ) _function_registry.INPUT_TYPE_MAP[func.__name__] = input_type - _function_registry.REGISTRY_MAP[ - func.__name__ - ] = _function_registry.TYPED_SIGNATURE_TYPE + _function_registry.REGISTRY_MAP[func.__name__] = ( + _function_registry.TYPED_SIGNATURE_TYPE + ) """ Checks whether the response type of the typed function has a to_dict method""" diff --git a/tests/test_http.py b/tests/test_http.py index fbfac9d2..0a46fbea 100644 --- a/tests/test_http.py +++ b/tests/test_http.py @@ -97,17 +97,17 @@ def test_gunicorn_application(debug): assert gunicorn_app.app == app assert gunicorn_app.options == { "bind": "%s:%s" % (host, port), - "workers": 1, - "threads": os.cpu_count() * 4, - "timeout": 0, + "workers": os.cpu_count() * 4, + "threads": 1, + "timeout": 300, "loglevel": "error", "limit_request_line": 0, } assert gunicorn_app.cfg.bind == ["1.2.3.4:1234"] - assert gunicorn_app.cfg.workers == 1 - assert gunicorn_app.cfg.threads == os.cpu_count() * 4 - assert gunicorn_app.cfg.timeout == 0 + assert gunicorn_app.cfg.workers == os.cpu_count() * 4 + assert gunicorn_app.cfg.threads == 1 + assert gunicorn_app.cfg.timeout == 300 assert gunicorn_app.load() == app diff --git a/tests/test_samples.py b/tests/test_samples.py index 65cee7d0..d76d7796 100644 --- a/tests/test_samples.py +++ b/tests/test_samples.py @@ -24,7 +24,7 @@ def test_cloud_run_http(self): self.stop_all_containers(client) TAG = "cloud_run_http" - client.images.build(path=str(EXAMPLES_DIR / "cloud_run_http"), tag={TAG}) + client.images.build(path=str(EXAMPLES_DIR / "cloud_run_http"), tag=TAG) container = client.containers.run(image=TAG, detach=True, ports={8080: 8080}) timeout = 10 success = False