Harden pre-production deployment with external environment and preflights
This commit is contained in:
@@ -0,0 +1,62 @@
|
||||
"""Read-only bug-report connectivity check. Never emits response bodies or tokens."""
|
||||
import re
|
||||
from urllib.parse import quote, urlsplit
|
||||
|
||||
import httpx
|
||||
|
||||
from gitea_service import GiteaConfig, GiteaError
|
||||
|
||||
|
||||
def check(config=None, transport=None):
|
||||
config = config or GiteaConfig.from_env()
|
||||
config.validate()
|
||||
try:
|
||||
parsed = urlsplit(config.url)
|
||||
if (not parsed.hostname or re.search(r'\s|\\', config.url) or
|
||||
parsed.port == 0 or config.owner in {'.', '..'} or config.repo in {'.', '..'}):
|
||||
raise GiteaError('configuration')
|
||||
except ValueError:
|
||||
raise GiteaError('configuration') from None
|
||||
try:
|
||||
with httpx.Client(base_url=config.url.rstrip('/') + '/api/v1/',
|
||||
headers={'Authorization': 'token ' + config.token,
|
||||
'Accept': 'application/json'},
|
||||
timeout=httpx.Timeout(15.0, connect=5.0),
|
||||
follow_redirects=False, trust_env=False, transport=transport) as client:
|
||||
identity = client.get('user')
|
||||
identity.raise_for_status()
|
||||
user = identity.json()
|
||||
if not isinstance(user, dict) or not isinstance(user.get('login'), str):
|
||||
raise GiteaError('invalid_response')
|
||||
if user['login'] != 'metalcircle-bot':
|
||||
raise GiteaError('wrong_account')
|
||||
# Test the issue resource using the existing write:issue scope.
|
||||
# GET repository metadata would require an additional read:repository scope.
|
||||
repository = 'repos/' + quote(config.owner, safe='') + '/' + quote(config.repo, safe='')
|
||||
response = client.get(repository + '/issues', params={'limit': 1, 'page': 1})
|
||||
response.raise_for_status()
|
||||
if not isinstance(response.json(), list):
|
||||
raise GiteaError('invalid_response')
|
||||
except GiteaError:
|
||||
raise
|
||||
except httpx.HTTPStatusError as error:
|
||||
raise GiteaError('http_' + str(error.response.status_code)) from None
|
||||
except (httpx.TimeoutException, httpx.NetworkError, httpx.RemoteProtocolError):
|
||||
raise GiteaError('network_or_timeout') from None
|
||||
except (ValueError, TypeError, KeyError, httpx.HTTPError):
|
||||
raise GiteaError('invalid_response') from None
|
||||
|
||||
|
||||
def main():
|
||||
try:
|
||||
check()
|
||||
except GiteaError as error:
|
||||
print('FAIL: gitea_' + error.kind)
|
||||
return 1
|
||||
print('PASS: Gitea reachable; metalcircle-bot verified; repository issues readable. '
|
||||
'Read-only check; issue creation and attachments not tested.')
|
||||
return 0
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
raise SystemExit(main())
|
||||
Reference in New Issue
Block a user