## Change Summary

Ensure that a `SecretStr` type can be populated from json.

## Related issue number

Fix #7720

## Checklist

* [x] The pull request title is a good summary of the changes - it will be used in the changelog
* [x] Unit tests for the changes exist
* [x] Tests pass on CI
* [ ] Documentation reflects the changes where applicable
* [x] My PR is ready to review, **please add a comment including the phrase "please review" to assign reviewers**


Selected Reviewer: @samuelcolvin
Fix failure to load `SecretStr` from JSON (regression in v2.4). ## Change Summary

Ensure that a `SecretStr` type can be populated from json.

## Related issue number

Fix #7720

## Checklist

* [x] The pull request title is a good summary of the changes - it will be used in the changelog
* [x] Unit tests for the changes exist
* [x] Tests pass on CI
* [ ] Documentation reflects the changes where applicable
* [x] My PR is ready to review, **please add a comment including the phrase "please review" to assign reviewers**


Selected Reviewer: @samuelcolvin
name: CI

on:
  push:
    branches:
      - main
    tags:
      - '**'
  pull_request: {}

env:
  COLUMNS: 150
  PDM_DEPS: 'urllib3<2'
  FINDPYTHON_GET_VERSION_TIMEOUT: 30

jobs:
  lint:
    runs-on: ubuntu-latest
    name: lint ${{ matrix.python-version }}
    strategy:
      fail-fast: false
      matrix:
        python-version: ['3.7', '3.8', '3.9', '3.10', '3.11', '3.12']
    steps:
      - uses: actions/checkout@v4

      - uses: pdm-project/setup-pdm@v3
        with:
          python-version: ${{ matrix.python-version }}
          cache: true
          allow-python-prereleases: true

      - name: install
        run: |
          pdm use -f $PYTHON
          pdm install -G linting -G email

      - uses: pre-commit/action@v3.0.0
        with:
          extra_args: --all-files --verbose
        env:
          SKIP: no-commit-to-branch

  docs-build:
    runs-on: ubuntu-latest
    steps:
    - uses: actions/checkout@v4

    - uses: pdm-project/setup-pdm@v3
      with:
        # cloudflare pages build containers run 3.8, hence using it here
        python-version: '3.8'

    - name: install dependencies
      # Unlike the docs build, we don't use mkdocs_material-insiders
      # Because the secret for accessing the library is not accessible from forks, but we still want to run
      # this job on public CI runs.
      run: |
        pdm venv create --with-pip $PYTHON
        pdm install -G docs

    - run: pdm run python -c 'import docs.plugins.main'

    # Adding local symlinks gets nice source locations like
    #   pydantic_core/core_schema.py
    # instead of
    #   .venv/lib/python3.10/site-packages/pydantic_core/core_schema.py
    - name: prepare shortcuts for extra modules
      run: |
        ln -s .venv/lib/python*/site-packages/pydantic_core pydantic_core
        ln -s .venv/lib/python*/site-packages/pydantic_settings pydantic_settings
        ln -s .venv/lib/python*/site-packages/pydantic_extra_types pydantic_extra_types

    - run: pdm run mkdocs build

  test-memray:
    name: test memray
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - uses: pdm-project/setup-pdm@v3
        with:
          python-version: '3.10'
          cache: true

      - name: install deps
        run: |
          pdm use -f $PYTHON
          pdm install -G testing -G testing-extra -G email -G memray
          pdm add pytest-memray

      - name: test
        run: pdm run pytest --ignore=tests/mypy/ --ignore=tests/test_docs.py --memray

  test:
    name: test ${{ matrix.os }} / ${{ matrix.python-version }}
    strategy:
      fail-fast: false
      matrix:
        os: [ubuntu, macos, windows]
        python-version: ['3.7', '3.8', '3.9', '3.10', '3.11', '3.12']
        include:
          # no pydantic-core binaries for pypy on windows, so tests take absolute ages
          # macos tests with pypy take ages (>10mins) since pypy is very slow
          # so we only test pypy on ubuntu
          - os: ubuntu
            python-version: 'pypy3.7'
          - os: ubuntu
            python-version: 'pypy3.8'
          - os: ubuntu
            python-version: 'pypy3.9'
          - os: ubuntu
            python-version: 'pypy3.10'

    env:
      OS: ${{ matrix.os }}
      DEPS: yes

    runs-on: ${{ matrix.os }}-latest

    steps:
    - uses: actions/checkout@v4

    - uses: pdm-project/setup-pdm@v3
      with:
        python-version: ${{ matrix.python-version }}
        cache: true
        allow-python-prereleases: true

    - name: install deps
      run: |
        pdm use -f $PYTHON
        pdm install -G testing -G email

    - run: pdm info && pdm list

    - run: 'pdm run python -c "import pydantic.version; print(pydantic.version.version_info())"'

    - run: mkdir coverage

    - name: test without deps
      # speed up by skipping this step on pypy
      if: "!startsWith(matrix.python-version, 'pypy')"
      run: make test
      env:
        COVERAGE_FILE: coverage/.coverage.${{ runner.os }}-py${{ matrix.python-version }}-without-deps
        CONTEXT: ${{ runner.os }}-py${{ matrix.python-version }}-without-deps

    - name: install extra deps
      run: pdm install -G testing-extra -G email

    - name: test with deps
      run: make test
      env:
        COVERAGE_FILE: coverage/.coverage.${{ runner.os }}-py${{ matrix.python-version }}-with-deps
        CONTEXT: ${{ runner.os }}-py${{ matrix.python-version }}-with-deps

    - name: store coverage files
      uses: actions/upload-artifact@v3
      with:
        name: coverage
        path: coverage

  test-fastapi:
    # If some tests start failing due to out-of-date schemas/validation errors/etc.,
    # update the `tests/test_fastapi.sh` script to exclude tests that have known-acceptable failures.
    name: test fastapi
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - name: set up python
        uses: actions/setup-python@v4
        with:
          python-version: '3.10'

      - name: test
        run: make test-fastapi

  test-plugin:
    name: test pydantic plugin
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - uses: pdm-project/setup-pdm@v3
        with:
          python-version: '3.11'
          cache: true

      - name: install deps
        run: |
          pdm use -f $PYTHON
          pdm install -G testing

      - name: install example plugin
        run: pdm add ./tests/plugin

      - run: pdm run pytest ./tests/plugin
        env:
          TEST_PLUGIN: 1

      # uninstalling is necessary to avoid creating a pdm cache shared with other jobs
      # which includes the plugin
      - name: uninstall example plugin
        run: pdm remove ./tests/plugin

  test-mypy:
    name: mypy ${{ matrix.mypy-version }} / ${{ matrix.python-version }}
    runs-on: ubuntu-latest
    strategy:
      fail-fast: false
      matrix:
        # test recent mypy versions on 3.10 and mypy 1.0.1 on all supported python versions
        # if you change the value in the lockfile add the old value to this list
        mypy-version: ['1.0.1', 'lockfile', '1.2.0', '1.4.1', '1.5.1']
        python-version: ['3.10']
        include:
          - mypy-version: 'lockfile'
            python-version: '3.7'
          - mypy-version: 'lockfile'
            python-version: '3.8'
          - mypy-version: 'lockfile'
            python-version: '3.9'
          - mypy-version: 'lockfile'
            python-version: '3.11'
          # TODO: Once Python 3.7 is removed, and mypy is bumped on the lockfile, we can add 'lockfile' again.
          - mypy-version: '1.5.1'
            python-version: '3.12'

    steps:
    - uses: actions/checkout@v4

    - uses: pdm-project/setup-pdm@v3
      with:
        python-version: ${{ matrix.python-version }}
        cache: true
        allow-python-prereleases: true

    - name: install deps
      run: |
        pdm use -f $PYTHON
        pdm install -G testing -G mypy

    - name: install mypy
      if: steps.cache.outputs.cache-hit != 'true'
      run: |
        if [ ${{ matrix.mypy-version }} == '1.5.1' ]; then
          # mypy 1.5.0 only supports 3.8 and newer, so adjust pyproject.toml
          sed -i "s/requires-python = '>=3.7'/requires-python = '>=3.8'/g" pyproject.toml
        fi
        if [ ${{ matrix.mypy-version }} != 'lockfile' ]; then
          pdm remove -G linting mypy && pdm remove -G mypy mypy && pdm add mypy==${{ matrix.mypy-version }}
        fi
        pdm list

    - run: mkdir coverage

    - name: run mypy tests
      run: pdm run coverage run -m pytest tests/mypy --test-mypy
      env:
        COVERAGE_FILE: coverage/.coverage.linux-py${{ matrix.python-version }}-mypy${{ matrix.mypy-version }}
        CONTEXT: linux-py${{ matrix.python-version }}-mypy${{ matrix.mypy-version }}

    - name: install node for pyright
      uses: actions/setup-node@v3
      with:
        node-version: '18'

    - name: install pyright
      run: npm install -g pyright@1.1.322  # try to keep this in sync with .pre-commit-config.yaml

    - name: run pyright tests
      run: make test-pyright
      env:
        COVERAGE_FILE: coverage/.coverage.linux-py${{ matrix.python-version }}-pyright
        CONTEXT: linux-py${{ matrix.python-version }}-pyright

    - name: store coverage files
      uses: actions/upload-artifact@v3
      with:
        name: coverage
        path: coverage

  coverage-combine:
    needs: [test, test-mypy]
    runs-on: ubuntu-latest

    steps:
      - uses: actions/checkout@v4

      - uses: actions/setup-python@v4
        with:
          python-version: '3.8'

      - name: get coverage files
        uses: actions/download-artifact@v3
        with:
          name: coverage
          path: coverage

      - run: pip install coverage[toml]

      - run: ls -la coverage
      - run: coverage combine coverage
      - run: coverage report
      - run: coverage html --show-contexts --title "pydantic coverage for ${{ github.sha }}"

      - name: Store coverage html
        uses: actions/upload-artifact@v3
        with:
          name: coverage-html
          path: htmlcov

  test-typing-extensions:
    name: test typing-extensions ${{ matrix.typing-extensions-version }} on Python ${{ matrix.python-version }}
    runs-on: ubuntu-latest
    strategy:
      fail-fast: false
      matrix:
        # test the oldest supported version and main
        typing-extensions-version: ['4.6.1', 'main']
        python-version: ['3.8', '3.9', '3.10', '3.11', '3.12']
        include:
          - typing-extensions-version: '4.6.1'
            python-version: '3.7'

    steps:
    - uses: actions/checkout@v4

    - uses: pdm-project/setup-pdm@v3
      with:
        python-version: ${{ matrix.python-version }}
        cache: true
        allow-python-prereleases: true

    - name: install deps
      run: |
        pdm use -f $PYTHON
        pdm install -G testing -G email

    - name: install typing-extensions
      run: |
        if [ ${{ matrix.typing-extensions-version }} == 'main' ]; then
          # typing-extensions main only supports 3.8 and newer, so adjust pyproject.toml
          sed -i "s/requires-python = '>=3.7'/requires-python = '>=3.8'/g" pyproject.toml
          pdm remove typing-extensions && pdm add 'typing-extensions @ git+https://github.com/python/typing_extensions.git'
        else
          pdm remove typing-extensions && pdm add 'typing-extensions==${{ matrix.typing-extensions-version }}'
        fi
        pdm list
    - name: test
      run: make test

  # https://github.com/marketplace/actions/alls-green
  check:  # This job does nothing and is only used for the branch protection

    if: always()

    outputs:
      result: ${{ steps.all-green.outputs.result }}

    needs:
      - lint
      - docs-build
      - test
      - test-memray
      - test-mypy
      - test-fastapi
      - test-plugin

    runs-on: ubuntu-latest

    steps:
      - name: Decide whether the needed jobs succeeded or failed
        uses: re-actors/alls-green@release/v1
        id: all-green
        with:
          jobs: ${{ toJSON(needs) }}

  release:
    needs: [check]
    if: needs.check.outputs.result == 'success' && startsWith(github.ref, 'refs/tags/')
    runs-on: ubuntu-latest
    environment: release

    permissions:
      id-token: write

    outputs:
      pydantic-version: ${{ steps.check-tag.outputs.VERSION }}

    steps:
      - uses: actions/checkout@v4

      - name: set up python
        uses: actions/setup-python@v4
        with:
          python-version: '3.10'

      - name: install
        run: pip install -U build

      - name: check version
        id: check-tag
        uses: samuelcolvin/check-python-version@v4.1
        with:
          version_file_path: pydantic/version.py

      - name: build
        run: python -m build

      - name: Upload package to PyPI
        uses: pypa/gh-action-pypi-publish@release/v1

  send-tweet:
    name: Send tweet
    needs: [release]
    if: needs.release.result == 'success'
    runs-on: ubuntu-latest

    steps:
      - uses: actions/setup-python@v4
        with:
          python-version: '3.10'
      - name: Install dependencies
        run: pip install tweepy==4.14.0
      - name: Send tweet
        shell: python
        run: |
          import os
          import tweepy

          client = tweepy.Client(
              access_token=os.getenv("TWITTER_ACCESS_TOKEN"),
              access_token_secret=os.getenv("TWITTER_ACCESS_TOKEN_SECRET"),
              consumer_key=os.getenv("TWITTER_CONSUMER_KEY"),
              consumer_secret=os.getenv("TWITTER_CONSUMER_SECRET"),
          )
          version = os.getenv("VERSION").strip('"')
          tweet = os.getenv("TWEET").format(version=version)
          client.create_tweet(text=tweet)
        env:
          VERSION: ${{ needs.release.outputs.pydantic-version }}
          TWEET: |
            Pydantic version {version} is out! 🎉

            https://github.com/pydantic/pydantic/releases/tag/v{version}
          TWITTER_CONSUMER_KEY: ${{ secrets.TWITTER_CONSUMER_KEY }}
          TWITTER_CONSUMER_SECRET: ${{ secrets.TWITTER_CONSUMER_SECRET }}
          TWITTER_ACCESS_TOKEN: ${{ secrets.TWITTER_ACCESS_TOKEN }}
          TWITTER_ACCESS_TOKEN_SECRET: ${{ secrets.TWITTER_ACCESS_TOKEN_SECRET }}

