рдХрдВрдЬреНрдпреВрдорд░ рдбреНрд░рд┐рд╡реНрдб рдХреЙрдиреНрдЯреНрд░реИрдХреНрдЯреНрд╕ рдпрд╛ рдЧрд┐рдЯрд▓реИрдм рд╕реАрдЖрдИ-рдЖрдЗрдб рдХреНрдпреВрдП рдЯреЗрд╕реНрдЯ рдСрдЯреЛрдореЗрд╢рди

рдЗрд╕ рдкреНрд░рдХрд╛рд╢рди рдХреЗ рдЙрджреНрджреЗрд╢реНрдп рд╣реИрдВ :


  • рдЙрдкрднреЛрдХреНрддрд╛ рдкреНрд░рд╡реГрддреНрдд рд╕рдВрд╡рд┐рджрд╛ (рд╕реАрдбреАрд╕реА) рдХрд╛ рд╕рдВрдХреНрд╖рд┐рдкреНрдд рдкрд░рд┐рдЪрдп
  • CDI- рдЖрдзрд╛рд░рд┐рдд CI рдкрд╛рдЗрдкрд▓рд╛рдЗрди рдХреЙрдиреНрдлрд╝рд┐рдЧрд░ рдХрд░реЗрдВ

рдЙрдкрднреЛрдХреНрддрд╛ рдкреНрд░реЗрд░рд┐рдд рдЕрдиреБрдмрдВрдз


рдЗрд╕ рднрд╛рдЧ рдореЗрдВ, рд╣рдо рд╕реАрдбреАрд╕реА рдХреЗ рдореБрдЦреНрдп рдмрд┐рдВрджреБрдУрдВ рдкрд░ рдЬрд╛рдПрдВрдЧреЗред рдЕрдиреБрдмрдВрдз рдкрд░реАрдХреНрд╖рдг рдХреЗ рд╡рд┐рд╖рдп рдкрд░ рдпрд╣ рд▓реЗрдЦ рд╕рдВрдкреВрд░реНрдг рдирд╣реАрдВ рд╣реИред рдПрдХ рд╣реА Habr├й рдкрд░ рдЗрд╕ рд╡рд┐рд╖рдп рдкрд░ рдкрд░реНрдпрд╛рдкреНрдд рдорд╛рддреНрд░рд╛ рдореЗрдВ рд╕рд╛рдордЧреНрд░реА рд╣реИред


рдЬрд╛рд░реА рд░рдЦрдиреЗ рдХреЗ рд▓рд┐рдП, рд╣рдореЗрдВ рд╕реАрдбреАрд╕реА рдХреЗ рдореБрдЦреНрдп рдкреНрд░рд╛рд╡рдзрд╛рдиреЛрдВ рд╕реЗ рдкрд░рд┐рдЪрд┐рдд рд╣реЛрдирд╛ рдЪрд╛рд╣рд┐рдП:


  • рд╕рдВрдкрд░реНрдХ рдкрд░реАрдХреНрд╖рдг рдорд╛рдЗрдХ рдХреЛрд╣рди рдкрд┐рд░рд╛рдорд┐рдб рдХреЗ рдЕрдиреБрд╕рд╛рд░ рдпреВрдирд┐рдЯ рдЯреЗрд╕реНрдЯ рд╕реЗ рдКрдкрд░ рд╕реЗрд╡рд╛ / рдПрдХреАрдХрд░рдг рдЯреЗрд╕реНрдЯ рд╕реНрддрд░ рдкрд░ рд╣реИ ред
  • рдЕрдиреБрдмрдВрдз рдкрд░реАрдХреНрд╖рдг рддрдм рд▓рд╛рдЧреВ рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИ рдЬрдм 2 (рдпрд╛ рдЕрдзрд┐рдХ) рд╕реЗрд╡рд╛рдПрдВ рд╣реЛрддреА рд╣реИрдВ рдЬреЛ рдПрдХ рджреВрд╕рд░реЗ рдХреЗ рд╕рд╛рде рдмрд╛рддрдЪреАрдд рдХрд░рддреА рд╣реИрдВред
  • рдЙрдкрднреЛрдХреНрддрд╛ рд╕рдВрдЪрд╛рд▓рд┐рдд рджреГрд╖реНрдЯрд┐рдХреЛрдг рдХрд╛ рдЕрд░реНрде рд╣реИ рдХрд┐ рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рдореЗрдВ рдкрд╣рд▓рд╛ рдХрджрдо рдЙрдкрднреЛрдХреНрддрд╛ рдкрдХреНрд╖ рдкрд░ рдПрдХ рдкрд░реАрдХреНрд╖рдг рд▓рд┐рдЦрдирд╛ рд╣реИред рдкрд░реАрдХреНрд╖рдг рдХрд╛ рдкрд░рд┐рдгрд╛рдо рдПрдХ рдЬрд╕рди-рд╕реНрд╡рд░реВрдкрд┐рдд рд╕рдВрдзрд┐ (рдЕрдиреБрдмрдВрдз) рд╣реИ рдЬреЛ рдЙрдкрднреЛрдХреНрддрд╛ рдХреЗ рдмреАрдЪ рдмрд╛рддрдЪреАрдд рдХрд╛ рд╡рд░реНрдгрди рдХрд░рддрд╛ рд╣реИ (рдЬреИрд╕реЗ рд╡реЗрдм рдЗрдВрдЯрд░рдлрд╝реЗрд╕ / рдореЛрдмрд╛рдЗрд▓ рдЗрдВрдЯрд░рдлрд╝реЗрд╕: рдПрдХ рд╕реЗрд╡рд╛ рдЬреЛ рдХреБрдЫ рдбреЗрдЯрд╛ рдкреНрд░рд╛рдкреНрдд рдХрд░рдирд╛ рдЪрд╛рд╣рддрд╛ рд╣реИ) рдФрд░ рдкреНрд░рджрд╛рддрд╛ (рдЬреИрд╕реЗ- рд╕рд░реНрд╡рд░ рдПрдкреАрдЖрдИ: рдПрдХ рд╕реЗрд╡рд╛ рдбреЗрдЯрд╛ рдкреНрд░рджрд╛рди рдХрд░рддреА рд╣реИ)
  • рдЕрдЧрд▓рд╛ рдХрджрдо рдкреНрд░рджрд╛рддрд╛ рдХреЗ рд╕рд╛рде рдЕрдиреБрдмрдВрдз рдХреА рдЬрд╛рдВрдЪ рдХрд░рдирд╛ рд╣реИред рдпрд╣ рдкреИрдХреНрдЯ рдврд╛рдВрдЪреЗ рджреНрд╡рд╛рд░рд╛ рдкреВрд░реА рддрд░рд╣ рд╕реЗ рд▓рд╛рдЧреВ рдХрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИред

рддреЛ, рдЪрд▓реЛ рдЙрдкрднреЛрдХреНрддрд╛ рдкрдХреНрд╖ рдкрд░реАрдХреНрд╖рдг рдХреЗ рд╕рд╛рде рд╢реБрд░реВ рдХрд░рддреЗ рд╣реИрдВред рдореИрдВрдиреЗ рдкреИрдХреНрдЯрдореИрди рдХрд╛ рдЗрд╕реНрддреЗрдорд╛рд▓ рдХрд┐рдпрд╛ред рдпрд╣ рдкрд░реАрдХреНрд╖рдг рдЬреИрд╕рд╛ рджрд┐рдЦрддрд╛ рд╣реИ:


import pytest from pactman import Like from model.client import Client @pytest.fixture() def consumer(pact): return Client(pact.uri) def test_app(pact, consumer): expected = '123456789' (pact .given('provider in some state') .upon_receiving("request to get user's phone number") .with_request( method='GET', path=f'/phone/john', ) .will_respond_with(200, body=Like(expected)) .given('provider in some state') .upon_receiving("request to get non-existent user's phone number") .with_request( method='GET', path=f'/phone/micky' ) .will_respond_with(404) ) with pact: consumer.get_users_phone(user='john', host=pact.uri) consumer.get_users_phone(user='micky', host=pact.uri) 

Pact DSL рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддреЗ рд╣реБрдП, рд╣рдо рдЕрдиреБрд░реЛрдз / рдкреНрд░рддрд┐рдХреНрд░рд┐рдпрд╛ рдЗрдВрдЯрд░реИрдХреНрд╢рди рдХрд╛ рд╡рд░реНрдгрди рдХрд░рддреЗ рд╣реИрдВред рдкрд░реАрдХреНрд╖рдг рд╢реБрд░реВ рдХрд░рдиреЗ рдХреЗ рдмрд╛рдж, рд╣рдо рдПрдХ рдирдИ рдлрд╝рд╛рдЗрд▓ ({рдЙрдкрднреЛрдХреНрддрд╛} - {рдкреНрд░рджрд╛рддрд╛} -pact.json) рдкреНрд░рд╛рдкреНрдд рдХрд░рддреЗ рд╣реИрдВ:


 { "consumer": { "name": 'basic_client' }, "provider": { "name": 'basic_flask_app' }, "interactions": [ { "providerStates": [ { "name": "provider in some state", "params": {} } ], "description": "request to get user's phone number", "request": { "method": "GET", "path": "/phone/john" }, "response": { "status": 200, "body": "123456789", "matchingRules": { "body": { "$": { "matchers": [ { "match": "type" } ] } } } } }, { "providerStates": [ { "name": "provider in some state", "params": {} } ], "description": "request to get non-existent user's phone number", "request": { "method": "GET", "path": "/phone/micky" }, "response": { "status": 404 } } ], "metadata": { "pactSpecification": { "version": "3.0.0" } } } 

рдЕрдЧрд▓рд╛, рд╣рдореЗрдВ рд╕рддреНрдпрд╛рдкрди рдХреЗ рд▓рд┐рдП рдкреНрд░рджрд╛рддрд╛ рдХреЛ рд╕рдВрдзрд┐ рдХреЛ рдкрд╛рд╕ рдХрд░рдирд╛ рд╣реЛрдЧрд╛ред рдпрд╣ рдкреИрдХреНрдЯ рдмреНрд░реЛрдХрд░ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИред


рдкреИрдХреНрдЯ рдмреНрд░реЛрдХрд░ рдХреБрдЫ рдЕрддрд┐рд░рд┐рдХреНрдд рд╡рд┐рд╢реЗрд╖рддрд╛рдУрдВ рдХреЗ рд╕рд╛рде рдПрдХ рдЕрдиреБрдмрдВрдз рднрдВрдбрд╛рд░ рд╣реИ рдЬреЛ рд╣рдореЗрдВ рд╕реЗрд╡рд╛ рд╕рдВрд╕реНрдХрд░рдгреЛрдВ рдХреА рд╕рдВрдЧрддрддрд╛ рдХреЛ рдЯреНрд░реИрдХ рдХрд░рдиреЗ рдХреА рдЕрдиреБрдорддрд┐ рджреЗрддрд╛ рд╣реИ, рд╕рд╛рде рд╣реА рд╕рд╛рде рдиреЗрдЯрд╡рд░реНрдХ рдЖрд░реЗрдЦ (рд╕реЗрд╡рд╛ рдЗрдВрдЯрд░реИрдХреНрд╢рди) рднреА рдЙрддреНрдкрдиреНрди рдХрд░рддрд╛ рд╣реИред


рд╕рдВрдзрд┐ рджрд▓рд╛рд▓
рдЫрд╡рд┐


рд╕рдВрдзрд┐
рдЫрд╡рд┐


рд╕рдВрд╕реНрдХрд░рдг рдореИрдЯреНрд░рд┐рдХреНрд╕
рдЫрд╡рд┐


рдкреНрд░рджрд╛рддрд╛ рд╕рддреНрдпрд╛рдкрди


рдкрд░реАрдХреНрд╖рдг рдХрд╛ рдпрд╣ рд╣рд┐рд╕реНрд╕рд╛ рдкреВрд░реА рддрд░рд╣ рд╕реЗ рд░реВрдкрд░реЗрдЦрд╛ рджреНрд╡рд╛рд░рд╛ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИред рд╕рддреНрдпрд╛рдкрди рдХреЗ рдмрд╛рдж, рдкрд░рд┐рдгрд╛рдо рдкреИрдХреНрдЯ рдмреНрд░реЛрдХрд░ рдХреЛ рд╡рд╛рдкрд╕ рднреЗрдЬ рджрд┐рдП рдЬрд╛рддреЗ рд╣реИрдВред


 provider-verifier_1 | Verifying a pact between basic_client and basic_flask_app provider-verifier_1 | Given provider in some state provider-verifier_1 | request to get user's phone number provider-verifier_1 | with GET /phone/john provider-verifier_1 | returns a response which provider-verifier_1 | WARN: Skipping set up for provider state 'provider in some state' for consumer 'basic_client' as there is no --provider-states-setup-url specified. provider-verifier_1 | has status code 200 provider-verifier_1 | has a matching body provider-verifier_1 | Given provider in some state provider-verifier_1 | request to get non-existent user's phone number provider-verifier_1 | with GET /phone/micky provider-verifier_1 | returns a response which provider-verifier_1 | WARN: Skipping set up for provider state 'provider in some state' for consumer 'basic_client' as there is no --provider-states-setup-url specified. provider-verifier_1 | has status code 404 provider-verifier_1 | provider-verifier_1 | 2 interactions, 0 failures 

