diff --git a/.github/workflows/bulk-import-git-repos.yml b/.github/workflows/bulk-import-git-repos.yml new file mode 100644 index 00000000..635dceee --- /dev/null +++ b/.github/workflows/bulk-import-git-repos.yml @@ -0,0 +1,19 @@ +name: Bulk Import Git Repos workflow container image and manifest push + +on: + workflow_dispatch: + push: + branches: [ "main" ] + paths: + - 'workflows/experimentals/bulk-import-git-repos/**' + - 'pipeline/**' + - 'scripts/**' + - .github/workflows/bulk-import-git-repos.yml + - .github/workflows/main.yml + +jobs: + bulk-import-git-repos: + uses: ./.github/workflows/main.yml + with: + workflow_id: bulk-import-git-repos + secrets: inherit diff --git a/Makefile b/Makefile index 2d6717c1..b7893440 100644 --- a/Makefile +++ b/Makefile @@ -164,11 +164,17 @@ save-oci: build-image # Description: Generates the k8s manifests for the WORKFLOW_ID workflow under the configured WORKDIR. # Depends on: prepare-workdir target. # Usage: make gen-manifests +# Optional: WORKFLOW_SUBDIR — when set, first arg is workflows/$(WORKFLOW_SUBDIR); when unset, workflows/$(WORKFLOW_ID) +# make WORKFLOW_ID=bulk-import-git-repos WORKFLOW_SUBDIR=bulk-import-git-repos/src/main/resources gen-manifests +GEN_MANIFESTS_WORKFLOW_FOLDER = workflows/$(if $(WORKFLOW_SUBDIR),$(WORKFLOW_SUBDIR),$(WORKFLOW_ID)) gen-manifests: prepare-workdir - cd $(WORKDIR) - $(CONTAINER_ENGINE) run --rm -v $(WORKDIR):/workdir:Z -w /workdir \ - $(LINUX_IMAGE) /bin/bash -c "ENABLE_PERSISTENCE=$(ENABLE_PERSISTENCE) WORKFLOW_IMAGE_TAG=$(IMAGE_TAG) ${SCRIPTS_DIR}/gen_manifests.sh workflows/$(WORKFLOW_ID) $(WORKFLOW_ID)" - @echo "Manifests are available in workdir $(WORKDIR)/workflows/$(WORKFLOW_ID)/manifests" + @# Ensure WORKDIR exists and is accessible (important for macOS Podman) + @test -d $(WORKDIR) || mkdir -p $(WORKDIR) + @# Use absolute path for volume mount (required for Podman on macOS) + @# On macOS, use realpath or fallback to WORKDIR if realpath fails + @$(CONTAINER_ENGINE) run --rm -v "$(shell realpath $(WORKDIR) 2>/dev/null || echo $(WORKDIR)):/workdir:Z" -w /workdir \ + $(LINUX_IMAGE) /bin/bash -c "ENABLE_PERSISTENCE=$(ENABLE_PERSISTENCE) WORKFLOW_IMAGE_TAG=$(IMAGE_TAG) ${SCRIPTS_DIR}/gen_manifests.sh $(GEN_MANIFESTS_WORKFLOW_FOLDER) $(WORKFLOW_ID)" + @echo "Manifests are available in workdir $(WORKDIR)/$(GEN_MANIFESTS_WORKFLOW_FOLDER)/manifests" remove-trailing-whitespaces: @echo "Removing all trailing whitespaces from application.properties files" diff --git a/pipeline/workflow-builder.Dockerfile b/pipeline/workflow-builder.Dockerfile index 818e7b8e..d5d699ab 100644 --- a/pipeline/workflow-builder.Dockerfile +++ b/pipeline/workflow-builder.Dockerfile @@ -41,7 +41,6 @@ COPY --chown=1001 ${WF_RESOURCES} ./resources/ RUN ls -la ./resources ENV swf_home_dir=/home/kogito/serverless-workflow-project -RUN if [[ -d "./resources/src" ]]; then cp -r ./resources/src/* ./src/; fi RUN /home/kogito/launch/build-app.sh ./resources diff --git a/workflows/bulk-import-git-repos/README.md b/workflows/bulk-import-git-repos/README.md new file mode 100644 index 00000000..85aec38c --- /dev/null +++ b/workflows/bulk-import-git-repos/README.md @@ -0,0 +1,49 @@ +# Bulk Import Git Repos Workflow + +This workflow creates pull requests (GitHub) or merge requests (GitLab) based on the `approvalTool` parameter. + +## Overview + +The workflow supports both GitHub and GitLab repositories and can create PRs/MRs with multiple files. + +## Input Schema + +The workflow expects the following input parameters: +- `approvalTool`: Either "GIT" for GitHub or "GITLAB" for GitLab +- `owner`: The owner/namespace of the repository +- `repo`: The repository name +- `baseBranch`: The base branch to create the PR/MR from +- `targetBranch`: The target branch name for the PR/MR + +## Workflow Steps + +1. **GetScafolderData**: Retrieves mock data with files to be added +2. **RouteToProvider**: Routes to either GitHub or GitLab workflow based on `approvalTool` +3. **GitHub Flow**: Creates branch, commits files, and creates a pull request +4. **GitLab Flow**: Searches for project, creates branch, commits files, and creates a merge request + +## Output + +- For GitHub: Returns PR URL in `PR_URL` output +- For GitLab: Returns MR URL in `MR_URL` output + +# Development + +Java artifacts build(prerequisites: pre-installed java and maven): + +``` +mvn clean install +``` + +Generate manifests, from the root of the repository: + +``` +make WORKFLOW_ID=bulk-import-git-repos WORKFLOW_SUBDIR=bulk-import-git-repos/src/main/resources gen-manifests +cp -rf /tmp/serverless-workflows/workflows/bulk-import-git-repos/src/main/resources/manifests ./workflows/bulk-import-git-repos +``` + +Build image: + +``` +make WORKFLOW_ID=bulk-import-git-repos build-image +``` diff --git a/workflows/bulk-import-git-repos/application.properties b/workflows/bulk-import-git-repos/application.properties new file mode 100644 index 00000000..6292630b --- /dev/null +++ b/workflows/bulk-import-git-repos/application.properties @@ -0,0 +1,2 @@ + +kie.flyway.enabled=true diff --git a/workflows/bulk-import-git-repos/argfile.conf b/workflows/bulk-import-git-repos/argfile.conf new file mode 100644 index 00000000..bfeb7ccc --- /dev/null +++ b/workflows/bulk-import-git-repos/argfile.conf @@ -0,0 +1,6 @@ +FLOW_NAME=Universal PR +FLOW_SUMMARY=Create Universal Pull/Merge Request +FLOW_DESCRIPTION=This workflow creates a pull request (GitHub) or merge request (GitLab) based on approvalTool parameter. +# Base extensions (JARs included in image): persistence-jdbc, jdbc-postgresql, openapi-generator, oidc-client-filter, oidc, agroal +QUARKUS_EXTENSIONS=org.kie:kie-addons-quarkus-persistence-jdbc,io.quarkus:quarkus-jdbc-postgresql:3.15.4.redhat-00001,io.quarkiverse.openapi.generator:quarkus-openapi-generator:2.9.1-lts,io.quarkus:quarkus-oidc-client-filter,io.quarkus:quarkus-oidc,io.quarkus:quarkus-agroal:3.15.4.redhat-00001,org.kie:kie-addons-quarkus-monitoring-sonataflow,org.kie:kogito-addons-quarkus-jobs-knative-eventing +MAVEN_ARGS_APPEND=-DmaxYamlCodePoints=35000000 -Dkogito.persistence.type=jdbc -Dquarkus.datasource.db-kind=postgresql -Dkogito.persistence.proto.marshaller=false diff --git a/workflows/bulk-import-git-repos/manifests/01-configmap_universal-pr-props.yaml b/workflows/bulk-import-git-repos/manifests/01-configmap_universal-pr-props.yaml new file mode 100755 index 00000000..5928ec1c --- /dev/null +++ b/workflows/bulk-import-git-repos/manifests/01-configmap_universal-pr-props.yaml @@ -0,0 +1,48 @@ +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=DEBUG + quarkus.log.level=DEBUG + + # Datasource + quarkus.datasource.db-kind=postgresql + quarkus.datasource.jdbc.url=jdbc:postgresql://postgres.showcase.svc.cluster.local:5432/sonata + quarkus.datasource.username=sonata + quarkus.datasource.password=sonata + + # 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.rest-client.github_yaml.headers.Accept=application/vnd.github+json + # quarkus.openapi-generator.github_yaml.auth.BearerToken.header-name=X-Authorization-github + # quarkus.openapi-generator.github_yaml.auth.BearerToken.bearer-token=${ghToken} + + # quarkus.openapi-generator.githubtwo_yaml.auth.BearerToken.token-propagation=true + # quarkus.openapi-generator.githubtwo_yaml.auth.BearerToken.header-name=X-Authorization-github-two + + 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: + creationTimestamp: null + 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/workflows/bulk-import-git-repos/manifests/02-secret_universal-pr-secrets.yaml b/workflows/bulk-import-git-repos/manifests/02-secret_universal-pr-secrets.yaml new file mode 100755 index 00000000..ba7b346b --- /dev/null +++ b/workflows/bulk-import-git-repos/manifests/02-secret_universal-pr-secrets.yaml @@ -0,0 +1,14 @@ +apiVersion: v1 +kind: Secret +metadata: + creationTimestamp: null + 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-secrets +stringData: + ghToken: ghp_ABC123 diff --git a/workflows/bulk-import-git-repos/manifests/03-configmap_01-universal-pr-resources-schemas.yaml b/workflows/bulk-import-git-repos/manifests/03-configmap_01-universal-pr-resources-schemas.yaml new file mode 100755 index 00000000..e1bc69b9 --- /dev/null +++ b/workflows/bulk-import-git-repos/manifests/03-configmap_01-universal-pr-resources-schemas.yaml @@ -0,0 +1,48 @@ +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: + creationTimestamp: null + name: 01-universal-pr-resources-schemas diff --git a/workflows/bulk-import-git-repos/manifests/04-configmap_02-universal-pr-resources-specs.yaml b/workflows/bulk-import-git-repos/manifests/04-configmap_02-universal-pr-resources-specs.yaml new file mode 100755 index 00000000..21413170 --- /dev/null +++ b/workflows/bulk-import-git-repos/manifests/04-configmap_02-universal-pr-resources-specs.yaml @@ -0,0 +1,494 @@ +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: + creationTimestamp: null + name: 02-universal-pr-resources-specs diff --git a/workflows/bulk-import-git-repos/manifests/05-sonataflow_universal-pr.yaml b/workflows/bulk-import-git-repos/manifests/05-sonataflow_universal-pr.yaml new file mode 100755 index 00000000..634105dd --- /dev/null +++ b/workflows/bulk-import-git-repos/manifests/05-sonataflow_universal-pr.yaml @@ -0,0 +1,374 @@ +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" + creationTimestamp: null + 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: + env: + - name: GHTOKEN + valueFrom: + secretKeyRef: + key: ghToken + name: universal-pr-secrets + image: quay.io/aandriienko/serverless-workflow-bulk-import-git-repos:latest + 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 +status: + address: {} + lastTimeRecoverAttempt: null diff --git a/workflows/bulk-import-git-repos/pom.xml b/workflows/bulk-import-git-repos/pom.xml new file mode 100644 index 00000000..fbf6a5ef --- /dev/null +++ b/workflows/bulk-import-git-repos/pom.xml @@ -0,0 +1,211 @@ + + + 4.0.0 + io.janus.workflow + basic + 1.0.0-SNAPSHOT + + 3.14.0 + 21 + UTF-8 + UTF-8 + quarkus-bom + com.redhat.quarkus.platform + 3.8.6.SP2-redhat-00002 + true + 3.5.3 + 10.0.0 + + + + + ${quarkus.platform.group-id} + ${quarkus.platform.artifact-id} + ${quarkus.platform.version} + pom + import + + + org.kie.kogito + kogito-bom + ${kie.version} + pom + import + + + + + + io.quarkus + quarkus-jdbc-postgresql + + + io.quarkiverse.openapi.generator + quarkus-openapi-generator + 2.9.1-lts + + + io.quarkus + quarkus-oidc-client-filter + + + io.quarkus + quarkus-kubernetes + + + io.quarkus + quarkus-smallrye-health + + + io.quarkus + quarkus-resteasy-jackson + + + io.quarkus + quarkus-arc + + + io.quarkus + quarkus-resteasy + + + io.quarkus + quarkus-junit5 + test + + + io.rest-assured + rest-assured + test + + + org.kie + kie-addons-quarkus-knative-eventing + + + org.kie + kie-addons-quarkus-process-management + + + org.kie + kie-addons-quarkus-source-files + + + org.kie + kogito-addons-quarkus-data-index-inmemory + + + org.kie + kogito-addons-quarkus-jobs-service-embedded + + + org.apache.kie.sonataflow + sonataflow-quarkus + + + org.apache.kie.sonataflow + sonataflow-quarkus-devui + ${kie.version} + + + + + + ${quarkus.platform.group-id} + quarkus-maven-plugin + ${quarkus.platform.version} + true + + + + build + generate-code + generate-code-tests + + + + + + maven-compiler-plugin + ${compiler-plugin.version} + + + -parameters + + + + + maven-surefire-plugin + ${surefire-plugin.version} + + + org.jboss.logmanager.LogManager + ${maven.home} + + + + + maven-failsafe-plugin + ${surefire-plugin.version} + + + + integration-test + verify + + + + + + + ${project.build.directory}/${project.build.finalName}-runner + org.jboss.logmanager.LogManager + ${maven.home} + + + + + + + + native + + + native + + + + false + native + + + + + + true + false + redhat + https://maven.repository.redhat.com/ga + + + apache-public-repository-group + Apache Public Repository Group + https://repository.apache.org/content/groups/public/ + + + apache-snapshot-repository-group + Apache Snapshot Repository Group + https://repository.apache.org/content/groups/snapshots/ + + + + + true + false + redhat + https://maven.repository.redhat.com/ga + + + \ No newline at end of file diff --git a/workflows/bulk-import-git-repos/src/main/docker/Dockerfile.jvm b/workflows/bulk-import-git-repos/src/main/docker/Dockerfile.jvm new file mode 100644 index 00000000..f8b24c20 --- /dev/null +++ b/workflows/bulk-import-git-repos/src/main/docker/Dockerfile.jvm @@ -0,0 +1,33 @@ +ARG BUILDER_IMAGE +ARG RUNTIME_IMAGE + +FROM ${BUILDER_IMAGE:-registry.redhat.io/openshift-serverless-1/logic-swf-builder-rhel8:1.35.0-6} AS builder + +ARG QUARKUS_EXTENSIONS +ENV QUARKUS_EXTENSIONS=${QUARKUS_EXTENSIONS} + +ARG MAVEN_ARGS_APPEND +ENV MAVEN_ARGS_APPEND=${MAVEN_ARGS_APPEND} + +COPY --chown=1001 . . + +RUN /home/kogito/launch/build-app.sh + +#============================= +# Runtime +#============================= +FROM ${RUNTIME_IMAGE:-registry.access.redhat.com/ubi9/openjdk-17:1.21-2} + +ENV LANGUAGE='en_US:en' LANG='en_US.UTF-8' + +COPY --from=builder --chown=185 /home/kogito/serverless-workflow-project/target/quarkus-app/lib/ /deployments/lib/ +COPY --from=builder --chown=185 /home/kogito/serverless-workflow-project/target/quarkus-app/*.jar /deployments/ +COPY --from=builder --chown=185 /home/kogito/serverless-workflow-project/target/quarkus-app/app/ /deployments/app/ +COPY --from=builder --chown=185 /home/kogito/serverless-workflow-project/target/quarkus-app/quarkus/ /deployments/quarkus/ + +EXPOSE 8080 +USER 185 +ENV JAVA_OPTS="-Dquarkus.http.host=0.0.0.0 -Djava.util.logging.manager=org.jboss.logmanager.LogManager" +ENV JAVA_APP_JAR="/deployments/quarkus-run.jar" + +ENTRYPOINT [ "/opt/jboss/container/java/run/run-java.sh" ] diff --git a/workflows/bulk-import-git-repos/src/main/resources/application.properties b/workflows/bulk-import-git-repos/src/main/resources/application.properties new file mode 100644 index 00000000..3e147352 --- /dev/null +++ b/workflows/bulk-import-git-repos/src/main/resources/application.properties @@ -0,0 +1,32 @@ +# 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=DEBUG +quarkus.log.level=DEBUG + +# Datasource +quarkus.datasource.db-kind=postgresql +quarkus.datasource.jdbc.url=jdbc:postgresql://postgres.showcase.svc.cluster.local:5432/sonata +quarkus.datasource.username=sonata +quarkus.datasource.password=sonata + +# 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.rest-client.github_yaml.headers.Accept=application/vnd.github+json +# quarkus.openapi-generator.github_yaml.auth.BearerToken.header-name=X-Authorization-github +# quarkus.openapi-generator.github_yaml.auth.BearerToken.bearer-token=${ghToken} + +# quarkus.openapi-generator.githubtwo_yaml.auth.BearerToken.token-propagation=true +# quarkus.openapi-generator.githubtwo_yaml.auth.BearerToken.header-name=X-Authorization-github-two + +quarkus.openapi-generator.gitlab_yaml.auth.BearerToken.token-propagation=true +quarkus.openapi-generator.gitlab_yaml.auth.BearerToken.header-name=X-Authorization-gitlab diff --git a/workflows/bulk-import-git-repos/src/main/resources/create-pr-universal.sw.yaml b/workflows/bulk-import-git-repos/src/main/resources/create-pr-universal.sw.yaml new file mode 100644 index 00000000..b8436912 --- /dev/null +++ b/workflows/bulk-import-git-repos/src/main/resources/create-pr-universal.sw.yaml @@ -0,0 +1,284 @@ +id: universal-pr +version: "1.0" +specVersion: "0.8" +name: "Create Universal Pull/Merge Request" +description: "This workflow creates a pull request (GitHub) or merge request (GitLab) based on approvalTool parameter." +dataInputSchema: schemas/create-pr-universal-input-schema.json +functions: + # Common functions + - name: scafolderMock + type: expression + operation: | + { + "files": [ + { + "path": "README.md", + "content": "# Hello World" + }, + { + "path": "index.js", + "content": "console.log('Hello, world!');" + } + ] + } + - name: sysLog + type: custom + operation: sysout:INFO + + # GitHub functions + - name: getBranchSHA + operation: specs/github.yaml#getBranchSHA + - name: createCommit + operation: specs/github.yaml#createCommit + - name: createTree + operation: specs/github.yaml#createTree + - name: createBlob + operation: specs/github.yaml#createBlob + - name: createBranch + operation: specs/github.yaml#createBranch + - name: getCommitDetails + operation: specs/github.yaml#getCommitDetails + - name: createPullRequest + operation: specs/github.yaml#createPullRequest + - name: createNewBlob + type: expression + operation: '{"mode": "100644", "path": ($currentFile.path|tostring), "type": "blob", "sha": $WORKFLOW.prevActionResult.sha}' + - name: githubSuccessResult + type: expression + operation: '{ + "result": { + "message": "PR created", + "outputs":[ + { + "key": "PR_URL", + "value": .prURL.html_url, + "format":"link" + } + ] + } + }' + + # GitLab functions + - name: searchProjects + operation: specs/gitlab.yaml#searchProjects + - name: getProject + operation: specs/gitlab.yaml#getProject + - name: gitlabCreateBranch + operation: specs/gitlab.yaml#createBranch + - name: gitlabCreateCommit + operation: specs/gitlab.yaml#createCommit + - name: gitlabCreateMergeRequest + operation: specs/gitlab.yaml#createMergeRequest + - name: gitlabSuccessResult + type: expression + operation: '{ + "result": { + "message": "Merge Request created", + "outputs":[ + { + "key": "MR_URL", + "value": .mrURL.web_url, + "format":"link" + } + ] + } + }' + +start: "GetScafolderData" +states: + - name: GetScafolderData + type: operation + actions: + - name: "Get Scafolder data" + functionRef: + refName: scafolderMock + actionDataFilter: + toStateData: .scafolderReponse + transition: RouteToProvider + + - name: RouteToProvider + type: switch + dataConditions: + - condition: '${ .approvalTool == "GIT" }' + transition: GitHubCreateBranch + - condition: '${ .approvalTool == "GITLAB" }' + transition: GitLabSearchProject + defaultCondition: + transition: ErrorUnknownProvider + + - name: ErrorUnknownProvider + type: inject + data: + error: "Unknown or unsupported approval tool" + approvalTool: "${ .approvalTool }" + end: true + + # GitHub workflow states + - name: GitHubCreateBranch + type: operation + actions: + - functionRef: + refName: sysLog + arguments: + message: '${ "Creating GitHub branch for " + (.owner | tostring) + "/" + (.repo | tostring) }' + - name: "GetHeadSha" + functionRef: + refName: getBranchSHA + arguments: + owner: .owner + repo: .repo + ref: '"heads/" + .baseBranch' + actionDataFilter: + toStateData: .latestSHA + - name: "getCommitDetails" + functionRef: + refName: getCommitDetails + arguments: + owner: .owner + repo: .repo + commit_sha: .latestSHA.object.sha + actionDataFilter: + toStateData: .commit + transition: GitHubCreateFiles + + - name: GitHubCreateFiles + type: foreach + inputCollection: "${ [.scafolderReponse.files[]] }" + iterationParam: currentFile + outputCollection: .blobs + actions: + - name: "createBlob" + functionRef: + refName: createBlob + arguments: + owner: .owner + repo: .repo + content: ($currentFile.content|tostring) + encoding: "utf-8" + - name: createNewBlob + functionRef: + refName: createNewBlob + transition: GitHubCreateNewTree + + - name: GitHubCreateNewTree + type: operation + actions: + - name: "createTree" + functionRef: + refName: createTree + arguments: + owner: .owner + repo: .repo + base_tree: .commit.tree.sha + tree: .blobs + actionDataFilter: + toStateData: .newTree + - name: "createCommit" + functionRef: + refName: createCommit + arguments: + owner: .owner + repo: .repo + message: "Added/Updated multiple files via API" + tree: .newTree.sha + parents: [.latestSHA.object.sha] + actionDataFilter: + toStateData: .newCommit + - name: "createBranch" + functionRef: + refName: createBranch + arguments: + owner: .owner + repo: .repo + ref: '"refs/heads/" + .targetBranch' + sha: .newCommit.sha + transition: GitHubCreatePR + + - name: GitHubCreatePR + type: operation + actions: + - name: "createPullRequest" + functionRef: + refName: createPullRequest + arguments: + owner: .owner + repo: .repo + title: "Automated PR" + body: "" + head: .targetBranch + base: .baseBranch + actionDataFilter: + toStateData: .prURL + - name: setOutput + functionRef: + refName: githubSuccessResult + end: true + + # GitLab workflow states + - name: GitLabSearchProject + type: operation + actions: + - functionRef: + refName: sysLog + arguments: + message: '${ "Searching GitLab project: " + (.owner | tostring) + "/" + (.repo | tostring) }' + - name: SearchProjects + functionRef: + refName: searchProjects + arguments: + search: .repo + membership: true + per_page: 100 + actionDataFilter: + toStateData: .projectsList + stateDataFilter: + output: '${ . as $state | ($state.projectsList // []) | map(select(.path_with_namespace == ($state.owner + "/" + $state.repo)))[0] as $project | $state + {project: $project} }' + transition: GitLabCreateBranch + + - name: GitLabCreateBranch + type: operation + actions: + - functionRef: + refName: sysLog + arguments: + message: '${ "Creating GitLab branch with project ID: " + (.project.id | tostring) }' + - name: "createBranch" + functionRef: + refName: gitlabCreateBranch + arguments: + id: .project.id | tostring + branch: .targetBranch + ref: .baseBranch + transition: GitLabCreateCommit + + - name: GitLabCreateCommit + type: operation + actions: + - name: "createCommit" + functionRef: + refName: gitlabCreateCommit + arguments: + id: .project.id | tostring + branch: .targetBranch + commit_message: "Added/Updated multiple files via API" + actions: '${ .scafolderReponse.files | map({ "action": "create", "file_path": .path, "content": .content }) }' + transition: GitLabCreateMR + + - name: GitLabCreateMR + type: operation + actions: + - name: "createMergeRequest" + functionRef: + refName: gitlabCreateMergeRequest + arguments: + id: .project.id | tostring + source_branch: .targetBranch + target_branch: .baseBranch + title: "Automated MR" + actionDataFilter: + toStateData: .mrURL + - name: setOutput + functionRef: + refName: gitlabSuccessResult + end: true + diff --git a/workflows/bulk-import-git-repos/src/main/resources/schemas/create-pr-universal-input-schema.json b/workflows/bulk-import-git-repos/src/main/resources/schemas/create-pr-universal-input-schema.json new file mode 100644 index 00000000..93a0b5ac --- /dev/null +++ b/workflows/bulk-import-git-repos/src/main/resources/schemas/create-pr-universal-input-schema.json @@ -0,0 +1,41 @@ +{ + "$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" + ] +} diff --git a/workflows/bulk-import-git-repos/src/main/resources/secret.properties b/workflows/bulk-import-git-repos/src/main/resources/secret.properties new file mode 100644 index 00000000..4a977c3f --- /dev/null +++ b/workflows/bulk-import-git-repos/src/main/resources/secret.properties @@ -0,0 +1 @@ +ghToken=ghp_ABC123 diff --git a/workflows/bulk-import-git-repos/src/main/resources/specs/github.yaml b/workflows/bulk-import-git-repos/src/main/resources/specs/github.yaml new file mode 100644 index 00000000..b8856bc3 --- /dev/null +++ b/workflows/bulk-import-git-repos/src/main/resources/specs/github.yaml @@ -0,0 +1,312 @@ +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 diff --git a/workflows/bulk-import-git-repos/src/main/resources/specs/gitlab.yaml b/workflows/bulk-import-git-repos/src/main/resources/specs/gitlab.yaml new file mode 100644 index 00000000..e620d77e --- /dev/null +++ b/workflows/bulk-import-git-repos/src/main/resources/specs/gitlab.yaml @@ -0,0 +1,174 @@ +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