name: CI

on:
  push:
    branches:
      - main
    tags:
      - '**'
  pull_request: {}

env:
  COLUMNS: 150
  PDM_DEPS: 'urllib3<2'
  FINDPYTHON_GET_VERSION_TIMEOUT: 30

jobs:
  lint:
    runs-on: ubuntu-latest
    name: lint ${{ matrix.python-version }}
    strategy:
      fail-fast: false
      matrix:
        python-version: ['3.7', '3.8', '3.9', '3.10', '3.11', '3.12']
    steps:
      - uses: actions/checkout@v4

      - uses: pdm-project/setup-pdm@v3
        with:
          python-version: ${{ matrix.python-version }}
          cache: true
          allow-python-prereleases: true

      - name: install
        run: |
          pdm venv create --with-pip --force $PYTHON
          pdm install -G linting -G email

      - uses: pre-commit/action@v3.0.0
        with:
          extra_args: --all-files --verbose
        env:
          SKIP: no-commit-to-branch

  docs-build:
    runs-on: ubuntu-latest
    steps:
    - uses: actions/checkout@v4

    - uses: pdm-project/setup-pdm@v3
      with:
        # cloudflare pages build containers run 3.8, hence using it here
        python-version: '3.8'

    - name: install dependencies
      # Unlike the docs build, we don't use mkdocs_material-insiders
      # Because the secret for accessing the library is not accessible from forks, but we still want to run
      # this job on public CI runs.
      run: |
        pdm venv create --with-pip --force $PYTHON
        pdm install -G docs

    - run: pdm run python -c 'import docs.plugins.main'

    # Adding local symlinks gets nice source locations like
    #   pydantic_core/core_schema.py
    # instead of
    #   .venv/lib/python3.10/site-packages/pydantic_core/core_schema.py
    - name: prepare shortcuts for extra modules
      run: |
        ln -s .venv/lib/python*/site-packages/pydantic_core pydantic_core
        ln -s .venv/lib/python*/site-packages/pydantic_settings pydantic_settings
        ln -s .venv/lib/python*/site-packages/pydantic_extra_types pydantic_extra_types

    - run: pdm run mkdocs build

  test-memray:
    name: test memray
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - uses: pdm-project/setup-pdm@v3
        with:
          python-version: '3.10'
          cache: true

      - name: install deps
        run: |
          pdm venv create --with-pip --force $PYTHON
          pdm install -G testing -G testing-extra -G email -G memray
          pdm add pytest-memray

      - name: test
        run: pdm run pytest --ignore=tests/mypy/ --ignore=tests/test_docs.py --memray

  test:
    name: test ${{ matrix.os }} / ${{ matrix.python-version }}
    strategy:
      fail-fast: false
      matrix:
        os: [ubuntu, macos, windows]
        python-version: ['3.7', '3.8', '3.9', '3.10', '3.11', '3.12']
        include:
          # no pydantic-core binaries for pypy on windows, so tests take absolute ages
          # macos tests with pypy take ages (>10mins) since pypy is very slow
          # so we only test pypy on ubuntu
          - os: ubuntu
            python-version: 'pypy3.7'
          - os: ubuntu
            python-version: 'pypy3.8'
          - os: ubuntu
            python-version: 'pypy3.9'
          - os: ubuntu
            python-version: 'pypy3.10'

    env:
      OS: ${{ matrix.os }}
      DEPS: yes

    runs-on: ${{ matrix.os }}-latest

    steps:
    - uses: actions/checkout@v4

    - uses: pdm-project/setup-pdm@v3
      with:
        python-version: ${{ matrix.python-version }}
        cache: true
        allow-python-prereleases: true

    - name: install deps
      run: |
        pdm venv create --with-pip --force $PYTHON
        pdm install -G testing -G email

    - run: pdm info && pdm list

    - run: 'pdm run python -c "import pydantic.version; print(pydantic.version.version_info())"'

    - run: mkdir coverage

    - name: test without deps
      # speed up by skipping this step on pypy
      if: "!startsWith(matrix.python-version, 'pypy')"
      run: make test
      env:
        COVERAGE_FILE: coverage/.coverage.${{ runner.os }}-py${{ matrix.python-version }}-without-deps
        CONTEXT: ${{ runner.os }}-py${{ matrix.python-version }}-without-deps

    - name: install extra deps
      run: pdm install -G testing-extra -G email

    - name: test with deps
      run: make test
      env:
        COVERAGE_FILE: coverage/.coverage.${{ runner.os }}-py${{ matrix.python-version }}-with-deps
        CONTEXT: ${{ runner.os }}-py${{ matrix.python-version }}-with-deps

    - name: store coverage files
      uses: actions/upload-artifact@v3
      with:
        name: coverage
        path: coverage

  test-fastapi:
    # If some tests start failing due to out-of-date schemas/validation errors/etc.,
    # update the `tests/test_fastapi.sh` script to exclude tests that have known-acceptable failures.
    name: test fastapi
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - name: set up python
        uses: actions/setup-python@v4
        with:
          python-version: '3.10'

      - name: test
        run: make test-fastapi

  test-plugin:
    name: test pydantic plugin
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - uses: pdm-project/setup-pdm@v3
        with:
          python-version: '3.11'
          cache: true

      - name: install deps
        run: |
          pdm venv create --with-pip --force $PYTHON
          pdm install -G testing

      - name: install example plugin
        run: pdm add ./tests/plugin

      - run: pdm run pytest ./tests/plugin
        env:
          TEST_PLUGIN: 1

      # uninstalling is necessary to avoid creating a pdm cache shared with other jobs
      # which includes the plugin
      - name: uninstall example plugin
        run: pdm remove ./tests/plugin

  test-mypy:
    name: mypy ${{ matrix.mypy-version }} / ${{ matrix.python-version }}
    runs-on: ubuntu-latest
    strategy:
      fail-fast: false
      matrix:
        # test recent mypy versions on 3.10 and mypy 1.0.1 on all supported python versions
        # if you change the value in the lockfile add the old value to this list
        mypy-version: ['1.0.1', 'lockfile', '1.2.0', '1.4.1', '1.5.1']
        python-version: ['3.10']
        include:
          - mypy-version: 'lockfile'
            python-version: '3.7'
          - mypy-version: 'lockfile'
            python-version: '3.8'
          - mypy-version: 'lockfile'
            python-version: '3.9'
          - mypy-version: 'lockfile'
            python-version: '3.11'
          # TODO: Once Python 3.7 is removed, and mypy is bumped on the lockfile, we can add 'lockfile' again.
          - mypy-version: '1.5.1'
            python-version: '3.12'

    steps:
    - uses: actions/checkout@v4

    - uses: pdm-project/setup-pdm@v3
      with:
        python-version: ${{ matrix.python-version }}
        cache: true
        allow-python-prereleases: true

    - name: install deps
      run: |
        pdm venv create --with-pip --force $PYTHON
        pdm install -G testing -G mypy

    - name: install mypy
      if: steps.cache.outputs.cache-hit != 'true'
      run: |
        if [ ${{ matrix.mypy-version }} == '1.5.1' ]; then
          # mypy 1.5.0 only supports 3.8 and newer, so adjust pyproject.toml
          sed -i "s/requires-python = '>=3.7'/requires-python = '>=3.8'/g" pyproject.toml
        fi
        if [ ${{ matrix.mypy-version }} != 'lockfile' ]; then
          pdm remove -G linting mypy && pdm remove -G mypy mypy && pdm add mypy==${{ matrix.mypy-version }}
        fi
        pdm list

    - run: mkdir coverage

    - name: run mypy tests
      run: pdm run coverage run -m pytest tests/mypy --test-mypy
      env:
        COVERAGE_FILE: coverage/.coverage.linux-py${{ matrix.python-version }}-mypy${{ matrix.mypy-version }}
        CONTEXT: linux-py${{ matrix.python-version }}-mypy${{ matrix.mypy-version }}

    - name: install node for pyright
      uses: actions/setup-node@v3
      with:
        node-version: '18'

    - name: install pyright
      run: npm install -g pyright@1.1.322  # try to keep this in sync with .pre-commit-config.yaml

    - name: run pyright tests
      run: make test-pyright
      env:
        COVERAGE_FILE: coverage/.coverage.linux-py${{ matrix.python-version }}-pyright
        CONTEXT: linux-py${{ matrix.python-version }}-pyright

    - name: store coverage files
      uses: actions/upload-artifact@v3
      with:
        name: coverage
        path: coverage

  coverage-combine:
    needs: [test, test-mypy]
    runs-on: ubuntu-latest

    steps:
      - uses: actions/checkout@v4

      - uses: actions/setup-python@v4
        with:
          python-version: '3.8'

      - name: get coverage files
        uses: actions/download-artifact@v3
        with:
          name: coverage
          path: coverage

      - run: pip install coverage[toml]

      - run: ls -la coverage
      - run: coverage combine coverage
      - run: coverage report
      - run: coverage html --show-contexts --title "pydantic coverage for ${{ github.sha }}"

      - name: Store coverage html
        uses: actions/upload-artifact@v3
        with:
          name: coverage-html
          path: htmlcov

  test-typing-extensions:
    name: test typing-extensions ${{ matrix.typing-extensions-version }} on Python ${{ matrix.python-version }}
    runs-on: ubuntu-latest
    strategy:
      fail-fast: false
      matrix:
        # test the oldest supported version and main
        typing-extensions-version: ['4.6.1', 'main']
        python-version: ['3.8', '3.9', '3.10', '3.11', '3.12']
        include:
          - typing-extensions-version: '4.6.1'
            python-version: '3.7'

    steps:
    - uses: actions/checkout@v4

    - uses: pdm-project/setup-pdm@v3
      with:
        python-version: ${{ matrix.python-version }}
        cache: true
        allow-python-prereleases: true

    - name: install deps
      run: |
        pdm venv create --with-pip --force $PYTHON
        pdm install -G testing -G email

    - name: install typing-extensions
      run: |
        if [ ${{ matrix.typing-extensions-version }} == 'main' ]; then
          # typing-extensions main only supports 3.8 and newer, so adjust pyproject.toml
          sed -i "s/requires-python = '>=3.7'/requires-python = '>=3.8'/g" pyproject.toml
          pdm remove typing-extensions && pdm add 'typing-extensions @ git+https://github.com/python/typing_extensions.git'
        else
          pdm remove typing-extensions && pdm add 'typing-extensions==${{ matrix.typing-extensions-version }}'
        fi
        pdm list
    - name: test
      run: make test

  # https://github.com/marketplace/actions/alls-green
  check:  # This job does nothing and is only used for the branch protection

    if: always()

    outputs:
      result: ${{ steps.all-green.outputs.result }}

    needs:
      - lint
      - docs-build
      - test
      - test-memray
      - test-mypy
      - test-fastapi
      - test-plugin

    runs-on: ubuntu-latest

    steps:
      - name: Decide whether the needed jobs succeeded or failed
        uses: re-actors/alls-green@release/v1
        id: all-green
        with:
          jobs: ${{ toJSON(needs) }}

  release:
    needs: [check]
    if: needs.check.outputs.result == 'success' && startsWith(github.ref, 'refs/tags/')
    runs-on: ubuntu-latest
    environment: release

    permissions:
      id-token: write

    outputs:
      pydantic-version: ${{ steps.check-tag.outputs.VERSION }}

    steps:
      - uses: actions/checkout@v4

      - name: set up python
        uses: actions/setup-python@v4
        with:
          python-version: '3.10'

      - name: install
        run: pip install -U build

      - name: check version
        id: check-tag
        uses: samuelcolvin/check-python-version@v4.1
        with:
          version_file_path: pydantic/version.py

      - name: build
        run: python -m build

      - name: Upload package to PyPI
        uses: pypa/gh-action-pypi-publish@release/v1

  send-tweet:
    name: Send tweet
    needs: [release]
    if: needs.release.result == 'success'
    runs-on: ubuntu-latest

    steps:
      - uses: actions/setup-python@v4
        with:
          python-version: '3.10'
      - name: Install dependencies
        run: pip install tweepy==4.14.0
      - name: Send tweet
        shell: python
        run: |
          import os
          import tweepy

          client = tweepy.Client(
              access_token=os.getenv("TWITTER_ACCESS_TOKEN"),
              access_token_secret=os.getenv("TWITTER_ACCESS_TOKEN_SECRET"),
              consumer_key=os.getenv("TWITTER_CONSUMER_KEY"),
              consumer_secret=os.getenv("TWITTER_CONSUMER_SECRET"),
          )
          version = os.getenv("VERSION").strip('"')
          tweet = os.getenv("TWEET").format(version=version)
          client.create_tweet(text=tweet)
        env:
          VERSION: ${{ needs.release.outputs.pydantic-version }}
          TWEET: |
            Pydantic version {version} is out! 🎉

            https://github.com/pydantic/pydantic/releases/tag/v{version}
          TWITTER_CONSUMER_KEY: ${{ secrets.TWITTER_CONSUMER_KEY }}
          TWITTER_CONSUMER_SECRET: ${{ secrets.TWITTER_CONSUMER_SECRET }}
          TWITTER_ACCESS_TOKEN: ${{ secrets.TWITTER_ACCESS_TOKEN }}
          TWITTER_ACCESS_TOKEN_SECRET: ${{ secrets.TWITTER_ACCESS_TOKEN_SECRET }}
