⁉️ 400 response on invalid JSON/YAML body #2580
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: Deploy | |
| on: | |
| schedule: | |
| - cron: "0 0 1 * *" | |
| push: | |
| tags: [ v* ] | |
| branches: [ main ] | |
| pull_request: | |
| branches: [ main ] | |
| env: | |
| PIP_DISABLE_PIP_VERSION_CHECK: yes | |
| jobs: | |
| prepare-build: | |
| name: Prepare building | |
| runs-on: ubuntu-24.04 | |
| permissions: | |
| contents: write | |
| steps: | |
| - name: Checkout repository | |
| uses: actions/checkout@v4 | |
| with: | |
| filter: blob:none | |
| fetch-deps: 0 | |
| fetch-tags: true | |
| - name: Check if already released | |
| if: github.event_name == 'schedule' | |
| run: test -z $(git tag --list "v*" --points-at) | |
| - name: Create tag | |
| if: github.event_name == 'schedule' | |
| run: git tag $(date -u '+v%y.%m') | |
| - name: Push tag | |
| if: github.event_name == 'schedule' | |
| run: git push --tags | |
| build: | |
| name: Build | |
| runs-on: ubuntu-24.04 | |
| permissions: | |
| contents: read | |
| needs: | |
| - prepare-build | |
| steps: | |
| - name: Checkout repository | |
| uses: actions/checkout@v4 | |
| with: | |
| fetch-depth: 0 | |
| - name: Setup Python | |
| uses: actions/setup-python@v5 | |
| with: | |
| python-version: 3.12 | |
| - name: Install build frontend | |
| run: pip install "build==1.*" | |
| - name: Build | |
| run: python -m build | |
| - name: Hash | |
| run: sha256sum dist/* | |
| - name: Upload as build artifact | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| path: dist | |
| build-source-tarball: | |
| name: Create minimal source tarball | |
| runs-on: ubuntu-24.04 | |
| permissions: | |
| contents: read | |
| needs: | |
| - prepare-build | |
| steps: | |
| - name: Setup Python | |
| uses: actions/setup-python@v5 | |
| with: | |
| python-version: 3.12.7 | |
| allow-prereleases: true | |
| - name: Checkout repository | |
| uses: actions/checkout@v4 | |
| with: | |
| fetch-depth: 0 | |
| - name: Run setup.py | |
| run: pip install --no-deps . | |
| - name: Write version to file | |
| run: "pip show an_website | grep -P '^Version: ' | cut '-d ' -f2 > VERSIONS.TXT" | |
| - name: Create tar | |
| run: git ls-files | xargs tar cf an-website.tar an_website/static/commits.txt REVISION.TXT TIMESTMP.TXT VERSIONS.TXT | |
| - name: Compress tar | |
| run: pigz -11 an-website.tar | |
| - name: Upload as build artifact | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| path: an-website.tar.gz | |
| name: source-tarball | |
| test-distribution: | |
| name: Test distribution | |
| runs-on: ubuntu-24.04 | |
| needs: | |
| - build | |
| permissions: {} | |
| continue-on-error: ${{ matrix.python-version == 3.14 }} | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| python-version: | |
| - 3.12.7 # EL10 | |
| - 3.13 | |
| - 3.14 # π | |
| distribution: | |
| - name: wheel | |
| glob: '*.whl' | |
| - name: sdist | |
| glob: '*.tar.gz' | |
| steps: | |
| - name: Setup Python | |
| uses: actions/setup-python@v5 | |
| with: | |
| python-version: ${{ matrix.python-version }} | |
| allow-prereleases: true | |
| - name: Download artifact | |
| uses: actions/download-artifact@v4 | |
| with: | |
| name: artifact | |
| - name: Install libcurl4-openssl-dev for compiling PycURL | |
| run: sudo apt-get install --update -y libcurl4-openssl-dev | |
| - name: Check dirty | |
| run: echo ${{ matrix.distribution.glob }} | grep -v dirty | |
| - name: Install ${{ matrix.distribution.name }} without dependencies | |
| run: pip install --no-deps ${{ matrix.distribution.glob }} | |
| timeout-minutes: 0.3 | |
| - name: Uninstall an-website | |
| run: pip uninstall -y an-website | |
| timeout-minutes: 1 | |
| - name: Install ${{ matrix.distribution.name }} | |
| run: pip install ${{ matrix.distribution.glob }} | |
| - name: Test help | |
| timeout-minutes: 1 | |
| run: python -m an_website --help | |
| - name: Test starting | |
| timeout-minutes: 1 | |
| run: python -m an_website -c | |
| - name: Test starting with recommended dev options | |
| timeout-minutes: 1 | |
| run: python -Xdev -Xwarn_default_encoding -m an_website -c | |
| - name: Test version | |
| timeout-minutes: 1 | |
| run: an-website --version | grep -v dirty | |
| - name: Test verbose version | |
| timeout-minutes: 1 | |
| run: an-website --version --verbose --verbose | tee hashes.txt | |
| - name: Upload file hashes as artifact | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| path: hashes.txt | |
| if-no-files-found: error | |
| name: file-hashes-${{ matrix.distribution.name }}-${{ matrix.python-version }} | |
| test-source-tarball: | |
| name: Test building from source tarball | |
| runs-on: ubuntu-24.04 | |
| permissions: | |
| contents: read | |
| needs: | |
| - build | |
| - build-source-tarball | |
| steps: | |
| - name: Download source tarball | |
| uses: actions/download-artifact@v4 | |
| with: | |
| name: source-tarball | |
| - name: Setup Python | |
| uses: actions/setup-python@v5 | |
| with: | |
| python-version: 3.12.7 | |
| allow-prereleases: true | |
| - name: Install build | |
| run: pip install build | |
| - name: Build from tarball | |
| run: | | |
| tar xf an-website.tar.gz | |
| python -m build | |
| sha256sum dist/* | |
| - name: Download artifact | |
| uses: actions/download-artifact@v4 | |
| with: | |
| name: artifact | |
| - name: Compare file hashes | |
| run: | | |
| set -xeu | |
| BALL_HASHES="$(sha256sum dist/*)" | |
| rm dist/* && mv an_website-* dist/ | |
| ORIG_HASHES="$(sha256sum dist/*)" | |
| [ "$ORIG_HASHES" = "$BALL_HASHES" ] | |
| sdist-tests: | |
| name: Run tests in source distribution | |
| runs-on: ubuntu-24.04 | |
| permissions: | |
| contents: read | |
| needs: | |
| - build | |
| continue-on-error: ${{ matrix.python-version == 3.14 }} | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| python-version: | |
| - 3.12.7 # EL10 | |
| - 3.13 | |
| - 3.14 # π | |
| services: | |
| redis: | |
| image: docker.io/redis/redis-stack-server:6.2.6-v20 | |
| ports: | |
| - 6379:6379 | |
| steps: | |
| - name: Setup Python | |
| uses: actions/setup-python@v5 | |
| with: | |
| python-version: ${{ matrix.python-version }} | |
| allow-prereleases: true | |
| - name: Download artifact | |
| uses: actions/download-artifact@v4 | |
| with: | |
| name: artifact | |
| - name: Install libcurl4-openssl-dev for compiling PycURL | |
| run: sudo apt-get install --update -y libcurl4-openssl-dev | |
| - name: Unpack sdist | |
| run: | | |
| tar xf *.tar.gz | |
| rm *.tar.gz *.whl | |
| mv an_website-*/* . | |
| rmdir an_website-* | |
| - name: Install requirements | |
| run: pip install -r pip-requirements.txt --no-deps | |
| - name: Install TESTDEPS | |
| run: pip install -r TESTDEPS.TXT | |
| - name: Run pytest | |
| timeout-minutes: 5 | |
| run: pytest --durations=0 --verbose | |
| tests: | |
| name: Run tests | |
| runs-on: ubuntu-24.04 | |
| permissions: | |
| contents: read | |
| continue-on-error: ${{ matrix.python-version == 3.14 }} | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| python-version: | |
| - 3.12.7 # EL10 | |
| - 3.13 | |
| - 3.14 # π | |
| services: | |
| redis: | |
| image: docker.io/redis/redis-stack-server:6.2.6-v20 | |
| ports: | |
| - 6379:6379 | |
| steps: | |
| # - name: Configure sysctl limits | |
| # run: | | |
| # sudo swapoff -a | |
| # sudo sysctl -w vm.swappiness=1 | |
| # sudo sysctl -w fs.file-max=262144 | |
| # sudo sysctl -w vm.max_map_count=262144 | |
| # - name: Start Elasticsearch | |
| # uses: elastic/elastic-github-actions/elasticsearch@2c3ec0418fabc996180995c47b86a65b581f1561 | |
| # with: | |
| # stack-version: 8.18.8 | |
| # security-enabled: false | |
| # nodes: 3 | |
| # license: trial | |
| # plugins: | | |
| # analysis-icu | |
| # analysis-phonetic | |
| # mapper-size | |
| # mapper-murmur3 | |
| # mapper-annotated-text | |
| - name: Checkout repository | |
| uses: actions/checkout@v4 | |
| with: | |
| fetch-depth: 0 | |
| - name: Setup Python | |
| uses: actions/setup-python@v5 | |
| with: | |
| python-version: ${{ matrix.python-version }} | |
| allow-prereleases: true | |
| cache: pip | |
| cache-dependency-path: Pipfile.lock | |
| - name: Install libcurl4-openssl-dev for compiling PycURL | |
| run: sudo apt-get install --update -y libcurl4-openssl-dev | |
| - name: Install requirements | |
| run: pip install . && pip uninstall -y an-website | |
| - name: Install stuff needed for the tests | |
| run: grep "^pytest-" pip-constraints.txt | xargs pip install -c pip-constraints.txt html5lib pytest time-machine "backports.zstd; python_version < '3.14'" | |
| # - name: Run pytest with -Xdev | |
| # run: python3 -Xdev -Xwarn_default_encoding -m pytest | |
| - name: Run pytest | |
| timeout-minutes: 5 | |
| run: pytest --durations=0 --verbose --cov --cov-report=term:skip-covered | |
| - name: Upload coverage as artifact | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| path: .coverage | |
| if-no-files-found: error | |
| include-hidden-files: true | |
| name: coverage-${{ matrix.python-version }} | |
| release: | |
| name: Create release | |
| runs-on: ubuntu-24.04 | |
| permissions: | |
| contents: write | |
| needs: | |
| - run-tests-in-oci-image | |
| - sdist-tests | |
| - test-source-tarball | |
| - test-running-oci-image | |
| - test-distribution | |
| - tests | |
| if: github.event_name == 'schedule' || (github.ref_type == 'tag' && github.event_name == 'push') | |
| steps: | |
| - name: Setup Python | |
| uses: actions/setup-python@v5 | |
| with: | |
| python-version: 3.12 | |
| - name: Download artifact | |
| uses: actions/download-artifact@v4 | |
| with: | |
| name: artifact | |
| - name: Download source tarball | |
| uses: actions/download-artifact@v4 | |
| with: | |
| name: source-tarball | |
| - name: Version | |
| id: version | |
| shell: python | |
| run: | | |
| import os | |
| from pathlib import Path | |
| from time import strftime, gmtime | |
| path = Path(os.getenv("GITHUB_OUTPUT")) | |
| if "${{ github.event_name }}" == "schedule": | |
| path.write_text(f"version={strftime('v%y.%m', gmtime())}\n") | |
| elif "${{ github.event_name }}" == "push" and "${{ github.ref_type }}" == "tag": | |
| path.write_text("version=${{ github.ref_name }}\n") | |
| else: | |
| assert 6 * 9 == 42 | |
| - name: Create release | |
| uses: softprops/action-gh-release@v2 | |
| with: | |
| tag_name: ${{ steps.version.outputs.version }} | |
| generate_release_notes: true | |
| files: | | |
| *.tar.gz | |
| *.whl | |
| pypi: | |
| name: Upload to PyPI | |
| runs-on: ubuntu-24.04 | |
| needs: | |
| - run-tests-in-oci-image | |
| - sdist-tests | |
| - test-running-oci-image | |
| - test-distribution | |
| - test-source-tarball | |
| - tests | |
| if: github.event_name == 'schedule' || (github.ref_type == 'tag' && github.event_name == 'push') | |
| permissions: {} | |
| steps: | |
| - name: Setup Python | |
| uses: actions/setup-python@v5 | |
| with: | |
| python-version: 3.12 | |
| - name: Download artifact | |
| uses: actions/download-artifact@v4 | |
| with: | |
| name: artifact | |
| - name: Install Twine | |
| run: pip install "twine==6.*" | |
| - name: Run Twine | |
| run: | | |
| twine check --strict *.tar.gz *.whl | |
| twine upload --verbose --disable-progress-bar *.tar.gz | |
| env: | |
| TWINE_USERNAME: __token__ | |
| TWINE_PASSWORD: ${{ secrets.PYPI_TOKEN }} | |
| sourcemaps: | |
| name: Upload sourcemaps | |
| runs-on: ubuntu-24.04 | |
| if: github.event_name == 'push' || github.event_name == 'schedule' | |
| needs: | |
| - sdist-tests | |
| - test-distribution | |
| - tests | |
| - test-source-tarball | |
| permissions: {} | |
| outputs: | |
| version: ${{ steps.version.outputs.version }} | |
| steps: | |
| - name: Setup Python | |
| uses: actions/setup-python@v5 | |
| with: | |
| python-version: 3.12 | |
| - name: Download artifact | |
| uses: actions/download-artifact@v4 | |
| with: | |
| name: artifact | |
| - name: Install required library | |
| run: pip install packaging==24.2 | |
| - name: Version | |
| id: version | |
| shell: python | |
| run: | | |
| import os | |
| from pathlib import Path | |
| from subprocess import run | |
| from packaging.utils import parse_sdist_filename | |
| command = "ls an_website-*.tar.gz" | |
| result = run(command, shell=True, capture_output=True) | |
| filename = result.stdout.decode("UTF-8").strip() | |
| _, version = parse_sdist_filename(filename) | |
| path = Path(os.getenv("GITHUB_OUTPUT")) | |
| path.write_text(f"version={version}\n") | |
| - name: Unpack source distribution | |
| run: tar xvf an_website-*.tar.gz | |
| - name: Upload sourcemaps | |
| run: | | |
| cd an_website-*/an_website | |
| find static/js -type f -name "*.js" -exec \ | |
| curl -sSfk https://kibana.asozial.org:5601/api/apm/sourcemaps \ | |
| -H "Authorization: ApiKey ${{ secrets.SOURCEMAP_API_KEY }}" \ | |
| -H "kbn-xsrf: true" \ | |
| -F service_name="an-website" \ | |
| -F service_version="${{ steps.version.outputs.version }}" \ | |
| -F bundle_filepath="/{}" \ | |
| -F sourcemap=@{}.map \; | |
| deploy: | |
| name: Deploy website | |
| runs-on: ubuntu-24.04 | |
| if: github.event_name == 'push' || github.event_name == 'schedule' | |
| needs: | |
| - sourcemaps | |
| permissions: {} | |
| environment: | |
| name: production | |
| url: https://asozial.org | |
| steps: | |
| - name: Download artifact | |
| uses: actions/download-artifact@v4 | |
| with: | |
| name: artifact | |
| - name: Deploy website | |
| run: | | |
| curl -sSf -T *.whl https://asozial.org/api/update/ \ | |
| -H "Authorization: ${{ secrets.UPDATE_API_SECRET }}" | |
| - name: Checkout repository | |
| uses: actions/checkout@v4 | |
| - name: Check deployment | |
| uses: ./.github/actions/check_deployment | |
| with: | |
| origin: https://asozial.org | |
| version: ${{ needs.sourcemaps.outputs.version }} | |
| github-pages: | |
| name: GitHub Pages | |
| runs-on: ubuntu-24.04 | |
| if: github.event_name == 'push' || github.event_name == 'schedule' | |
| needs: | |
| - sdist-tests | |
| - test-distribution | |
| - deploy | |
| permissions: | |
| actions: read | |
| contents: read | |
| id-token: write | |
| pages: write | |
| environment: | |
| name: github-pages | |
| url: ${{ steps.deployment.outputs.page_url }} | |
| steps: | |
| - name: Checkout repository | |
| uses: actions/checkout@v4 | |
| with: | |
| ref: ${{ github.head_ref }} | |
| fetch-depth: 0 | |
| - name: Setup Python | |
| uses: actions/setup-python@v5 | |
| with: | |
| python-version: 3.12.7 | |
| cache: pip | |
| cache-dependency-path: Pipfile.lock | |
| - name: Download coverage | |
| uses: actions/download-artifact@v4 | |
| with: | |
| name: coverage-3.12.7 | |
| - name: Download file hashes | |
| uses: actions/download-artifact@v4 | |
| with: | |
| name: file-hashes-wheel-3.12.7 | |
| - name: Make directory | |
| run: mkdir github-pages | |
| - name: Move file hashes | |
| run: mv hashes.txt github-pages/hashes.txt | |
| - name: Install Coverage.py | |
| run: pip install -c pip-constraints.txt coverage | |
| - name: Create coverage files | |
| run: | | |
| coverage html -d github-pages/coverage | |
| coverage json -o github-pages/coverage.json | |
| ./generate-badge.sh > github-pages/coverage/badge.svg | |
| rm -f github-pages/coverage/.gitignore | |
| - name: Generate commitment.txt | |
| run: git log "--pretty=%H %ct %s" > github-pages/commitment.txt | |
| - name: Upload GitHub Pages artifact | |
| uses: actions/upload-pages-artifact@v3 | |
| with: | |
| path: github-pages | |
| - name: Deploy GitHub Pages site | |
| id: deployment | |
| uses: actions/deploy-pages@v4 | |
| build-oci-image: | |
| name: Build OCI image | |
| runs-on: ubuntu-24.04 | |
| needs: | |
| - build | |
| permissions: | |
| packages: write | |
| steps: | |
| - name: Setup Go | |
| uses: actions/setup-go@v5 | |
| with: | |
| go-version: ~1.20 | |
| - name: Install Netavark | |
| run: sudo apt-get install --update -y netavark | |
| - name: Upgrade Buildah | |
| run: | | |
| sudo apt-get install -y libapparmor-dev libdevmapper-dev libglib2.0-dev libgpgme-dev libseccomp-dev libselinux1-dev | |
| git clone -b v1.35.5 --depth=1 https://github.com/containers/buildah.git ~/go/src/github.com/containers/buildah | |
| pushd ~/go/src/github.com/containers/buildah | |
| make buildah docs | |
| sudo make install | |
| buildah version | |
| popd | |
| - name: Download youki | |
| run: | | |
| wget https://github.com/containers/youki/releases/download/v${VERSION}/youki-${VERSION}-x86_64-musl.tar.gz | |
| tar xOf youki-${VERSION}-x86_64-musl.tar.gz youki > /opt/youki | |
| rm -f youki-${VERSION}-x86_64-musl.tar.gz | |
| chmod +x /opt/youki | |
| env: | |
| VERSION: 0.5.5 | |
| - name: Setup Python | |
| uses: actions/setup-python@v5 | |
| with: | |
| python-version: 3.12 | |
| - name: Install Setuptools | |
| run: pip install "setuptools==70.3.0" | |
| - name: Download artifact | |
| uses: actions/download-artifact@v4 | |
| with: | |
| name: artifact | |
| - name: Extract source distribution | |
| run: | | |
| tar xvf *.tar.gz | |
| - name: Build image | |
| run: | | |
| cd an_website-*/ | |
| sudo ./build-oci-image.sh -t an-website | |
| cd .. | |
| env: | |
| BUILDAH_RUNTIME: /opt/youki | |
| - name: Save image | |
| run: sudo buildah push --all --format=oci --compression-format=zstd:chunked --compression-level=20 an-website oci-archive:oci-archive.tar | |
| - name: Upload as build artifact | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: oci-image | |
| path: oci-archive.tar | |
| test-running-oci-image: | |
| name: Test running OCI image | |
| runs-on: ubuntu-24.04 | |
| needs: | |
| - build-oci-image | |
| steps: | |
| - name: Download artifact | |
| uses: actions/download-artifact@v4 | |
| with: | |
| name: oci-image | |
| - name: Run image | |
| timeout-minutes: 1 | |
| run: sudo podman run --network=host -t oci-archive:oci-archive.tar -c | |
| run-tests-in-oci-image: | |
| name: Run tests in OCI image | |
| runs-on: ubuntu-24.04 | |
| needs: | |
| - build-oci-image | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| redis-image: | |
| - docker.io/redis/redis-stack-server:6.2.6-v20 | |
| #- docker.dragonflydb.io/dragonflydb/dragonfly | |
| services: | |
| redis: | |
| image: ${{ matrix.redis-image }} | |
| ports: | |
| - 6379:6379 | |
| steps: | |
| - name: Checkout repository | |
| uses: actions/checkout@v4 | |
| - name: Download artifact | |
| uses: actions/download-artifact@v4 | |
| with: | |
| name: oci-image | |
| - name: Run tests | |
| timeout-minutes: 20 | |
| run: sudo podman run --network=host -t -v ./pip-constraints.txt:/pip-constraints.txt:z,ro -v ./tests:/tests:z,ro --entrypoint=/bin/sh oci-archive:oci-archive.tar -c "grep -P '^pytest-(?!cov)' /pip-constraints.txt | xargs /venv/bin/pip install --disable-pip-version-check -c /pip-constraints.txt html5lib pytest time-machine && /venv/bin/pytest --verbose /tests" | |
| push-oci-image: | |
| name: Push OCI image | |
| runs-on: ubuntu-24.04 | |
| needs: | |
| - run-tests-in-oci-image | |
| - test-running-oci-image | |
| if: github.event_name == 'push' || github.event_name == 'schedule' | |
| permissions: | |
| packages: write | |
| steps: | |
| - name: Setup Go | |
| uses: actions/setup-go@v5 | |
| with: | |
| go-version: ~1.20 | |
| - name: Upgrade Skopeo | |
| run: | | |
| sudo apt-get install --update -y libdevmapper-dev libgpgme-dev | |
| git clone -b v1.15.2 --depth=1 https://github.com/containers/skopeo.git ~/go/src/github.com/containers/skopeo | |
| pushd ~/go/src/github.com/containers/skopeo | |
| make bin/skopeo | |
| sudo make install DISABLE_DOCS=1 | |
| skopeo --version | |
| popd | |
| - name: Download artifact | |
| uses: actions/download-artifact@v4 | |
| with: | |
| name: oci-image | |
| - name: Version | |
| id: version | |
| shell: python | |
| run: | | |
| import os | |
| from pathlib import Path | |
| from time import strftime, gmtime | |
| path = Path(os.getenv("GITHUB_OUTPUT")) | |
| if "${{ github.event_name }}" == "schedule": | |
| path.write_text(f"version={strftime('v%y.%m', gmtime())}\n") | |
| elif "${{ github.event_name }}" == "push" and "${{ github.ref_type }}" == "tag": | |
| path.write_text("version=${{ github.ref_name }}\n") | |
| - name: Log in to ghcr.io | |
| uses: redhat-actions/podman-login@v1 | |
| with: | |
| username: ${{ github.actor }} | |
| password: ${{ github.token }} | |
| registry: ghcr.io/${{ github.repository }} | |
| - name: Push image to ghcr.io | |
| run: skopeo copy --all --preserve-digests oci-archive:oci-archive.tar docker://ghcr.io/${{ github.repository }}:dev | |
| - name: Push image as ${{ steps.version.outputs.version }} to ghcr.io | |
| run: skopeo copy --all --preserve-digests oci-archive:oci-archive.tar docker://ghcr.io/${{ github.repository }}:${{ steps.version.outputs.version }} | |
| if: steps.version.outputs.version | |
| - name: Tag image as latest | |
| run: skopeo copy --all --preserve-digests oci-archive:oci-archive.tar docker://ghcr.io/${{ github.repository }}:latest | |
| if: steps.version.outputs.version |