diff --git a/deploy/charts/bulk-import-git-repos/templates/01-configmap_universal-pr-props.yaml b/deploy/charts/bulk-import-git-repos/templates/01-configmap_universal-pr-props.yaml new file mode 100755 index 00000000..a8724e8e --- /dev/null +++ b/deploy/charts/bulk-import-git-repos/templates/01-configmap_universal-pr-props.yaml @@ -0,0 +1,37 @@ +apiVersion: v1 +data: + application.properties: | + # This property is used to select the log level, which controls the amount + # of information logged on HTTP requests based on the severity of the events. + # Possible values: OFF, FATAL, ERROR, WARN, INFO, DEBUG, ALL. + # and see https://quarkus.io/guides/logging for documentation + quarkus.log.category."org.apache.http".level=INFO + quarkus.log.level=INFO + + quarkus.datasource.db-kind=postgresql + + # Persistence + kogito.persistence.type=jdbc + kogito.persistence.auto.ddl=false + kie.flyway.enabled=true + + quarkus.oidc.enabled=false + quarkus.oidc.tenant-enabled=false + quarkus.kogito.devservices.enabled=false + quarkus.openapi-generator.github_yaml.auth.BearerToken.token-propagation=true + quarkus.openapi-generator.github_yaml.auth.BearerToken.header-name=X-Authorization-Github + + quarkus.openapi-generator.gitlab_yaml.auth.BearerToken.token-propagation=true + quarkus.openapi-generator.gitlab_yaml.auth.BearerToken.header-name=X-Authorization-gitlab + + kie.flyway.enabled=true +kind: ConfigMap +metadata: + labels: + app: universal-pr + app.kubernetes.io/component: serverless-workflow + app.kubernetes.io/managed-by: sonataflow-operator + app.kubernetes.io/name: universal-pr + sonataflow.org/workflow-app: universal-pr + sonataflow.org/workflow-namespace: "" + name: universal-pr-props diff --git a/deploy/charts/bulk-import-git-repos/templates/02-configmap_01-universal-pr-resources-schemas.yaml b/deploy/charts/bulk-import-git-repos/templates/02-configmap_01-universal-pr-resources-schemas.yaml new file mode 100755 index 00000000..9d4ae023 --- /dev/null +++ b/deploy/charts/bulk-import-git-repos/templates/02-configmap_01-universal-pr-resources-schemas.yaml @@ -0,0 +1,47 @@ +apiVersion: v1 +data: + create-pr-universal-input-schema.json: | + { + "$id": "classpath:/schemas/create-pr-universal-input-schema.json", + "title": "Create Universal PR/MR Input Schema", + "$schema": "http://json-schema.org/draft-07/schema#", + "type": "object", + "properties": { + "approvalTool": { + "title": "Approval Tool", + "description": "The Git provider to use: GIT for GitHub or GITLAB for GitLab", + "type": "string", + "enum": ["GIT", "GITLAB"] + }, + "owner": { + "title": "Owner", + "description": "The owner/namespace of the repository", + "type": "string" + }, + "repo": { + "title": "Repository", + "description": "The repository name", + "type": "string" + }, + "baseBranch": { + "title": "Base Branch", + "description": "The base branch to create the PR/MR from", + "type": "string" + }, + "targetBranch": { + "title": "Target Branch", + "description": "The target branch name for the PR/MR", + "type": "string" + } + }, + "required": [ + "approvalTool", + "owner", + "repo", + "baseBranch", + "targetBranch" + ] + } +kind: ConfigMap +metadata: + name: 01-universal-pr-resources-schemas diff --git a/deploy/charts/bulk-import-git-repos/templates/03-configmap_02-universal-pr-resources-specs.yaml b/deploy/charts/bulk-import-git-repos/templates/03-configmap_02-universal-pr-resources-specs.yaml new file mode 100755 index 00000000..c088d56a --- /dev/null +++ b/deploy/charts/bulk-import-git-repos/templates/03-configmap_02-universal-pr-resources-specs.yaml @@ -0,0 +1,493 @@ +apiVersion: v1 +data: + github.yaml: | + openapi: 3.0.0 + info: + title: GitHub Repository Automation API + version: 1.0.0 + description: API specification for automating GitHub repository tasks using the GitHub REST API v3. + + servers: + - url: https://api.github.com + description: GitHub API + security: + - BearerToken: [] + paths: + /repos/{owner}/{repo}/git/refs/{ref}: + patch: + summary: Update a branch reference + operationId: updateBranchRef + parameters: + - name: owner + in: path + required: true + schema: + type: string + - name: repo + in: path + required: true + schema: + type: string + - name: ref + in: path + required: true + schema: + type: string + requestBody: + required: true + content: + application/json: + schema: + type: object + properties: + sha: + type: string + force: + type: boolean + responses: + '200': + description: Branch updated successfully + content: + application/json: + schema: + type: object + get: + summary: Get the SHA of a ref + operationId: getBranchSHA + parameters: + - name: owner + in: path + required: true + schema: + type: string + - name: repo + in: path + required: true + schema: + type: string + - name: ref + in: path + required: true + schema: + type: string + responses: + '200': + description: Successfully retrieved branch reference + content: + application/json: + schema: + type: object + properties: + object: + type: object + properties: + sha: + type: string + '404': + description: Branch not found + /repos/{owner}/{repo}/git/refs: + post: + summary: Create a new branch + operationId: createBranch + parameters: + - name: owner + in: path + required: true + schema: + type: string + - name: repo + in: path + required: true + schema: + type: string + requestBody: + required: true + content: + application/json: + schema: + type: object + properties: + ref: + type: string + sha: + type: string + responses: + '201': + description: Branch created successfully + content: + application/json: + schema: + type: object + /repos/{owner}/{repo}/git/blobs: + post: + summary: Create a new blob + operationId: createBlob + parameters: + - name: owner + in: path + required: true + schema: + type: string + - name: repo + in: path + required: true + schema: + type: string + requestBody: + required: true + content: + application/json: + schema: + type: object + properties: + content: + type: string + encoding: + type: string + responses: + '201': + description: Blob created successfully + content: + application/json: + schema: + type: object + /repos/{owner}/{repo}/git/trees: + post: + summary: Create a new tree + operationId: createTree + parameters: + - name: owner + in: path + required: true + schema: + type: string + - name: repo + in: path + required: true + schema: + type: string + requestBody: + required: true + content: + application/json: + schema: + type: object + properties: + base_tree: + type: string + tree: + type: array + items: + type: object + properties: + path: + type: string + mode: + type: string + type: + type: string + sha: + type: string + responses: + '201': + description: Tree created successfully + content: + application/json: + schema: + type: object + /repos/{owner}/{repo}/git/commits: + post: + summary: Create a new commit + operationId: createCommit + parameters: + - name: owner + in: path + required: true + schema: + type: string + - name: repo + in: path + required: true + schema: + type: string + requestBody: + required: true + content: + application/json: + schema: + type: object + properties: + message: + type: string + tree: + type: string + parents: + type: array + items: + type: string + responses: + '201': + description: Commit created successfully + content: + application/json: + schema: + type: object + /repos/{owner}/{repo}/git/commits/{commit_sha}: + get: + summary: Get details of a commit + operationId: getCommitDetails + parameters: + - name: owner + in: path + required: true + schema: + type: string + - name: repo + in: path + required: true + schema: + type: string + - name: commit_sha + in: path + required: true + schema: + type: string + responses: + '200': + description: Commit details retrieved successfully + content: + application/json: + schema: + type: object + /repos/{owner}/{repo}/pulls: + post: + summary: Create a pull request + description: Opens a new pull request from a branch to the base branch. + operationId: createPullRequest + parameters: + - name: owner + in: path + required: true + schema: + type: string + - name: repo + in: path + required: true + schema: + type: string + requestBody: + required: true + content: + application/json: + schema: + type: object + properties: + title: + type: string + example: "New Feature: Added new file" + body: + type: string + example: "This PR adds a new file using the GitHub REST API." + head: + type: string + example: "new-feature-branch" + base: + type: string + example: "main" + responses: + '201': + description: Pull request created successfully. + content: + application/json: + schema: + type: object + properties: + html_url: + type: string + example: "https://github.com/user/repo/pull/42" + '422': + description: Invalid input or pull request already exists. + components: + securitySchemes: + BearerToken: + type: http + scheme: bearer + description: Bearer Token authentication + gitlab.yaml: | + openapi: 3.0.0 + info: + title: GitLab Repository Automation API + version: 1.0.0 + description: API specification for automating GitLab repository tasks using the GitLab REST API v4. + + servers: + - url: https://gitlab.com/api/v4 + description: GitLab API + security: + - BearerToken: [] + paths: + /projects: + get: + summary: Search for projects + operationId: searchProjects + parameters: + - name: search + in: query + required: false + schema: + type: string + - name: membership + in: query + required: false + schema: + type: boolean + - name: per_page + in: query + required: false + schema: + type: integer + responses: + '200': + description: Successfully retrieved projects + content: + application/json: + schema: + type: array + items: + type: object + properties: + id: + type: integer + path_with_namespace: + type: string + /projects/{id}: + get: + summary: Get project details + operationId: getProject + parameters: + - name: id + in: path + required: true + schema: + type: string + responses: + '200': + description: Successfully retrieved project + content: + application/json: + schema: + type: object + properties: + id: + type: integer + path_with_namespace: + type: string + /projects/{id}/repository/branches: + post: + summary: Create a new branch + operationId: createBranch + parameters: + - name: id + in: path + required: true + schema: + type: string + requestBody: + required: true + content: + application/json: + schema: + type: object + properties: + branch: + type: string + ref: + type: string + responses: + '201': + description: Branch created successfully + content: + application/json: + schema: + type: object + /projects/{id}/repository/commits: + post: + summary: Create a new commit + operationId: createCommit + parameters: + - name: id + in: path + required: true + schema: + type: string + requestBody: + required: true + content: + application/json: + schema: + type: object + properties: + branch: + type: string + commit_message: + type: string + actions: + type: array + items: + type: object + properties: + action: + type: string + file_path: + type: string + content: + type: string + responses: + '201': + description: Commit created successfully + content: + application/json: + schema: + type: object + /projects/{id}/merge_requests: + post: + summary: Create a merge request + operationId: createMergeRequest + parameters: + - name: id + in: path + required: true + schema: + type: string + requestBody: + required: true + content: + application/json: + schema: + type: object + properties: + source_branch: + type: string + target_branch: + type: string + title: + type: string + responses: + '201': + description: Merge request created successfully + content: + application/json: + schema: + type: object + properties: + web_url: + type: string + components: + securitySchemes: + BearerToken: + type: http + scheme: bearer + description: Bearer Token authentication +kind: ConfigMap +metadata: + name: 02-universal-pr-resources-specs diff --git a/deploy/charts/bulk-import-git-repos/templates/04-sonataflow_universal-pr.yaml b/deploy/charts/bulk-import-git-repos/templates/04-sonataflow_universal-pr.yaml new file mode 100755 index 00000000..f9704ed1 --- /dev/null +++ b/deploy/charts/bulk-import-git-repos/templates/04-sonataflow_universal-pr.yaml @@ -0,0 +1,364 @@ +apiVersion: sonataflow.org/v1alpha08 +kind: SonataFlow +metadata: + annotations: + sonataflow.org/description: This workflow creates a pull request (GitHub) or merge request (GitLab) based on approvalTool parameter. + sonataflow.org/expressionLang: jq + sonataflow.org/profile: gitops + sonataflow.org/version: "1.0" + labels: + app: universal-pr + app.kubernetes.io/component: serverless-workflow + app.kubernetes.io/managed-by: sonataflow-operator + app.kubernetes.io/name: universal-pr + sonataflow.org/workflow-app: universal-pr + sonataflow.org/workflow-namespace: "" + name: universal-pr +spec: + flow: + dataInputSchema: + failOnValidationErrors: true + schema: schemas/create-pr-universal-input-schema.json + functions: + - name: scafolderMock + operation: | + { + "files": [ + { + "path": "README.md", + "content": "# Hello World" + }, + { + "path": "index.js", + "content": "console.log('Hello, world!');" + } + ] + } + type: expression + - name: sysLog + operation: sysout:INFO + type: custom + - name: getBranchSHA + operation: specs/github.yaml#getBranchSHA + type: rest + - name: createCommit + operation: specs/github.yaml#createCommit + type: rest + - name: createTree + operation: specs/github.yaml#createTree + type: rest + - name: createBlob + operation: specs/github.yaml#createBlob + type: rest + - name: createBranch + operation: specs/github.yaml#createBranch + type: rest + - name: getCommitDetails + operation: specs/github.yaml#getCommitDetails + type: rest + - name: createPullRequest + operation: specs/github.yaml#createPullRequest + type: rest + - name: createNewBlob + operation: '{"mode": "100644", "path": ($currentFile.path|tostring), "type": "blob", "sha": $WORKFLOW.prevActionResult.sha}' + type: expression + - name: githubSuccessResult + operation: '{ "result": { "message": "PR created", "outputs":[ { "key": "PR_URL", "value": .prURL.html_url, "format":"link" } ] } }' + type: expression + - name: searchProjects + operation: specs/gitlab.yaml#searchProjects + type: rest + - name: getProject + operation: specs/gitlab.yaml#getProject + type: rest + - name: gitlabCreateBranch + operation: specs/gitlab.yaml#createBranch + type: rest + - name: gitlabCreateCommit + operation: specs/gitlab.yaml#createCommit + type: rest + - name: gitlabCreateMergeRequest + operation: specs/gitlab.yaml#createMergeRequest + type: rest + - name: gitlabSuccessResult + operation: '{ "result": { "message": "Merge Request created", "outputs":[ { "key": "MR_URL", "value": .mrURL.web_url, "format":"link" } ] } }' + type: expression + start: + stateName: GetScafolderData + states: + - actionMode: sequential + actions: + - actionDataFilter: + toStateData: .scafolderReponse + useResults: true + functionRef: + invoke: sync + refName: scafolderMock + name: Get Scafolder data + name: GetScafolderData + transition: + nextState: RouteToProvider + type: operation + - dataConditions: + - condition: ${ .approvalTool == "GIT" } + transition: + nextState: GitHubCreateBranch + - condition: ${ .approvalTool == "GITLAB" } + transition: + nextState: GitLabSearchProject + defaultCondition: + transition: + nextState: ErrorUnknownProvider + name: RouteToProvider + type: switch + - data: + approvalTool: ${ .approvalTool } + error: Unknown or unsupported approval tool + end: + terminate: true + name: ErrorUnknownProvider + type: inject + - actionMode: sequential + actions: + - actionDataFilter: + useResults: true + functionRef: + arguments: + message: ${ "Creating GitHub branch for " + (.owner | tostring) + "/" + (.repo | tostring) } + invoke: sync + refName: sysLog + - actionDataFilter: + toStateData: .latestSHA + useResults: true + functionRef: + arguments: + owner: .owner + ref: '"heads/" + .baseBranch' + repo: .repo + invoke: sync + refName: getBranchSHA + name: GetHeadSha + - actionDataFilter: + toStateData: .commit + useResults: true + functionRef: + arguments: + commit_sha: .latestSHA.object.sha + owner: .owner + repo: .repo + invoke: sync + refName: getCommitDetails + name: getCommitDetails + name: GitHubCreateBranch + transition: + nextState: GitHubCreateFiles + type: operation + - actions: + - actionDataFilter: + useResults: true + functionRef: + arguments: + content: ($currentFile.content|tostring) + encoding: utf-8 + owner: .owner + repo: .repo + invoke: sync + refName: createBlob + name: createBlob + - actionDataFilter: + useResults: true + functionRef: + invoke: sync + refName: createNewBlob + name: createNewBlob + inputCollection: ${ [.scafolderReponse.files[]] } + iterationParam: currentFile + mode: parallel + name: GitHubCreateFiles + outputCollection: .blobs + transition: + nextState: GitHubCreateNewTree + type: foreach + - actionMode: sequential + actions: + - actionDataFilter: + toStateData: .newTree + useResults: true + functionRef: + arguments: + base_tree: .commit.tree.sha + owner: .owner + repo: .repo + tree: .blobs + invoke: sync + refName: createTree + name: createTree + - actionDataFilter: + toStateData: .newCommit + useResults: true + functionRef: + arguments: + message: Added/Updated multiple files via API + owner: .owner + parents: + - .latestSHA.object.sha + repo: .repo + tree: .newTree.sha + invoke: sync + refName: createCommit + name: createCommit + - actionDataFilter: + useResults: true + functionRef: + arguments: + owner: .owner + ref: '"refs/heads/" + .targetBranch' + repo: .repo + sha: .newCommit.sha + invoke: sync + refName: createBranch + name: createBranch + name: GitHubCreateNewTree + transition: + nextState: GitHubCreatePR + type: operation + - actionMode: sequential + actions: + - actionDataFilter: + toStateData: .prURL + useResults: true + functionRef: + arguments: + base: .baseBranch + body: "" + head: .targetBranch + owner: .owner + repo: .repo + title: Automated PR + invoke: sync + refName: createPullRequest + name: createPullRequest + - actionDataFilter: + useResults: true + functionRef: + invoke: sync + refName: githubSuccessResult + name: setOutput + end: + terminate: true + name: GitHubCreatePR + type: operation + - actionMode: sequential + actions: + - actionDataFilter: + useResults: true + functionRef: + arguments: + message: '${ "Searching GitLab project: " + (.owner | tostring) + "/" + (.repo | tostring) }' + invoke: sync + refName: sysLog + - actionDataFilter: + toStateData: .projectsList + useResults: true + functionRef: + arguments: + membership: true + per_page: 100 + search: .repo + invoke: sync + refName: searchProjects + name: SearchProjects + name: GitLabSearchProject + stateDataFilter: + output: '${ . as $state | ($state.projectsList // []) | map(select(.path_with_namespace == ($state.owner + "/" + $state.repo)))[0] as $project | $state + {project: $project} }' + transition: + nextState: GitLabCreateBranch + type: operation + - actionMode: sequential + actions: + - actionDataFilter: + useResults: true + functionRef: + arguments: + message: '${ "Creating GitLab branch with project ID: " + (.project.id | tostring) }' + invoke: sync + refName: sysLog + - actionDataFilter: + useResults: true + functionRef: + arguments: + branch: .targetBranch + id: .project.id | tostring + ref: .baseBranch + invoke: sync + refName: gitlabCreateBranch + name: createBranch + name: GitLabCreateBranch + transition: + nextState: GitLabCreateCommit + type: operation + - actionMode: sequential + actions: + - actionDataFilter: + useResults: true + functionRef: + arguments: + actions: '${ .scafolderReponse.files | map({ "action": "create", "file_path": .path, "content": .content }) }' + branch: .targetBranch + commit_message: Added/Updated multiple files via API + id: .project.id | tostring + invoke: sync + refName: gitlabCreateCommit + name: createCommit + name: GitLabCreateCommit + transition: + nextState: GitLabCreateMR + type: operation + - actionMode: sequential + actions: + - actionDataFilter: + toStateData: .mrURL + useResults: true + functionRef: + arguments: + id: .project.id | tostring + source_branch: .targetBranch + target_branch: .baseBranch + title: Automated MR + invoke: sync + refName: gitlabCreateMergeRequest + name: createMergeRequest + - actionDataFilter: + useResults: true + functionRef: + invoke: sync + refName: gitlabSuccessResult + name: setOutput + end: + terminate: true + name: GitLabCreateMR + type: operation + podTemplate: + container: + image: quay.io/orchestrator/serverless-workflow-bulk-import-git-repos:8aa743d82ab877784bc12bcdb642221e53693903 + resources: {} + resources: + configMaps: + - configMap: + name: 01-universal-pr-resources-schemas + workflowPath: schemas + - configMap: + name: 02-universal-pr-resources-specs + workflowPath: specs + persistence: + postgresql: + secretRef: + name: backstage-psql-secret + userKey: POSTGRES_USER + passwordKey: POSTGRES_PASSWORD + serviceRef: + name: backstage-psql + port: 5432 + databaseName: backstage_plugin_orchestrator + databaseSchema: bulk-import-git-repos + namespace: orchestrator