mirror of
https://github.com/jhd3197/ServerKit.git
synced 2026-11-09 21:43:05 +09:00
Introduce RepositoryManifestService to detect deployment manifests (ServerKit, Render, Railway, Compose, app.json, Dockerfile, Nixpacks) and recommend app/build settings. Add backend integration: analyze repo during import (apps.create_app_from_repository), new GitHub manifest API route, and SourceConnectionService helpers to list root files and fetch file contents from GitHub. Pass resolved dockerfile_path/custom build/start commands into build configuration. Add unit tests for the manifest service. Frontend: add template support and manifest UI in NewService.jsx, new API call inspectGithubRepositoryManifest, and related SCSS styles for templates/manifest display. Misc: updated imports and minor UX messaging changes.
144 lines
4.7 KiB
Python
144 lines
4.7 KiB
Python
"""Source provider connection API."""
|
|
|
|
from flask import Blueprint, jsonify, request
|
|
from flask_jwt_extended import jwt_required, get_jwt_identity
|
|
from requests import HTTPError
|
|
|
|
from app.models import User
|
|
from app.middleware.rbac import admin_required
|
|
from app.services.source_connection_service import SourceConnectionService
|
|
|
|
source_connections_bp = Blueprint('source_connections', __name__)
|
|
|
|
|
|
@source_connections_bp.route('/github/status', methods=['GET'])
|
|
@jwt_required()
|
|
def github_status():
|
|
user_id = int(get_jwt_identity())
|
|
return jsonify(SourceConnectionService.get_status(user_id)), 200
|
|
|
|
|
|
@source_connections_bp.route('/github/authorize', methods=['GET'])
|
|
@jwt_required()
|
|
def github_authorize():
|
|
redirect_uri = request.args.get('redirect_uri', '')
|
|
if not redirect_uri:
|
|
return jsonify({'error': 'redirect_uri is required'}), 400
|
|
|
|
try:
|
|
auth_url, state = SourceConnectionService.generate_github_authorize_url(redirect_uri)
|
|
return jsonify({'auth_url': auth_url, 'state': state}), 200
|
|
except ValueError as exc:
|
|
return jsonify({'error': str(exc)}), 400
|
|
|
|
|
|
@source_connections_bp.route('/github/callback', methods=['POST'])
|
|
@jwt_required()
|
|
def github_callback():
|
|
user_id = int(get_jwt_identity())
|
|
data = request.get_json() or {}
|
|
code = data.get('code', '')
|
|
state = data.get('state', '')
|
|
redirect_uri = data.get('redirect_uri', '')
|
|
|
|
if not code or not state or not redirect_uri:
|
|
return jsonify({'error': 'code, state, and redirect_uri are required'}), 400
|
|
|
|
try:
|
|
connection = SourceConnectionService.complete_github_callback(
|
|
user_id=user_id,
|
|
code=code,
|
|
state=state,
|
|
redirect_uri=redirect_uri,
|
|
)
|
|
return jsonify({'connection': connection.to_dict()}), 200
|
|
except ValueError as exc:
|
|
return jsonify({'error': str(exc)}), 400
|
|
except HTTPError as exc:
|
|
return jsonify({'error': _github_error(exc)}), 400
|
|
|
|
|
|
@source_connections_bp.route('/github/repos', methods=['GET'])
|
|
@jwt_required()
|
|
def github_repositories():
|
|
user_id = int(get_jwt_identity())
|
|
search = request.args.get('search', '')
|
|
page = request.args.get('page', 1, type=int)
|
|
per_page = request.args.get('per_page', 50, type=int)
|
|
|
|
try:
|
|
repos = SourceConnectionService.list_github_repositories(user_id, search, page, per_page)
|
|
return jsonify({'repos': repos}), 200
|
|
except ValueError as exc:
|
|
return jsonify({'error': str(exc)}), 400
|
|
except HTTPError as exc:
|
|
return jsonify({'error': _github_error(exc)}), 400
|
|
|
|
|
|
@source_connections_bp.route('/github/repos/<path:full_name>/branches', methods=['GET'])
|
|
@jwt_required()
|
|
def github_branches(full_name):
|
|
user_id = int(get_jwt_identity())
|
|
|
|
try:
|
|
branches = SourceConnectionService.list_github_branches(user_id, full_name)
|
|
return jsonify({'branches': branches}), 200
|
|
except ValueError as exc:
|
|
return jsonify({'error': str(exc)}), 400
|
|
except HTTPError as exc:
|
|
return jsonify({'error': _github_error(exc)}), 400
|
|
|
|
|
|
@source_connections_bp.route('/github/repos/<path:full_name>/manifest', methods=['GET'])
|
|
@jwt_required()
|
|
def github_repository_manifest(full_name):
|
|
user_id = int(get_jwt_identity())
|
|
ref = request.args.get('ref') or None
|
|
|
|
try:
|
|
manifest = SourceConnectionService.get_github_repository_manifest(user_id, full_name, ref)
|
|
return jsonify({'manifest': manifest}), 200
|
|
except ValueError as exc:
|
|
return jsonify({'error': str(exc)}), 400
|
|
except HTTPError as exc:
|
|
return jsonify({'error': _github_error(exc)}), 400
|
|
|
|
|
|
@source_connections_bp.route('/github', methods=['DELETE'])
|
|
@jwt_required()
|
|
def disconnect_github():
|
|
user_id = int(get_jwt_identity())
|
|
try:
|
|
SourceConnectionService.disconnect(user_id, 'github')
|
|
return jsonify({'message': 'GitHub disconnected'}), 200
|
|
except ValueError as exc:
|
|
return jsonify({'error': str(exc)}), 404
|
|
|
|
|
|
@source_connections_bp.route('/admin/github', methods=['GET'])
|
|
@admin_required
|
|
def github_admin_config():
|
|
return jsonify({'config': SourceConnectionService.get_github_config(redacted=True)}), 200
|
|
|
|
|
|
@source_connections_bp.route('/admin/github', methods=['PUT'])
|
|
@admin_required
|
|
def update_github_admin_config():
|
|
user = User.query.get(get_jwt_identity())
|
|
result = SourceConnectionService.update_github_config(
|
|
request.get_json() or {},
|
|
user_id=user.id if user else None,
|
|
)
|
|
return jsonify(result), 200
|
|
|
|
|
|
def _github_error(exc):
|
|
response = getattr(exc, 'response', None)
|
|
if response is None:
|
|
return str(exc)
|
|
try:
|
|
data = response.json()
|
|
return data.get('message') or str(exc)
|
|
except Exception:
|
|
return response.text or str(exc)
|