рдкрд╛рдЗрдкрд▓рд╛рдЗрди рдореЗрдВ рдкрд░реАрдХреНрд╖рдг рдХреЗ рджреЛрдиреЛрдВ рд╣рд┐рд╕реНрд╕реЛрдВ рдХреЛ рдЪрд▓рд╛рдирд╛


рдЕрдм рдЬрдм рдХреЙрдиреНрдЯреНрд░реИрдХреНрдЯ рдЯреЗрд╕реНрдЯрд┐рдВрдЧ рдХреЗ рджреЛрдиреЛрдВ рд╣рд┐рд╕реНрд╕реЗ рдбрд┐рд╕рд╛рдЗрдб рд╣реЛ рдЧрдП рд╣реИрдВ, рддреЛ рдЙрдиреНрд╣реЗрдВ рд╣рд░ рдХрдорд┐рдЯрдореЗрдВрдЯ рдореЗрдВ рдЪрд▓рд╛рдирд╛ рдЕрдЪреНрдЫрд╛ рд░рд╣реЗрдЧрд╛ред рдпрд╣ рд╡рд╣ рдЬрдЧрд╣ рд╣реИ рдЬрд╣рд╛рдБ рдЧрд┐рдЯрд▓рдм рд╕реАрдЖрдИ рдмрдЪрд╛рд╡ рдХреЗ рд▓рд┐рдП рдЖрддрд╛ рд╣реИред рдкрд╛рдЗрдкрд▓рд╛рдЗрди рдиреМрдХрд░рд┐рдпреЛрдВ рдореЗрдВ .gitlab-ci.yml рд╡рд░реНрдгрди рдХрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИред рдЗрд╕рд╕реЗ рдкрд╣рд▓реЗ рдХрд┐ рд╣рдо рдкрд╛рдЗрдкрд▓рд╛рдЗрди рдкрд░ рдЖрдЧреЗ рдмрдврд╝реЗрдВ, рд╣рдореЗрдВ рдЧрд┐рдЯрд▓реИрдм рд░рдирд░ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдХреБрдЫ рд╢рдмреНрдж рдХрд╣рдиреЗ рдХреА рдЬрд╝рд░реВрд░рдд рд╣реИ, рдЬреЛ рдПрдХ рдУрдкрди-рд╕реЛрд░реНрд╕ рдкреНрд░реЛрдЬреЗрдХреНрдЯ рд╣реИ, рдФрд░ рдЗрд╕рдХрд╛ рдЙрдкрдпреЛрдЧ рдЬреЙрдм рдЪрд▓рд╛рдиреЗ рдФрд░ рд░рд┐рдЬрд▓реНрдЯреНрд╕ рдХреЛ рд╡рд╛рдкрд╕ рдЧреАрддрд╛рд▓рд╛рдм рдореЗрдВ рднреЗрдЬрдиреЗ рдХреЗ рд▓рд┐рдП рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИред рдиреМрдХрд░рд┐рдпреЛрдВ рдХреЛ рд╕реНрдерд╛рдиреАрдп рд░реВрдк рд╕реЗ рдпрд╛ рдбреЙрдХрдЯрд░ рдХрдВрдЯреЗрдирд░реЛрдВ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рдЪрд▓рд╛рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИред рд╣рдорд╛рд░реЗ рдкреНрд░реЛрдЬреЗрдХреНрдЯ рдореЗрдВ рд╣рдо рдбреЙрдХрд░ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддреЗ рд╣реИрдВред рдкрд░реАрдХреНрд╖рдг рдмреБрдирд┐рдпрд╛рджреА рдврд╛рдВрдЪреЗ рдХреЛ рдХрдВрдЯреЗрдирд░реЛрдВ рдореЗрдВ рд▓рд╛рдЧреВ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ рдФрд░ рдкрд░рд┐рдпреЛрдЬрдирд╛ рдХреЗ рдореВрд▓ рдореЗрдВ рд╕реНрдерд┐рдд docker-compose.yml рдореЗрдВ рд╡рд░реНрдгрд┐рдд рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИред


 version: '2' services: basic-flask-app: image: registry.gitlab.com/tknino69/basic_flask_app:latest ports: - 5005:5005 postgres: image: postgres ports: - 5432:5432 env_file: - test-setup.env volumes: - db-data:/var/lib/postgresql/data/pgdata pactbroker: image: dius/pact-broker links: - postgres ports: - 80:80 env_file: - test-setup.env provider-states: image: registry.gitlab.com/tknino69/cdc/provider-states:latest build: provider-states ports: - 5000:5000 consumer-test: image: registry.gitlab.com/tknino69/cdc/consumer-test:latest command: ["sh", "-c", "find -name '*.pyc' -delete && pytest $${TEST}"] links: - pactbroker environment: - CONSUMER_VERSION=$CI_COMMIT_SHA provider-verifier: image: registry.gitlab.com/tknino69/cdc/provider-verifier:latest build: provider-verifier ports: - 5001:5000 links: - pactbroker depends_on: - consumer-test - provider-states command: ['sh', '-c', 'find -name "*.pyc" -delete && CONSUMER_VERSION=`curl --header "PRIVATE-TOKEN:$${API_TOKEN}" https://gitlab.com/api/v4/projects/$${BASIC_CLIENT}/repository/commits | jq ".[0] .id" | sed -e "s/\x22//g"` && echo $${CONSUMER_VERSION} && pact-provider-verifier $${PACT_BROKER}/pacts/provider/$${PROVIDER}/consumer/$${CONSUMER}/version/$${CONSUMER_VERSION} --provider-base-url=$${BASE_URL} --pact-broker-base-url=$${PACT_BROKER} --provider=$${PROVIDER} --consumer-version-tag=$${CONSUMER_VERSION} --provider-app-version=$${PROVIDER_VERSION} -v --publish-verification-results=PUBLISH_VERIFICATION_RESULTS'] environment: - PROVIDER_VERSION=$CI_COMMIT_SHA - API_TOKEN=$API_TOKEN env_file: - test-setup.env volumes: db-data: 

