-
Notifications
You must be signed in to change notification settings - Fork 1
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Investigate requirements for creating repo config PR #155
Comments
https://docs.github.com/en/rest/pulls?apiVersion=2022-11-28#create-a-pull-request I have verified that Github Apps (apparently) have permission to open PRs without exgtra permissions (after all if you can see a repo you can open a PR to it) EDIT we need more permissions to actually create files and commits and all that (Contents: Read & Write) |
Might not be possible to do it in BitBucket. Gitlab seems to be possible. If we use the CLI ( |
As a little POC of how to do this in GitHub I offer the task below which generated giovanni-guidini/ats-data#5 import logging
from httpx import AsyncClient
from database.models.core import Branch, Repository
from services.repository import get_repo_provider_service
from tasks.base import BaseCodecovTask
from shared.torngit.base import TorngitBaseAdapter
from app import celery_app
from sqlalchemy.orm import Session
log = logging.getLogger(__name__)
class RepoConfigPRTask(BaseCodecovTask):
name = 'app.tasks.repo_config_pr'
example_yaml_content = (
"codecov:\n" +
" require_ci_to_pass: false\n" +
"notify:\n" +
" wait_for_ci: false\n" +
"comment:\n"
" show_critical_paths: true\n"
' layout: "reach,diff,flags,components,tree,betaprofiling"\n'
)
async def _create_tree_gh(self, base_commit_sha: str, repo_provider: TorngitBaseAdapter, client: AsyncClient) -> str:
# Git trees https://docs.github.com/en/rest/git/trees?apiVersion=2022-11-28#about-git-trees
url = f'/repos/{repo_provider.slug}/git/trees'
body = dict(
base_tree=base_commit_sha,
tree=[
dict(
path='codecov.yml',
mode='100644',
type='blob',
content=self.example_yaml_content
)
]
)
response = await repo_provider.api(client=client, url=url, body=body, method='POST')
return response['sha']
async def _create_commit_gh(self, tree_sha: str, parent_commit_sha: str, repo_provider: TorngitBaseAdapter, client: AsyncClient):
# Create a commit https://docs.github.com/en/rest/git/commits?apiVersion=2022-11-28
url = f'/repos/{repo_provider.slug}/git/commits'
body = dict(
message="Auto-created commit",
tree=tree_sha,
parents=[parent_commit_sha],
)
response = await repo_provider.api(client=client, url=url, body=body, method='POST')
return response['sha']
async def _create_branch_gh(self, branch_name: str, commit_sha: str, repo_provider: TorngitBaseAdapter, client: AsyncClient):
# Create a commit https://docs.github.com/en/rest/git/refs?apiVersion=2022-11-28#create-a-reference
url = f'/repos/{repo_provider.slug}/git/refs'
body = dict(
ref=f'refs/heads/{branch_name}',
sha=commit_sha
)
response = await repo_provider.api(client=client, url=url, body=body, method='POST')
return response
async def _create_pr_gh(self, feature_branch_name, base_branch_name, repo_provider, client):
# Create PR
url = f'/repos/{repo_provider.slug}/pulls'
body = dict(
title="Test config PR",
head=feature_branch_name,
base=base_branch_name,
body="This is a PR to test auto configs. IGNORE",
maintainer_can_modify=True,
draft=True,
)
response = await repo_provider.api(client=client, url=url, body=body, method='POST')
return response
async def _do_config_repo_pr_gh(self, dbsession: Session, repo: Repository, repo_provider: TorngitBaseAdapter):
default_branch: Branch = dbsession.query(Branch).filter(Branch.repoid == repo.repoid, Branch.branch == repo.branch).first()
head_commit_sha_default_branch: str = default_branch.head
async with repo_provider.get_client() as client:
# Create file
tree_sha = await self._create_tree_gh(head_commit_sha_default_branch, repo_provider, client)
# Create commit
commit_sha = await self._create_commit_gh(tree_sha, head_commit_sha_default_branch, repo_provider, client)
# Create branch
branch_name = 'codecov/test-config-pr'
await self._create_branch_gh(branch_name, commit_sha, repo_provider, client)
# Create PR
await self._create_pr_gh(branch_name, default_branch.branch, repo_provider, client)
async def run_async(self, dbsession, repoid, *args, **kwargs):
repository = dbsession.query(Repository).filter(Repository.repoid == repoid).first()
repo_provider = get_repo_provider_service(repository)
await self._do_config_repo_pr_gh(dbsession=dbsession, repo=repository, repo_provider=repo_provider)
return "Finished"
RegisteredRepoConfigPRTask = celery_app.register_task(RepoConfigPRTask())
repo_config_pr = celery_app.tasks[RegisteredRepoConfigPRTask.name] |
Hummm I was curious to see what would happen if we tried to include a workflow file. The task with the changes below created this PR: giovanni-guidini/ats-data#6 ...
example_workflow_content = (
"name: Upload-to-codecov\n" +
"\n" +
"on: [push] # Run on any push event\n" +
"\n" +
"jobs:\n" +
" upload-codecov:\n" +
" runs-on: ubuntu-latest\n" +
" steps:\n"
" - name: Upload coverage reports to Codecov\n" +
" uses: codecov/codecov-action@v3\n" +
" env:\n"
" CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}\n"
)
...
async def _create_tree_gh(self, base_commit_sha: str, repo_provider: TorngitBaseAdapter, client: AsyncClient) -> str:
# Git trees https://docs.github.com/en/rest/git/trees?apiVersion=2022-11-28#about-git-trees
url = f'/repos/{repo_provider.slug}/git/trees'
body = dict(
base_tree=base_commit_sha,
tree=[
dict(
path='codecov.yml',
mode='100644',
type='blob',
content=self.example_yaml_content
),
dict(
path='.github/workflows/upload_codecov.yml',
mode='100644',
type='blob',
content=self.example_workflow_content
),
]
)
response = await repo_provider.api(client=client, url=url, body=body, method='POST')
return response['sha'] |
In order to create the repo config PR, we will likely need to know the user's file to add config to. This will require some input from the frontend app. Work with @adrian-codecov currently to determine what this could look like. We will use this info to inform the design required and implementation details of the backend feature.
The text was updated successfully, but these errors were encountered: