Uploaded image for project: 'Jenkins'
  1. Jenkins
  2. JENKINS-41403

Additions to Github APIs for Organizations and Repositories

    • Icon: Improvement Improvement
    • Resolution: Fixed
    • Icon: Minor Minor
    • blueocean-plugin
    • None
    • pannonian, iapetus

      I would like to request two additions to the Github APIs.

      When listing organizations via /jenkins/scm/github/organizations/?credentialId=github the response is currently:

      [{
          "_class": "io.jenkins.blueocean.blueocean_github_pipeline.GithubOrganization",
          "_links": {
              "repositories": {
                  "_class": "io.jenkins.blueocean.rest.hal.Link",
                  "href": "/organizations/jenkins/scm/github/organizations/jenkinsci/repositories/"
              },
              "self": {
                  "_class": "io.jenkins.blueocean.rest.hal.Link",
                  "href": "/organizations/jenkins/scm/github/organizations/jenkinsci/"
              }
          },
          "avatar": "https://avatars.githubusercontent.com/u/107424?v=3&s=50",
          "jenkinsOrganizationPipeline": false,
          "name": "jenkinsci"
      }, {
          "_class": "io.jenkins.blueocean.blueocean_github_pipeline.GithubUserOrganization",
          "_links": {
              "repositories": {
                  "_class": "io.jenkins.blueocean.rest.hal.Link",
                  "href": "/organizations/jenkins/scm/github/organizations/cliffmeyers/repositories/"
              },
              "self": {
                  "_class": "io.jenkins.blueocean.rest.hal.Link",
                  "href": "/organizations/jenkins/scm/github/organizations/cliffmeyers/"
              }
          },
          "avatar": "https://avatars.githubusercontent.com/u/143466?v=3&s=50",
          "jenkinsOrganizationPipeline": true,
          "name": "cliffmeyers"
      }, {
          "_class": "io.jenkins.blueocean.blueocean_github_pipeline.GithubOrganization",
          "_links": {
              "repositories": {
                  "_class": "io.jenkins.blueocean.rest.hal.Link",
                  "href": "/organizations/jenkins/scm/github/organizations/cloudbees/repositories/"
              },
              "self": {
                  "_class": "io.jenkins.blueocean.rest.hal.Link",
                  "href": "/organizations/jenkins/scm/github/organizations/cloudbees/"
              }
          },
          "avatar": "https://avatars.githubusercontent.com/u/235526?v=3&s=50",
          "jenkinsOrganizationPipeline": false,
          "name": "cloudbees"
      }]
      

      1. For organizations where jenkinsOrganizationPipeline is true, could we add an additional field that indicates whether "auto discover" is enabled? This is equivalent to a Github org folder that was created without specifying any repository names (i.e. empty "repoNames" array)

      2. For organizations where jenkinsOrganizationPipeline is true, could we also add a HAL link to the Jenkins org folder? This will make REST API update calls much easier.

      When listing repositories via /jenkins/scm/github/organizations/cliffmeyers/repositories/?credentialId=github&pageNumber=1&pageSize=100 the response is currently:

      {
          "_class": "io.jenkins.blueocean.blueocean_github_pipeline.GithubRespositoryContainer",
          "_links": {
              "self": {
                  "_class": "io.jenkins.blueocean.rest.hal.Link",
                  "href": "/organizations/jenkins/scm/github/organizations/cliffmeyers/repositories/"
              }
          },
          "repositories": {
              "_class": "io.jenkins.blueocean.blueocean_github_pipeline.GithubRepositories",
              "_links": {
                  "self": {
                      "_class": "io.jenkins.blueocean.rest.hal.Link",
                      "href": "/organizations/jenkins/scm/github/organizations/cliffmeyers/repositories/repositories/"
                  }
              },
              "items": [{
                  "_class": "io.jenkins.blueocean.blueocean_github_pipeline.GithubRepository",
                  "_links": {
                      "self": {
                          "_class": "io.jenkins.blueocean.rest.hal.Link",
                          "href": "/organizations/jenkins/scm/github/organizations/cliffmeyers/repositories/repositories/blog-examples/"
                      }
                  },
                  "defaultBranch": "master",
                  "description": "Sample code from stuff on my blog",
                  "name": "blog-examples",
                  "permissions": {
                      "admin": true,
                      "push": true,
                      "pull": true
                  },
                  "private": false,
                  "fullName": "cliffmeyers/blog-examples"
              }, {
                  "_class": "io.jenkins.blueocean.blueocean_github_pipeline.GithubRepository",
                  "_links": {
                      "self": {
                          "_class": "io.jenkins.blueocean.rest.hal.Link",
                          "href": "/organizations/jenkins/scm/github/organizations/cliffmeyers/repositories/repositories/blueocean-plugin/"
                      }
                  },
                  "defaultBranch": "master",
                  "description": "Blue Ocean UI app",
                  "name": "blueocean-plugin",
                  "permissions": {
                      "admin": true,
                      "push": true,
                      "pull": true
                  },
                  "private": false,
                  "fullName": "cliffmeyers/blueocean-plugin"
              }, {
                  "_class": "io.jenkins.blueocean.blueocean_github_pipeline.GithubRepository",
                  "_links": {
                      "self": {
                          "_class": "io.jenkins.blueocean.rest.hal.Link",
                          "href": "/organizations/jenkins/scm/github/organizations/cliffmeyers/repositories/repositories/frontend-maven-plugin/"
                      }
                  },
                  "defaultBranch": "master",
                  "description": "\"Maven-node-grunt-gulp-npm-node-plugin to end all maven-node-grunt-gulp-npm-plugins.\" A Maven plugin that downloads/installs Node and NPM locally, runs NPM install, Grunt, Gulp and/or Karma.",
                  "name": "frontend-maven-plugin",
                  "permissions": {
                      "admin": true,
                      "push": true,
                      "pull": true
                  },
                  "private": false,
                  "fullName": "cliffmeyers/frontend-maven-plugin"
              }, {
                  "_class": "io.jenkins.blueocean.blueocean_github_pipeline.GithubRepository",
                  "_links": {
                      "self": {
                          "_class": "io.jenkins.blueocean.rest.hal.Link",
                          "href": "/organizations/jenkins/scm/github/organizations/cliffmeyers/repositories/repositories/java-utils/"
                      }
                  },
                  "defaultBranch": "master",
                  "description": "Utilities for Java",
                  "name": "java-utils",
                  "permissions": {
                      "admin": true,
                      "push": true,
                      "pull": true
                  },
                  "private": false,
                  "fullName": "cliffmeyers/java-utils"
              }],
              "lastPage": 3,
              "nextPage": 2,
              "pageSize": 4
          }
      }
      

      3. Could we add a field to the repository object that indicates whether a pipeline has already been created for it? This is important in the "update" scenario to avoid the user trying to create a repo that was already created.

          [JENKINS-41403] Additions to Github APIs for Organizations and Repositories

          Cliff Meyers added a comment -

          It would be nice to have this API sooner rather than later so I can spend some more time on these re-entrant flows. Thanks vivek!

          Cliff Meyers added a comment - It would be nice to have this API sooner rather than later so I can spend some more time on these re-entrant flows. Thanks vivek !

          Vivek Pandey added a comment -

          cliffmeyers

          > For organizations where jenkinsOrganizationPipeline is true, could we add an additional field that indicates whether "auto discover" is enabled?

          So auto-discover is false if in model there are no branch filtering specified? that is branch filter is empty then its auto-discover?

          > Could we add a field to the repository object that indicates whether a pipeline has already been created for it?

          yeah can be done, I guess you want it to be true if there is job for this repo inside this org folder

          Vivek Pandey added a comment - cliffmeyers > For organizations where jenkinsOrganizationPipeline is true, could we add an additional field that indicates whether "auto discover" is enabled? So auto-discover is false if in model there are no branch filtering specified? that is branch filter is empty then its auto-discover? > Could we add a field to the repository object that indicates whether a pipeline has already been created for it? yeah can be done, I guess you want it to be true if there is job for this repo inside this org folder

          Cliff Meyers added a comment - - edited

          > So auto-discover is false if in model there are no branch filtering specified? that is branch filter is empty then its auto-discover?

          What we call "auto discover" in the UI is the mode where there is no filtering of repositories. You said "branch filtering" but I think perhaps you mean "repository filtering"

          > yeah can be done, I guess you want it to be true if there is job for this repo inside this org folder

          Yes, that's exactly right.

          These fields will allow us to customize the UI appropriately when the user selects a Github organization that already has an org folder created in Jenkins.

          Cliff Meyers added a comment - - edited > So auto-discover is false if in model there are no branch filtering specified? that is branch filter is empty then its auto-discover? What we call "auto discover" in the UI is the mode where there is no filtering of repositories. You said "branch filtering" but I think perhaps you mean "repository filtering" > yeah can be done, I guess you want it to be true if there is job for this repo inside this org folder Yes, that's exactly right. These fields will allow us to customize the UI appropriately when the user selects a Github organization that already has an org folder created in Jenkins.

          Cliff Meyers added a comment -

          vivek I added #2 to this list, related to the HAL href to the Jenkins org folder. Let me know if you think that's doable.

          Cliff Meyers added a comment - vivek I added #2 to this list, related to the HAL href to the Jenkins org folder. Let me know if you think that's doable.

          Vivek Pandey added a comment - - edited

          cliffmeyers

          > I added #2 to this list, related to the HAL href to the Jenkins org folder. Let me know if you think that's doable.

          I would avoid doing it as HAL that is inside _links element. HAL links are HTTP reachable resources, org folder contains repositories and not other way round. This way when you fetch jenkins org folder (/jenkins/scm/github/organizations/cliffmeyers/) you should see HAL link to repositories. Besides if you are accessing /jenkins/scm/github/organizations/cliffmeyers/repositories/ then you already have org folder link that is /jenkins/scm/github/organizations/cliffmeyers/.

          I could expose it as separate element, but it should be a collection as there could be more than one jenkins org folder for a given GitHub organization.

          Vivek Pandey added a comment - - edited cliffmeyers > I added #2 to this list, related to the HAL href to the Jenkins org folder. Let me know if you think that's doable. I would avoid doing it as HAL that is inside _links element. HAL links are HTTP reachable resources, org folder contains repositories and not other way round. This way when you fetch jenkins org folder (/jenkins/scm/github/organizations/cliffmeyers/) you should see HAL link to repositories. Besides if you are accessing /jenkins/scm/github/organizations/cliffmeyers/repositories/ then you already have org folder link that is /jenkins/scm/github/organizations/cliffmeyers/. I could expose it as separate element, but it should be a collection as there could be more than one jenkins org folder for a given GitHub organization.

          Vivek Pandey added a comment -

          cliffmeyers

          >> So auto-discover is false if in model there are no branch filtering specified? that is branch filter is empty then its auto-discover?
          > What we call "auto discover" in the UI is the mode where there is no filtering of repositories. You said "branch filtering" but I think perhaps you mean "repository filtering"

          First of all there could be more than one jenkins org folder for a given GitHub organization. Second there is no definitive way to tell if it was auto-discover. This is UI concept so I can provide an element that can provide list of requested repos when jenkins org folder was created. If its empty you can compute its auto-discover.

          So my proposed json element in GitHub organization response could be:

          {
          ...
            "isJenkinsOrganizationPipeline":true,
            "jenkinsOrganizationPipelines":[
              {
                "pipeline":"cloudbeers1",
                "requestedRepos":["PR-7"],
                "_links" : {
                  "self" : {
                    "_class" : "io.jenkins.blueocean.rest.hal.Link",
                    "href" : "/organizations/jenkins/pipelines/cloudbeers1/"
                  }
                }
              },
              {
                "pipeline":"cloudbeers2",
                "requestedRepos":[], //will fetch all repos
                "_links" : {
                  "self" : {
                    "_class" : "io.jenkins.blueocean.rest.hal.Link",
                    "href" : "/organizations/jenkins/pipelines/cloudbeers2/"
                  }
                }
              }
            ]
          ...
          }
          

          There could be more than one jenkins org folder for a given GitHub org, I am not sure how useful its going to be. I would avoid doing it unless there is UX defined to handle it. Lets chat about it Monday, will be good to have jamesdumay and michaelneale around to get clarification on expected UX.

          Vivek Pandey added a comment - cliffmeyers >> So auto-discover is false if in model there are no branch filtering specified? that is branch filter is empty then its auto-discover? > What we call "auto discover" in the UI is the mode where there is no filtering of repositories. You said "branch filtering" but I think perhaps you mean "repository filtering" First of all there could be more than one jenkins org folder for a given GitHub organization. Second there is no definitive way to tell if it was auto-discover. This is UI concept so I can provide an element that can provide list of requested repos when jenkins org folder was created. If its empty you can compute its auto-discover. So my proposed json element in GitHub organization response could be: { ... "isJenkinsOrganizationPipeline" : true , "jenkinsOrganizationPipelines" :[ { "pipeline" : "cloudbeers1" , "requestedRepos" :[ "PR-7" ], "_links" : { "self" : { "_class" : "io.jenkins.blueocean. rest .hal.Link" , "href" : "/organizations/jenkins/pipelines/cloudbeers1/" } } }, { "pipeline" : "cloudbeers2" , "requestedRepos" :[], //will fetch all repos "_links" : { "self" : { "_class" : "io.jenkins.blueocean. rest .hal.Link" , "href" : "/organizations/jenkins/pipelines/cloudbeers2/" } } } ] ... } There could be more than one jenkins org folder for a given GitHub org, I am not sure how useful its going to be. I would avoid doing it unless there is UX defined to handle it. Lets chat about it Monday, will be good to have jamesdumay and michaelneale around to get clarification on expected UX.

          Michael Neale added a comment -

          vivek cliffmeyers yes, returning an empty list or not empty is enough for the UI to decide what should be shown.

          The other question is a little more vexing. Lets say we have a github org called "cloudbeers".
          In jenkins today you could create as many instances of the cloudbees github org folder as you want - naming them all something creative, but al of the same thing (or with different filter criteria etc). There may be a valid case for this (not terribly likely, but you may apply different PR rules to some named subset of repos - I am fishing for a reason here).

          The bottom line is that when you say "github org" - which one of these is the One True github org? In the blue ocean creation flow, you chose "github" and then it enumerate the org (folders?) it knows about, but that implies there is One True github org folder that you will add repos to (or make it auto discovery)? Do we assume the named item is the github orgs name? If things are created through blue ocean we can control this for sure.

          Michael Neale added a comment - vivek cliffmeyers yes, returning an empty list or not empty is enough for the UI to decide what should be shown. The other question is a little more vexing. Lets say we have a github org called "cloudbeers". In jenkins today you could create as many instances of the cloudbees github org folder as you want - naming them all something creative, but al of the same thing (or with different filter criteria etc). There may be a valid case for this (not terribly likely, but you may apply different PR rules to some named subset of repos - I am fishing for a reason here). The bottom line is that when you say "github org" - which one of these is the One True github org? In the blue ocean creation flow, you chose "github" and then it enumerate the org (folders?) it knows about, but that implies there is One True github org folder that you will add repos to (or make it auto discovery)? Do we assume the named item is the github orgs name? If things are created through blue ocean we can control this for sure.

          Cliff Meyers added a comment -

          michaelneale Well this is a real problem if we can't define a rule or convention to identify these org folders in a consistent manner. Let's discuss in the meeting later today.

          Cliff Meyers added a comment - michaelneale Well this is a real problem if we can't define a rule or convention to identify these org folders in a consistent manner. Let's discuss in the meeting later today.

          Michael Neale added a comment -

          cliffmeyers there would be a few ways to solve it that are suitable I am sure.

          Michael Neale added a comment - cliffmeyers there would be a few ways to solve it that are suitable I am sure.

          Vivek Pandey added a comment -

          As discussed in backend meeting, the only change will be made in pipeline API that returns org folder pipeline.

          Following tasks are expected:

          • Ensure jenkins.branch.OrganizationFolder capability is returned for blueocean organization folder
          • Following changes are expected in pipeline JSON response:
            {
              "pipeline":"blueocean-plugin",
              "requestedRepos":["master", "task/JENMINS-123"],
              "pipelines": ["master", "task/JENMINS-123"]
            }
            
          • pipelines array is subset of requestedRepos (if not empty) as some of the repos might not have Jenkinsfile
          {
            "pipeline":"blueocean-plugin",
            "requestedRepos":["master", "task/JENMINS-123"],
            "pipelines": ["task/JENMINS-123"] //no Jenkinsfile on master
          }
          
          
          • If requestedRepos is empty then consider it as auto-discover
            {
              "pipeline":"blueocean-plugin",
              "requestedRepos":[], //auto-discover
              "pipelines": ["master", "task/JENMINS-123"]
            }
            
            

          cliffmeyers michaelneale did I get everything that needs to be done in API for this ticket?

          Vivek Pandey added a comment - As discussed in backend meeting, the only change will be made in pipeline API that returns org folder pipeline. Following tasks are expected: Ensure jenkins.branch.OrganizationFolder capability is returned for blueocean organization folder Following changes are expected in pipeline JSON response: { "pipeline" : "blueocean-plugin" , "requestedRepos" :[ "master" , "task/JENMINS-123" ], "pipelines" : [ "master" , "task/JENMINS-123" ] } pipelines array is subset of requestedRepos (if not empty) as some of the repos might not have Jenkinsfile { "pipeline" : "blueocean-plugin" , "requestedRepos" :[ "master" , "task/JENMINS-123" ], "pipelines" : [ "task/JENMINS-123" ] //no Jenkinsfile on master } If requestedRepos is empty then consider it as auto-discover { "pipeline" : "blueocean-plugin" , "requestedRepos" :[], //auto-discover "pipelines" : [ "master" , "task/JENMINS-123" ] } cliffmeyers michaelneale did I get everything that needs to be done in API for this ticket?

          Michael Neale added a comment -

          Yes that is right. And the assumption is that the name of the org is the name of the top level org folder item so that the UI knows what to look up to fetch what repos are setup etc.

          Michael Neale added a comment - Yes that is right. And the assumption is that the name of the org is the name of the top level org folder item so that the UI knows what to look up to fetch what repos are setup etc.

          Cliff Meyers added a comment -

          I am in agreement: this looks good.

          Cliff Meyers added a comment - I am in agreement: this looks good.

          Vivek Pandey added a comment -

          michaelneale cliffmeyers requestedRepos is saved as pattern using underlying GitHub-branch-source library. If you create org pipeline using BO creation flow there is way to get list of requested repo (BO api saves list of requested repos as properties on the org folder).

          However users can create org pipeline using classic and give any kind of regex pattern and its not possible to get meaningful list of repositories. Basically, if its created using classic, this field is going to be empty but that might get interpreted as auto-scanned.

          So is it reasonable behavior that "requestedRepos" element is present only if org folder was created using BO GitHub creation flow?

          Vivek Pandey added a comment - michaelneale cliffmeyers requestedRepos is saved as pattern using underlying GitHub-branch-source library. If you create org pipeline using BO creation flow there is way to get list of requested repo (BO api saves list of requested repos as properties on the org folder). However users can create org pipeline using classic and give any kind of regex pattern and its not possible to get meaningful list of repositories. Basically, if its created using classic, this field is going to be empty but that might get interpreted as auto-scanned. So is it reasonable behavior that "requestedRepos" element is present only if org folder was created using BO GitHub creation flow?

          Michael Neale added a comment -

          vivek if we can discriminate between if it was created by blue ocean or not* - sure. Perhaps could be another field? I would leave it to cliffmeyers. However, I think it is probably fine to omit it.

          What about the case that it was created by blue ocean originally, but a user tweaks the regex after the fact - it would then be invalidated and we would have to know somehow - is this possible?

          • Is it necessary to be a property - as if it is a list of patterns, it is pretty clear that it is a list (ie space separated right? or not reasonable to reverse it out of the pattern?)

          Michael Neale added a comment - vivek if we can discriminate between if it was created by blue ocean or not* - sure. Perhaps could be another field? I would leave it to cliffmeyers . However, I think it is probably fine to omit it. What about the case that it was created by blue ocean originally, but a user tweaks the regex after the fact - it would then be invalidated and we would have to know somehow - is this possible? Is it necessary to be a property - as if it is a list of patterns, it is pretty clear that it is a list (ie space separated right? or not reasonable to reverse it out of the pattern?)

          Vivek Pandey added a comment -

          michaelneale cliffmeyers Actually I don't see how it can work in all cases no matter which way we go. Internally its represented as pattern that user can tweak as well in classic. So there is no guarunteed round trip. I propose to drop requestedRepos property as there doesn't seem a way to provide that in consistent way.

          Vivek Pandey added a comment - michaelneale cliffmeyers Actually I don't see how it can work in all cases no matter which way we go. Internally its represented as pattern that user can tweak as well in classic. So there is no guarunteed round trip. I propose to drop requestedRepos property as there doesn't seem a way to provide that in consistent way.

          Cliff Meyers added a comment -

          If we drop "requestedRepos" we can't determine whether the user originally picked "autodiscover" or "one repo" and this has a profound implication on what we can do with the re-entrant flow for Github Creation. Seems appropriate to pull jamesdumay into this conversation as he had originally conceived of the feature.

          Cliff Meyers added a comment - If we drop "requestedRepos" we can't determine whether the user originally picked "autodiscover" or "one repo" and this has a profound implication on what we can do with the re-entrant flow for Github Creation. Seems appropriate to pull jamesdumay into this conversation as he had originally conceived of the feature.

          Vivek Pandey added a comment -

          cliffmeyers Ok, so all you need is to determine auto-discover or not. How about backend API returns a boolean - I was trying to avoid that but this seems like most logical solution given challenges listing requested repos. Sounds good to you?

          Vivek Pandey added a comment - cliffmeyers Ok, so all you need is to determine auto-discover or not. How about backend API returns a boolean - I was trying to avoid that but this seems like most logical solution given challenges listing requested repos. Sounds good to you?

          Cliff Meyers added a comment -

          Per discussion, boolean flag is okay as long as the "pipelines" array is preserved. This is important when a user wants to transition from "auto-discover" to "single repo" so that we can call the "update" REST API and provide accurate list for "repoNames": [].concat(pipelines, newRepoName)

          Cliff Meyers added a comment - Per discussion, boolean flag is okay as long as the "pipelines" array is preserved. This is important when a user wants to transition from "auto-discover" to "single repo" so that we can call the "update" REST API and provide accurate list for "repoNames": [].concat(pipelines, newRepoName)

          James Dumay added a comment -

          cliffmeyers vivek not sure what I should be chiming in here for?

          James Dumay added a comment - cliffmeyers vivek not sure what I should be chiming in here for?

          Cliff Meyers added a comment -

          jamesdumay Vivek and I chatted earlier and sorted this out; we're all good for now.

          Cliff Meyers added a comment - jamesdumay Vivek and I chatted earlier and sorted this out; we're all good for now.

            vivek Vivek Pandey
            cliffmeyers Cliff Meyers
            Votes:
            0 Vote for this issue
            Watchers:
            4 Start watching this issue

              Created:
              Updated:
              Resolved: