diff --git a/.github/workflows/cd.yml b/.github/workflows/cd.yml index 2c834b2..ddfbc07 100644 --- a/.github/workflows/cd.yml +++ b/.github/workflows/cd.yml @@ -8,6 +8,9 @@ on: jobs: upload: runs-on: ubuntu-latest + permissions: + contents: read + id-token: write steps: - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7 @@ -24,12 +27,27 @@ jobs: python3 -m pip install setuptools build twine python3 -m pip install . - # Build and upload to PyPI - - name: "Builds and uploads to PyPI" + - name: Build distribution run: | python3 -m build python3 -m twine check dist/* - python3 -m twine upload dist/* + + - name: Publish to PyPI env: - TWINE_USERNAME: __token__ - TWINE_PASSWORD: ${{ secrets.PYPI_TOKEN }} + PYPI_OIDC_AUDIENCE: pypi + run: | + set -euo pipefail + + oidc_response=$(curl --fail-with-body --silent --show-error \ + -H "Authorization: bearer ${ACTIONS_ID_TOKEN_REQUEST_TOKEN}" \ + "${ACTIONS_ID_TOKEN_REQUEST_URL}&audience=${PYPI_OIDC_AUDIENCE}") + oidc_token=$(jq --raw-output '.value' <<< "${oidc_response}") + + token_response=$(curl --fail-with-body --silent --show-error \ + -X POST https://pypi.org/_/oidc/mint-token \ + -H 'Content-Type: application/json' \ + --data "$(jq --null-input --arg token "${oidc_token}" '{token: $token}')") + api_token=$(jq --raw-output '.token' <<< "${token_response}") + + echo "::add-mask::${api_token}" + TWINE_USERNAME=__token__ TWINE_PASSWORD="${api_token}" python3 -m twine upload dist/* diff --git a/mercadopago/resources/order_automatic_payments.py b/mercadopago/resources/order_automatic_payments.py index 15bdbb2..40a8add 100644 --- a/mercadopago/resources/order_automatic_payments.py +++ b/mercadopago/resources/order_automatic_payments.py @@ -25,3 +25,4 @@ class OrderAutomaticPayments: retries: Optional[int] = None schedule_date: Optional[str] = None due_date: Optional[str] = None + subscription: Optional[dict] = None diff --git a/tests/test_order.py b/tests/test_order.py index e56a30b..256a44b 100644 --- a/tests/test_order.py +++ b/tests/test_order.py @@ -1,6 +1,9 @@ """Unit tests for the Order resource using a mock HTTP client.""" +from dataclasses import asdict import unittest +from mercadopago.resources.order_automatic_payments import OrderAutomaticPayments + from tests.base_client_test import BaseClientTest @@ -146,6 +149,25 @@ def test_create_raises_for_non_dict(self): with self.assertRaises(ValueError): self.sdk.order().create("not-a-dict") + def test_automatic_payments_subscription_payload(self): + automatic_payments = OrderAutomaticPayments( + subscription={ + "id": "subscription-1", + "sequence": {"number": 1, "total": 12}, + "invoice": { + "id": "invoice-1", + "billing_date": "2026-08-26", + "period": {"interval": 1, "type": "month"}, + }, + } + ) + + payload = asdict(automatic_payments) + + self.assertEqual("subscription-1", payload["subscription"]["id"]) + self.assertEqual(12, payload["subscription"]["sequence"]["total"]) + self.assertEqual("month", payload["subscription"]["invoice"]["period"]["type"]) + if __name__ == "__main__": unittest.main() diff --git a/tests/test_payment.py b/tests/test_payment.py index 7b1646d..0ea56ae 100644 --- a/tests/test_payment.py +++ b/tests/test_payment.py @@ -32,6 +32,28 @@ def test_get(self): self.assertEqual("6351", resp["card"]["last_four_digits"]) self.mock_http.get.assert_called_once() + def test_get_preserves_expanded_gateway_network_data(self): + self.mock_get( + { + "expanded": { + "gateway": { + "reference": { + "network_data": { + "transaction_id": "ABC123", + "transaction_link_id": "550e8400", + } + } + } + } + } + ) + + result = self.sdk.payment().get(17014025134) + + network_data = result["response"]["expanded"]["gateway"]["reference"]["network_data"] + self.assertEqual("ABC123", network_data["transaction_id"]) + self.assertEqual("550e8400", network_data["transaction_link_id"]) + def test_search(self): fixture = self.load_fixture("payment_search.json") self.mock_get(fixture)