рдЗрд╕рд▓рд┐рдП, рд╣рдорд╛рд░реЗ рдкрд╛рд╕ рдРрд╕реА рд╕реЗрд╡рд╛рдПрдБ рд╣реИрдВ рдЬреЛ рдЖрд╡рд╢реНрдпрдХрддрд╛рдиреБрд╕рд╛рд░ рдХрдВрдЯреЗрдирд░ рдореЗрдВ рдЪрд▓рддреА рд╣реИрдВред


рд╕реЗрд╡рд╛ рдкреНрд░рджрд╛рддрд╛:


 basic-flask-app: image: registry.gitlab.com/tknino69/basic_flask_app:latest ports: - 5005:5005 

рдкреИрдХреНрдЯ рдмреНрд░реЛрдХрд░ рдФрд░ рдЙрд╕рдХреЗ рдбреЗрдЯрд╛рдмреЗрд╕ред рд╡реЙрд▓реНрдпреВрдо рд╣рдореЗрдВ рдкреИрдХреНрдЯреНрд╕ рдФрд░ рдкреНрд░рджрд╛рддрд╛ рд╕рддреНрдпрд╛рдкрди рдХреЗ рдкрд░рд┐рдгрд╛рдореЛрдВ рдХреЗ рд▓рд┐рдП рдПрдХ рд╕реНрдерд╛рдпреА рднрдВрдбрд╛рд░ рд░рдЦрдиреЗ рдХреА рдЕрдиреБрдорддрд┐ рджреЗрддреЗ рд╣реИрдВ:


 postgres: image: postgres ports: - 5432:5432 env_file: - test-setup.env volumes: - db-data:/var/lib/postgresql/data/pgdata pactbroker: image: dius/pact-broker links: - postgres ports: - 80:80 env_file: - test-setup.env 

