"""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())