рд╕реЗрд╡рд╛ рдкреНрд░рджрд╛рддрд╛ рд░рд╛рдЬреНрдпред рд╡реНрдпрд╡рд╣рд╛рд░ рдореЗрдВ, рдЗрд╕реЗ рдкреНрд░рджрд╛рддрд╛ рдХреЛ рдПрдХ рдирд┐рд╢реНрдЪрд┐рдд рд╕реНрдерд┐рддрд┐ рдореЗрдВ рд▓рд╛рдирд╛ рдЪрд╛рд╣рд┐рдП (рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, рдбреЗрдЯрд╛рдмреЗрд╕ рдореЗрдВ рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдкреНрд░рд╛рдкреНрдд рдХрд░реЗрдВ)ред рд╣рд╛рд▓рд╛рдВрдХрд┐, рд╣рдорд╛рд░реЗ рдЙрджрд╛рд╣рд░рдг рдореЗрдВ, рдпрд╣ рдХреЗрд╡рд▓ рдПрдХ рдбрдореА рдлрд╝рдВрдХреНрд╢рди рдХрд░рддрд╛ рд╣реИред


 provider-states: image: registry.gitlab.com/tknino69/cdc/provider-states:latest build: provider-states ports: - 5000:5000 

рдПрдХ рд╕реЗрд╡рд╛ рдЬреЛ рдЙрдкрднреЛрдХреНрддрд╛ рдкрд░реАрдХреНрд╖рдг рдЪрд▓рд╛рддрд╛ рд╣реИред рдХрдВрдЯреЗрдирд░ find -name '* .pyc' -delete && pytest $$ {TEST} рд╡рд╛рд▓реЗ рдХрдорд╛рдВрдб рдореЗрдВ рдзреНрдпрд╛рди рджреЗрдВ find -name '* .pyc' -delete && pytest $$ {TEST}


 consumer-test: image: registry.gitlab.com/tknino69/cdc/consumer-test:latest command: ["sh", "-c", "find -name '*.pyc' -delete && pytest $${TEST}"] links: - pactbroker environment: - CONSUMER_VERSION=$CI_COMMIT_SHA 

рд╕реЗрд╡рд╛ рдкреНрд░рджрд╛рддрд╛ рд╕рддреНрдпрд╛рдкрдирдХрд░реНрддрд╛:


 provider-verifier: image: registry.gitlab.com/tknino69/cdc/provider-verifier:latest build: provider-verifier ports: - 5001:5000 links: - pactbroker depends_on: - consumer-test - provider-states command: ['sh', '-c', 'find -name "*.pyc" -delete && CONSUMER_VERSION=`curl --header "PRIVATE-TOKEN:$${API_TOKEN}" https://gitlab.com/api/v4/projects/$${BASIC_CLIENT}/repository/commits | jq ".[0] .id" | sed -e "s/\x22//g"` && echo $${CONSUMER_VERSION} && pact-provider-verifier $${PACT_BROKER}/pacts/provider/$${PROVIDER}/consumer/$${CONSUMER}/version/$${CONSUMER_VERSION} --provider-base-url=$${BASE_URL} --pact-broker-base-url=$${PACT_BROKER} --provider=$${PROVIDER} --consumer-version-tag=$${CONSUMER_VERSION} --provider-app-version=$${PROVIDER_VERSION} -v --publish-verification-results=PUBLISH_VERIFICATION_RESULTS'] environment: - PROVIDER_VERSION=$CI_COMMIT_SHA - API_TOKEN=$API_TOKEN env_file: - test-setup.env 

рдЙрдкрднреЛрдХреНрддрд╛ рдкрд╛рдЗрдкрд▓рд╛рдЗрди
рдЙрдкрднреЛрдХреНрддрд╛ рдкрд░рд┐рдпреЛрдЬрдирд╛ рдХреЗ рдореВрд▓ рдореЗрдВ .gitlab-ci.yml рдЙрдкрднреЛрдХреНрддрд╛ рдкрдХреНрд╖ рдкрд░ рдЪрд▓рдиреЗ рд╡рд╛рд▓реА рдкреНрд░рдХреНрд░рд┐рдпрд╛рдУрдВ рдХрд╛ рд╡рд░реНрдгрди рдХрд░рддрд╛ рд╣реИ:


 image: gitlab/dind:latest variables: TEST: 'tests/docker-compose.app.yml' CONSUMER_VERSION: $CI_COMMIT_SHA BASIC_APP: '11993024' services: - gitlab/gitlab-runner:latest before_script: - docker login -u $GIT_USER -p $GIT_PASS registry.gitlab.com stages: - clone_test - get_broker_up - test - verify_provider - clean_up clone test: tags: - cdc stage: clone_test script: - git clone https://$GIT_USER:$GIT_PASS@gitlab.com/tknino69/cdc.git && ls -ali artifacts: paths: - cdc/ broker: tags: - cdc stage: get_broker_up script: - cd cdc && docker-compose -f docker-compose.yml up -d pactbroker dependencies: - clone test test: tags: - cdc stage: test script: - cd cdc && CONSUMER_VERSION=$CONSUMER_VERSION docker-compose -f docker-compose.yml -f $TEST up consumer-test dependencies: - clone test provider verification: tags: - cdc stage: verify_provider script: - curl -X POST -F token=$CI_JOB_TOKEN -F ref=master https://gitlab.com/api/v4/projects/$BASIC_APP/trigger/pipeline when: on_success clean up: tags: - cdc stage: clean_up script: - cd cdc && docker-compose stop consumer-test dependencies: - clone test 

рдпрд╣рд╛рдБ рдирд┐рдореНрди рд╣реЛрддрд╛ рд╣реИ:


before_script рд╣рдо $ GIT_USER рдФрд░ $ GIT_PASS рдЪрд░ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рдЕрдкрдиреА gitlab рд░рдЬрд┐рд╕реНрдЯреНрд░реА рдореЗрдВ рд▓реЙрдЧ рдЗрди рдХрд░рддреЗ рд╣реИрдВ рдЬреЛ рд╣рдордиреЗ рд╕реЗрдЯрд┐рдВрдЧреНрд╕> CI / CD рдореЗрдВ рд╕реЗрдЯ рдХрд┐рдпрд╛ рд╣реИ
рдЫрд╡рд┐


  • рдЕрдЧрд▓рд╛, рд╣рдо рдПрдХ рдкрд░реАрдХреНрд╖рдг рдкрд░рд┐рдпреЛрдЬрдирд╛ рдХрд╛ рдХреНрд▓реЛрди рдмрдирд╛рддреЗ рд╣реИрдВ
  • рдЕрдЧрд▓реЗ рдЪрд░рдг рдореЗрдВ, рд╣рдо рдкреИрдХреНрдЯ рдмреНрд░реЛрдХрд░ рдмрдврд╝рд╛рддреЗ рд╣реИрдВ
  • рдлрд┐рд░ рдХрдВрдЬреНрдпреВрдорд░ рдЯреЗрд╕реНрдЯ рд╢реБрд░реВ рд╣реЛрддрд╛ рд╣реИред
  • рдЙрд╕рдХреЗ рдмрд╛рдж, рдкреНрд░рджрд╛рддрд╛ рд╕рддреНрдпрд╛рдкрди рд╢реБрд░реВ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП Gitlab API рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░реЗрдВред
  • рдФрд░ рдЕрдВрдд рдореЗрдВ, рд╣рдо рдЦреБрдж рдХреЛ рд╕рд╛рдл рдХрд░рддреЗ рд╣реИрдВ

рдкреНрд░рджрд╛рддрд╛ рдкрд╛рдЗрдкрд▓рд╛рдЗрди
рдкреНрд░рджрд╛рддрд╛ рдкрд╛рдЗрдкрд▓рд╛рдЗрди рд╡рд┐рдиреНрдпрд╛рд╕ рдХреЛ рдкреНрд░рджрд╛рддрд╛ рдкрд░рд┐рдпреЛрдЬрдирд╛ рдХреА рдЬрдбрд╝ рдореЗрдВ .gitlab-ci.yml рдореЗрдВ рд╕рдВрдЧреНрд░рд╣реАрдд рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИред


 image: gitlab/dind:latest variables: TEST: 'tests/docker-compose.app.yml' PROVIDER_VERSION: $CI_COMMIT_SHA services: - gitlab/gitlab-runner:latest stages: - clone_test - provider_verification - clean_up clone test: tags: - cdc stage: clone_test script: - git clone https://$GIT_USER:$GIT_PASS@gitlab.com/tknino69/cdc.git artifacts: paths: - cdc/ verify provider: tags: - cdc stage: provider_verification before_script: - cd cdc - docker login -u $GIT_USER -p $GIT_PASS registry.gitlab.com && docker-compose -f docker-compose.yml up -d basic-flask-app script: - PROVIDER_VERSION=$PROVIDER_VERSION docker-compose -f docker-compose.yml -f $TEST up provider-verifier dependencies: - clone test .clean up: tags: - cdc stage: clean_up script: - cd cdc && docker-compose down --rmi local 

рдЙрдкрднреЛрдХреНрддрд╛ рдкрд╛рдЗрдкрд▓рд╛рдЗрди рдореЗрдВ, рд╣рдорд╛рд░реЗ рдкрд╛рд╕ рдХрдИ рдХрд╛рдо рд╣реИрдВ:


  • рдХреНрд▓реЛрди рдПрдХ рдкрд░реАрдХреНрд╖рдг рдкрд░рд┐рдпреЛрдЬрдирд╛
  • рдкреНрд░рджрд╛рддрд╛ рд╕рддреНрдпрд╛рдкрд┐рдд рдХрд░реЗрдВ
  • рд╣рдо рдЦреБрдж рдХреЛ рд╕рд╛рдл рдХрд░рддреЗ рд╣реИрдВ

рд╕рдВрдХреНрд╖реЗрдк :


  • рдкрд╛рдЗрдерди рдореЗрдВ рдПрдХ рдЕрдиреБрдмрдВрдз рдкрд░реАрдХреНрд╖рдг рд▓рд┐рдЦрд╛
  • рдбреЙрдХрдЯрд░ рдХрдВрдЯреЗрдирд░реЛрдВ рдореЗрдВ рдПрдХ рдкрд░реАрдХреНрд╖рдг рд╡рд╛рддрд╛рд╡рд░рдг рд╕реЗрдЯ рдХрд░реЗрдВ
  • рдЕрдиреБрдмрдВрдз рдкрд░реАрдХреНрд╖рдгреЛрдВ рдХреЗ рдЖрдзрд╛рд░ рдкрд░ рдХреЙрдиреНрдлрд╝рд┐рдЧрд░ рдХрд┐рдпрд╛ рдЧрдпрд╛ CI, рдЕрд░реНрдерд╛рдд рдЙрдкрднреЛрдХреНрддрд╛ рдкрд░рд┐рдпреЛрдЬрдирд╛ рдХреЗ рд▓рд┐рдП CI рдкрд╛рдЗрдкрд▓рд╛рдЗрди рд▓реЙрдиреНрдЪ рдХрд░реЗрдЧрд╛ ( рдЙрдкрднреЛрдХреНрддрд╛ рдкрдХреНрд╖ рдкрд░ : рдкрд░реАрдХреНрд╖рдг рд╡рд╛рддрд╛рд╡рд░рдг рдХрд╛ рдХреНрд▓реЛрдирд┐рдВрдЧ -> рдкреИрдХреНрдЯ рдмреНрд░реЛрдХрд░ рд╢реБрд░реВ рдХрд░рдирд╛ -> рдЙрдкрднреЛрдХреНрддрд╛ рдХрд╛ рдкрд░реАрдХреНрд╖рдг рдХрд░рдирд╛ - рдкреНрд░рджрд╛рддрд╛ рдкреНрд░рджрд╛рддрд╛ рд╕рддреНрдпрд╛рдкрди рд╢реБрд░реВ рдХрд░рдирд╛ -> рдкреНрд░рджрд╛рддрд╛ рдкрдХреНрд╖ рдкрд░ : рдкрд░реАрдХреНрд╖рдг рд╡рд╛рддрд╛рд╡рд░рдг рдХрд╛ рдХреНрд▓реЛрди рдХрд░рдирд╛ -> рдкреНрд░рджрд╛рддрд╛ рд╕рддреНрдпрд╛рдкрди)> рд╕рд╛рдл рдХрд░рдирд╛; )ред
    рдкреНрд░рджрд╛рддрд╛ рдкрд░рд┐рдпреЛрдЬрдирд╛ рдХреЗ рд▓рд┐рдП рдкреНрд░рджрд╛рддрд╛ рд╕рддреНрдпрд╛рдкрди рд╕реБрдирд┐рд╢реНрдЪрд┐рдд рдХрд░рддрд╛ рд╣реИ рдХрд┐ рдкреНрд░рджрд╛рддрд╛ рд╕рдордЭреМрддреЗ рдХрд╛ рдЕрдиреБрдкрд╛рд▓рди рдХрд░рддрд╛ рд╣реИ

рдЖрдкрдХрд╛ рдзреНрдпрд╛рди рдХреЗ рд▓рд┐рдП рдзрдиреНрдпрд╡рд╛рджред

Source: https://habr.com/ru/post/hi451132/


All Articles