{"action":"created","comment":{"url":"https://api.github.com/repos/openshift/ci-operator-prowgen/pulls/comments/244794895","pull_request_review_id":188753615,"id":244794895,"node_id":"MDI0OlB1bGxSZXF1ZXN0UmV2aWV3Q29tbWVudDI0NDc5NDg5NQ==","diff_hunk":"@@ -0,0 +1,313 @@\n+package main\n+\n+import (\n+\t\"flag\"\n+\t\"fmt\"\n+\t\"io/ioutil\"\n+\t\"os\"\n+\t\"path/filepath\"\n+\t\"strings\"\n+\n+\t// TODO: Solve this properly\n+\t// \"github.com/davecgh/go-spew/spew\"\n+\t\"github.com/getlantern/deepcopy\"\n+\t\"github.com/ghodss/yaml\"\n+\t\"github.com/sirupsen/logrus\"\n+\n+\tpjapi \"k8s.io/test-infra/prow/apis/prowjobs/v1\"\n+\tpjclientset \"k8s.io/test-infra/prow/client/clientset/versioned\"\n+\tpj \"k8s.io/test-infra/prow/client/clientset/versioned/typed/prowjobs/v1\"\n+\t\"k8s.io/test-infra/prow/config\"\n+\tprowflagutil \"k8s.io/test-infra/prow/flagutil\"\n+\t\"k8s.io/test-infra/prow/github\"\n+\t\"k8s.io/test-infra/prow/pjutil\"\n+\n+\tv1 \"k8s.io/api/core/v1\"\n+\tmetav1 \"k8s.io/apimachinery/pkg/apis/meta/v1\"\n+\tcorev1 \"k8s.io/client-go/kubernetes/typed/core/v1\"\n+\n+\t\"k8s.io/client-go/rest\"\n+\t\"k8s.io/client-go/tools/clientcmd\"\n+)\n+\n+func getJobsToExecute(ca *config.Agent) config.JobConfig {\n+\tvar youHaveOneJob config.Presubmit\n+\tfor _, job := range ca.Config().Presubmits[\"openshift/ci-operator\"] {\n+\t\tif job.Name == \"pull-ci-openshift-ci-operator-master-build\" {\n+\t\t\tyouHaveOneJob = job\n+\t\t\tbreak\n+\t\t}\n+\t}\n+\n+\tjobs := config.JobConfig{\n+\t\tPresubmits: map[string][]config.Presubmit{\"openshift/ci-operator\": []config.Presubmit{youHaveOneJob}},\n+\t}\n+\treturn jobs\n+}\n+\n+func makeRehearsalPresubmit(source *config.Presubmit, repo string, prNumber int) (*config.Presubmit, error) {\n+\tvar rehearsal config.Presubmit\n+\tdeepcopy.Copy(&rehearsal, source)\n+\n+\trehearsal.Name = fmt.Sprintf(\"rehearse-%d-%s\", prNumber, source.Name)\n+\trehearsal.Context = fmt.Sprintf(\"ci/rehearse/%s/%s\", repo, strings.TrimPrefix(source.Context, \"ci/prow/\"))\n+\n+\tif len(source.Spec.Containers) != 1 {\n+\t\treturn nil, fmt.Errorf(\"Cannot rehearse jobs with more than 1 container in Spec\")\n+\t}\n+\tcontainer := source.Spec.Containers[0]\n+\n+\tif len(container.Command) != 1 || container.Command[0] != \"ci-operator\" {\n+\t\treturn nil, fmt.Errorf(\"Cannot rehearse jobs that have Command different from simple 'ci-operator'\")\n+\t}\n+\n+\tfor _, arg := range container.Args {\n+\t\tif strings.HasPrefix(arg, \"--git-ref\") || strings.HasPrefix(arg, \"-git-ref\") {\n+\t\t\treturn nil, fmt.Errorf(\"Cannot rehearse jobs that call ci-operator with '--git-ref' arg\")\n+\t\t}\n+\t}\n+\n+\tif len(source.Branches) != 1 {\n+\t\treturn nil, fmt.Errorf(\"Cannot rehearse jobs that run over multiple branches\")\n+\t}\n+\tbranch := strings.TrimPrefix(strings.TrimSuffix(source.Branches[0], \"$\"), \"^\")\n+\n+\tgitrefArg := fmt.Sprintf(\"--git-ref=%s@%s\", repo, branch)\n+\trehearsal.Spec.Containers[0].Args = append(source.Spec.Containers[0].Args, gitrefArg)\n+\n+\treturn &rehearsal, nil\n+}\n+\n+func loadClusterConfig() (*rest.Config, error) {\n+\tclusterConfig, err := rest.InClusterConfig()\n+\tif err == nil {\n+\t\treturn clusterConfig, nil\n+\t}\n+\n+\tcredentials, err := clientcmd.NewDefaultClientConfigLoadingRules().Load()\n+\tif err != nil {\n+\t\treturn nil, fmt.Errorf(\"could not load credentials from config: %v\", err)\n+\t}\n+\n+\tclusterConfig, err = clientcmd.NewDefaultClientConfig(*credentials, &clientcmd.ConfigOverrides{}).ClientConfig()\n+\tif err != nil {\n+\t\treturn nil, fmt.Errorf(\"could not load client configuration: %v\", err)\n+\t}\n+\treturn clusterConfig, nil\n+}\n+\n+func submitRehearsal(job *config.Presubmit, pr *github.PullRequest, logger *logrus.Entry, pjclient pj.ProwJobInterface, dry bool) (*pjapi.ProwJob, error) {\n+\tpj := pjutil.NewPresubmit(*pr, \"\", *job, \"\")\n+\tlogger.WithFields(pjutil.ProwJobFields(&pj)).Info(\"Submitting a new prowjob.\")\n+\n+\tif dry {\n+\t\tjobAsYAML, err := yaml.Marshal(pj)\n+\t\tif err != nil {\n+\t\t\treturn nil, fmt.Errorf(\"Failed to marshal job to YAML: %v\", err)\n+\t\t}\n+\t\tfmt.Printf(\"%s\\n\", jobAsYAML)\n+\t\treturn &pj, nil\n+\t}\n+\n+\tcreated, err := pjclient.Create(&pj)\n+\tif err != nil {\n+\t\treturn created, err\n+\t}\n+\n+\treturn created, nil\n+}\n+\n+func fixupCioperatorConfigPath(job *config.Presubmit, rehearsalCMName string) string {\n+\tfor _, container := range job.Spec.Containers {\n+\t\tfor _, env := range container.Env {\n+\t\t\tif env.ValueFrom == nil {\n+\t\t\t\tcontinue\n+\t\t\t}\n+\t\t\tif env.ValueFrom.ConfigMapKeyRef == nil {\n+\t\t\t\tcontinue\n+\t\t\t}\n+\t\t\tif env.ValueFrom.ConfigMapKeyRef.Name == \"ci-operator-configs\" {\n+\t\t\t\tfilename := env.ValueFrom.ConfigMapKeyRef.Key\n+\t\t\t\tenv.ValueFrom.ConfigMapKeyRef.Name = rehearsalCMName\n+\t\t\t\treturn filename\n+\t\t\t}\n+\t\t}\n+\t}\n+\n+\treturn \"\"\n+}\n+\n+func createRehearsalCiopConfigCM(configs map[string]string, configDir string, name string, cmclient corev1.ConfigMapInterface, logger *logrus.Entry, dry bool) error {\n+\tcm := &v1.ConfigMap{\n+\t\tObjectMeta: metav1.ObjectMeta{Name: name},\n+\t\tData:       map[string]string{},\n+\t}\n+\tlogger = logger.WithField(\"ciop-configs-cm\", name)\n+\tlogger.Info(\"Preparing rehearsal ConfigMap for ci-operator configs\")\n+\n+\tfor key, path := range configs {\n+\t\tfullPath := filepath.Join(configDir, path)\n+\t\tcontent, err := ioutil.ReadFile(fullPath)\n+\t\tlogger.WithField(\"ciop-config\", key).Info(\"Loading ci-operator config to rehearsal ConfigMap\")\n+\t\tif err != nil {\n+\t\t\treturn fmt.Errorf(\"failed to read ci-operator config file from %s: %v\", fullPath, err)\n+\t\t}\n+\n+\t\tcm.Data[key] = string(content)\n+\t}\n+\n+\tif dry {\n+\t\tcmAsYAML, err := yaml.Marshal(cm)\n+\t\tif err != nil {\n+\t\t\treturn fmt.Errorf(\"Failed to marshal ConfigMap to YAML: %v\", err)\n+\t\t}\n+\t\tfmt.Printf(\"%s\\n\", cmAsYAML)\n+\t\treturn nil\n+\t}\n+\tlogger.Info(\"Creating rehearsal ConfigMap for ci-operator configs\")\n+\t_, err := cmclient.Create(cm)\n+\treturn err\n+}\n+\n+func execute(jobs config.JobConfig, pr *github.PullRequest, githubClient *github.Client, logger *logrus.Entry, ciopConfigsPath string, pjclient pj.ProwJobInterface, cmclient corev1.ConfigMapInterface, dry bool) error {\n+\trehearsals := []*config.Presubmit{}\n+\tciopConfigs := map[string]string{}\n+\trehearsalCiopConfigCMName := fmt.Sprintf(\"rehearsal-ci-operator-configs-%d\", pr.Number)\n+\tvar logFields logrus.Fields\n+\n+\tfor repo, jobs := range jobs.Presubmits {\n+\t\tfor _, job := range jobs {\n+\t\t\tlogFields = logrus.Fields{\"target-repo\": repo, \"target-job\": job.Name}\n+\t\t\trehearsal, err := makeRehearsalPresubmit(&job, repo, pr.Number)\n+\t\t\tif err != nil {\n+\t\t\t\tlogger.WithFields(logFields).WithError(err).Warn(\"Failed to make a rehearsal presubmit\")\n+\t\t\t} else {\n+\t\t\t\tlogger.WithFields(logFields).WithFields(logrus.Fields{\"rehearsal-job\": rehearsal.Name}).Info(\"Created a rehearsal job to be submitted\")\n+\t\t\t\trehearsals = append(rehearsals, rehearsal)\n+\t\t\t\tcioperatorConfig := fixupCioperatorConfigPath(rehearsal, rehearsalCiopConfigCMName)\n+\t\t\t\tif len(cioperatorConfig) > 0 {\n+\t\t\t\t\tlogger.WithFields(logFields).WithField(\"ci-operator-config\", cioperatorConfig).Info(\"Rehearsal job uses ci-operator config ConfigMap\")\n+\t\t\t\t\tciopConfigs[cioperatorConfig] = fmt.Sprintf(\"%s/%s\", repo, cioperatorConfig)\n+\t\t\t\t}\n+\t\t\t}\n+\t\t}\n+\t}\n+\n+\tif len(rehearsals) > 0 {\n+\t\tif err := createRehearsalCiopConfigCM(ciopConfigs, ciopConfigsPath, rehearsalCiopConfigCMName, cmclient, logger, dry); err != nil {\n+\t\t\treturn fmt.Errorf(\"failed to prepare rehearsal ci-operator config ConfigMap: %v\", err)\n+\t\t}\n+\t\tfor _, job := range rehearsals {\n+\t\t\tcreated, err := submitRehearsal(job, pr, logger, pjclient, dry)\n+\t\t\tif err != nil {\n+\t\t\t\tlogger.WithError(err).Warn(\"Failed to execute a rehearsal presubmit presubmit\")\n+\t\t\t} else {\n+\t\t\t\tlogger.WithFields(pjutil.ProwJobFields(created)).Info(\"Submitted rehearsal prowjob\")\n+\t\t\t}\n+\t\t}\n+\t} else {\n+\t\tlogger.WithFields(logFields).Warn(\"No job rehearsals\")\n+\t}\n+\n+\treturn nil\n+}\n+\n+type options struct {\n+\tdryRun bool\n+\n+\tconfigPath      string\n+\tjobConfigPath   string\n+\tciopConfigsPath string\n+\n+\tprowConfigOrg  string\n+\tprowConfigRepo string\n+\tprowConfigPR   int\n+\n+\tgithub prowflagutil.GitHubOptions\n+}\n+\n+func gatherOptions() options {\n+\to := options{}\n+\tfs := flag.NewFlagSet(os.Args[0], flag.ExitOnError)\n+\tfs.BoolVar(&o.dryRun, \"dry-run\", true, \"Whether to actually submit rehearsal jobs to Prow\")\n+\n+\tfs.StringVar(&o.configPath, \"config-path\", \"/etc/config/config.yaml\", \"Path to Prow config.yaml\")\n+\tfs.StringVar(&o.jobConfigPath, \"job-config-path\", \"\", \"Path to Prow job config file\")\n+\tfs.StringVar(&o.ciopConfigsPath, \"ci-operator-configs\", \"\", \"Path to a directory containing ci-operator configs\")\n+\n+\tfs.StringVar(&o.prowConfigOrg, \"prow-config-org\", \"openshift\", \"GitHub organization holding the repo with Prow config\")\n+\tfs.StringVar(&o.prowConfigRepo, \"prow-config-repo\", \"release\", \"Name of GitHub repository with Prow config\")\n+\tfs.IntVar(&o.prowConfigPR, \"pr\", 0, \"Pull Request ID on the Prow config repository for which to rehearse jobs\")\n+\n+\to.github.AddFlags(fs)\n+\n+\tfs.Parse(os.Args[1:])\n+\treturn o\n+}\n+\n+func (o *options) Validate() error {\n+\tif err := o.github.Validate(o.dryRun); err != nil {\n+\t\treturn err\n+\t}\n+\n+\treturn nil\n+}\n+\n+func main() {\n+\to := gatherOptions()\n+\tif err := o.Validate(); err != nil {\n+\t\tlogrus.WithError(err).Fatal(\"Failed to validate provided options\")\n+\t}\n+\n+\tprFields := logrus.Fields{\"org\": o.prowConfigOrg, \"repo\": o.prowConfigRepo, \"PR\": o.prowConfigPR}\n+\tlogger := logrus.WithFields(prFields)\n+\tlogger.Info(\"Rehearsing Prow jobs for a configuration PR\")\n+\n+\tsecretAgent := &config.SecretAgent{}\n+\tif o.github.TokenPath != \"\" {\n+\t\tif err := secretAgent.Start([]string{o.github.TokenPath}); err != nil {\n+\t\t\tlogger.WithError(err).Fatal(\"Failed to start secrets agent\")\n+\t\t}\n+\t} else {\n+\t\tlogger.Fatal(\"Cannot start secrets agent without GitHub token\")\n+\t}\n+\n+\tgithubClient, err := o.github.GitHubClient(secretAgent, o.dryRun)\n+\tif err != nil {\n+\t\tlogger.WithError(err).Fatal(\"Failed to create GitHub client\")\n+\t}\n+\n+\tpr, err := githubClient.GetPullRequest(o.prowConfigOrg, o.prowConfigRepo, o.prowConfigPR)","path":"cmd/rehearse/main.go","position":null,"original_position":280,"commit_id":"e92169e8de150e425c91535b8d538ab34381b64d","original_commit_id":"8d8e8b5e0401b40eb860c097c7a4453ba49dec3f","user":{"login":"petr-muller","id":712614,"node_id":"MDQ6VXNlcjcxMjYxNA==","avatar_url":"https://avatars3.githubusercontent.com/u/712614?v=4","gravatar_id":"","url":"https://api.github.com/users/petr-muller","html_url":"https://github.com/petr-muller","followers_url":"https://api.github.com/users/petr-muller/followers","following_url":"https://api.github.com/users/petr-muller/following{/other_user}","gists_url":"https://api.github.com/users/petr-muller/gists{/gist_id}","starred_url":"https://api.github.com/users/petr-muller/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/petr-muller/subscriptions","organizations_url":"https://api.github.com/users/petr-muller/orgs","repos_url":"https://api.github.com/users/petr-muller/repos","events_url":"https://api.github.com/users/petr-muller/events{/privacy}","received_events_url":"https://api.github.com/users/petr-muller/received_events","type":"User","site_admin":false},"body":"Done!","created_at":"2019-01-02T17:07:19Z","updated_at":"2019-01-02T17:07:19Z","html_url":"https://github.com/openshift/ci-operator-prowgen/pull/49#discussion_r244794895","pull_request_url":"https://api.github.com/repos/openshift/ci-operator-prowgen/pulls/49","author_association":"MEMBER","_links":{"self":{"href":"https://api.github.com/repos/openshift/ci-operator-prowgen/pulls/comments/244794895"},"html":{"href":"https://github.com/openshift/ci-operator-prowgen/pull/49#discussion_r244794895"},"pull_request":{"href":"https://api.github.com/repos/openshift/ci-operator-prowgen/pulls/49"}},"in_reply_to_id":243586814},"pull_request":{"url":"https://api.github.com/repos/openshift/ci-operator-prowgen/pulls/49","id":239928778,"node_id":"MDExOlB1bGxSZXF1ZXN0MjM5OTI4Nzc4","html_url":"https://github.com/openshift/ci-operator-prowgen/pull/49","diff_url":"https://github.com/openshift/ci-operator-prowgen/pull/49.diff","patch_url":"https://github.com/openshift/ci-operator-prowgen/pull/49.patch","issue_url":"https://api.github.com/repos/openshift/ci-operator-prowgen/issues/49","number":49,"state":"open","locked":false,"title":"[WIP] Add an initial working version of `rehearse` tool","user":{"login":"petr-muller","id":712614,"node_id":"MDQ6VXNlcjcxMjYxNA==","avatar_url":"https://avatars3.githubusercontent.com/u/712614?v=4","gravatar_id":"","url":"https://api.github.com/users/petr-muller","html_url":"https://github.com/petr-muller","followers_url":"https://api.github.com/users/petr-muller/followers","following_url":"https://api.github.com/users/petr-muller/following{/other_user}","gists_url":"https://api.github.com/users/petr-muller/gists{/gist_id}","starred_url":"https://api.github.com/users/petr-muller/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/petr-muller/subscriptions","organizations_url":"https://api.github.com/users/petr-muller/orgs","repos_url":"https://api.github.com/users/petr-muller/repos","events_url":"https://api.github.com/users/petr-muller/events{/privacy}","received_events_url":"https://api.github.com/users/petr-muller/received_events","type":"User","site_admin":false},"body":"The `rehearse` binary takes a PR on a repository holding Prow job\r\nconfiguration (openshift/release by default) and submits ephemeral\r\n\"rehearsal\" Prow jobs. Rehearsal jobs are jobs configured for a\r\ndifferent OpenShift repo but executed on openshift/release repo PR to\r\ngive Prow job configuration authors early feedback on how their changes\r\nwill affect \"production\" Prow job executions.\r\n\r\nCurrent version of rehearse mocks the \"which jobs need be be executed\"\r\ncode and only focuses on the actual rehearsal job creation and\r\nsubmission.\r\n\r\nIf you manage to compile it, it can be used together with my [test PR](https://github.com/openshift/release/pull/2367), like this (you need to pass the PR2367 version of the files to `rehearse`):\r\n\r\n```\r\n$ ./rehearse --github-token-path=oauth --config-path=.../openshift/release/cluster/ci/config/prow/config.yaml --job-config-path=.../openshift/release/ci-operator/jobs/openshift/ci-operator/ --pr 2367\r\n``` \r\nCurrently, the tool is totally dumb, it only makes the modified and re-targeted Presubmit prowjobs and creates them in the cluster. It does not yet create any configmaps nor other resources for the created jobs to consume (that's my next step).\r\n\r\n### WIP items\r\n\r\n- [ ] Finish dependency resolution\r\nI have worked on the code in a standalone repo and tried to add the deps to `Gopkg.toml`, but my `dep ensure` fails on something that looks like the `test-infra` dependency path needs new-ish kubernetes version and the `ci-operator` path needs something old.\r\n- [x] Optimize the clientset creation\r\nI noticed I have a leftover code in that creates a ProwJob clientset for each job submitted, which should only be done once\r\n\r\n\r\n/cc @stevekuznetsov @bbguimaraes @droslean ","created_at":"2018-12-19T18:11:35Z","updated_at":"2019-01-02T17:07:19Z","closed_at":null,"merged_at":null,"merge_commit_sha":"e8394aede2787520531fe7f1697381e1dc4b0ded","assignee":null,"assignees":[],"requested_reviewers":[{"login":"bbguimaraes","id":934092,"node_id":"MDQ6VXNlcjkzNDA5Mg==","avatar_url":"https://avatars2.githubusercontent.com/u/934092?v=4","gravatar_id":"","url":"https://api.github.com/users/bbguimaraes","html_url":"https://github.com/bbguimaraes","followers_url":"https://api.github.com/users/bbguimaraes/followers","following_url":"https://api.github.com/users/bbguimaraes/following{/other_user}","gists_url":"https://api.github.com/users/bbguimaraes/gists{/gist_id}","starred_url":"https://api.github.com/users/bbguimaraes/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/bbguimaraes/subscriptions","organizations_url":"https://api.github.com/users/bbguimaraes/orgs","repos_url":"https://api.github.com/users/bbguimaraes/repos","events_url":"https://api.github.com/users/bbguimaraes/events{/privacy}","received_events_url":"https://api.github.com/users/bbguimaraes/received_events","type":"User","site_admin":false}],"requested_teams":[],"labels":[{"id":1033564388,"node_id":"MDU6TGFiZWwxMDMzNTY0Mzg4","url":"https://api.github.com/repos/openshift/ci-operator-prowgen/labels/approved","name":"approved","color":"0ffa16","default":false},{"id":1034074792,"node_id":"MDU6TGFiZWwxMDM0MDc0Nzky","url":"https://api.github.com/repos/openshift/ci-operator-prowgen/labels/do-not-merge/work-in-progress","name":"do-not-merge/work-in-progress","color":"e11d21","default":false},{"id":1033564566,"node_id":"MDU6TGFiZWwxMDMzNTY0NTY2","url":"https://api.github.com/repos/openshift/ci-operator-prowgen/labels/size/XXL","name":"size/XXL","color":"ee0000","default":false}],"milestone":null,"commits_url":"https://api.github.com/repos/openshift/ci-operator-prowgen/pulls/49/commits","review_comments_url":"https://api.github.com/repos/openshift/ci-operator-prowgen/pulls/49/comments","review_comment_url":"https://api.github.com/repos/openshift/ci-operator-prowgen/pulls/comments{/number}","comments_url":"https://api.github.com/repos/openshift/ci-operator-prowgen/issues/49/comments","statuses_url":"https://api.github.com/repos/openshift/ci-operator-prowgen/statuses/e92169e8de150e425c91535b8d538ab34381b64d","head":{"label":"petr-muller:rehearse","ref":"rehearse","sha":"e92169e8de150e425c91535b8d538ab34381b64d","user":{"login":"petr-muller","id":712614,"node_id":"MDQ6VXNlcjcxMjYxNA==","avatar_url":"https://avatars3.githubusercontent.com/u/712614?v=4","gravatar_id":"","url":"https://api.github.com/users/petr-muller","html_url":"https://github.com/petr-muller","followers_url":"https://api.github.com/users/petr-muller/followers","following_url":"https://api.github.com/users/petr-muller/following{/other_user}","gists_url":"https://api.github.com/users/petr-muller/gists{/gist_id}","starred_url":"https://api.github.com/users/petr-muller/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/petr-muller/subscriptions","organizations_url":"https://api.github.com/users/petr-muller/orgs","repos_url":"https://api.github.com/users/petr-muller/repos","events_url":"https://api.github.com/users/petr-muller/events{/privacy}","received_events_url":"https://api.github.com/users/petr-muller/received_events","type":"User","site_admin":false},"repo":{"id":146293604,"node_id":"MDEwOlJlcG9zaXRvcnkxNDYyOTM2MDQ=","name":"ci-operator-prowgen","full_name":"petr-muller/ci-operator-prowgen","private":false,"owner":{"login":"petr-muller","id":712614,"node_id":"MDQ6VXNlcjcxMjYxNA==","avatar_url":"https://avatars3.githubusercontent.com/u/712614?v=4","gravatar_id":"","url":"https://api.github.com/users/petr-muller","html_url":"https://github.com/petr-muller","followers_url":"https://api.github.com/users/petr-muller/followers","following_url":"https://api.github.com/users/petr-muller/following{/other_user}","gists_url":"https://api.github.com/users/petr-muller/gists{/gist_id}","starred_url":"https://api.github.com/users/petr-muller/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/petr-muller/subscriptions","organizations_url":"https://api.github.com/users/petr-muller/orgs","repos_url":"https://api.github.com/users/petr-muller/repos","events_url":"https://api.github.com/users/petr-muller/events{/privacy}","received_events_url":"https://api.github.com/users/petr-muller/received_events","type":"User","site_admin":false},"html_url":"https://github.com/petr-muller/ci-operator-prowgen","description":"A generator for Prow job configuration from CI Operator configuration","fork":true,"url":"https://api.github.com/repos/petr-muller/ci-operator-prowgen","forks_url":"https://api.github.com/repos/petr-muller/ci-operator-prowgen/forks","keys_url":"https://api.github.com/repos/petr-muller/ci-operator-prowgen/keys{/key_id}","collaborators_url":"https://api.github.com/repos/petr-muller/ci-operator-prowgen/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/petr-muller/ci-operator-prowgen/teams","hooks_url":"https://api.github.com/repos/petr-muller/ci-operator-prowgen/hooks","issue_events_url":"https://api.github.com/repos/petr-muller/ci-operator-prowgen/issues/events{/number}","events_url":"https://api.github.com/repos/petr-muller/ci-operator-prowgen/events","assignees_url":"https://api.github.com/repos/petr-muller/ci-operator-prowgen/assignees{/user}","branches_url":"https://api.github.com/repos/petr-muller/ci-operator-prowgen/branches{/branch}","tags_url":"https://api.github.com/repos/petr-muller/ci-operator-prowgen/tags","blobs_url":"https://api.github.com/repos/petr-muller/ci-operator-prowgen/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/petr-muller/ci-operator-prowgen/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/petr-muller/ci-operator-prowgen/git/refs{/sha}","trees_url":"https://api.github.com/repos/petr-muller/ci-operator-prowgen/git/trees{/sha}","statuses_url":"https://api.github.com/repos/petr-muller/ci-operator-prowgen/statuses/{sha}","languages_url":"https://api.github.com/repos/petr-muller/ci-operator-prowgen/languages","stargazers_url":"https://api.github.com/repos/petr-muller/ci-operator-prowgen/stargazers","contributors_url":"https://api.github.com/repos/petr-muller/ci-operator-prowgen/contributors","subscribers_url":"https://api.github.com/repos/petr-muller/ci-operator-prowgen/subscribers","subscription_url":"https://api.github.com/repos/petr-muller/ci-operator-prowgen/subscription","commits_url":"https://api.github.com/repos/petr-muller/ci-operator-prowgen/commits{/sha}","git_commits_url":"https://api.github.com/repos/petr-muller/ci-operator-prowgen/git/commits{/sha}","comments_url":"https://api.github.com/repos/petr-muller/ci-operator-prowgen/comments{/number}","issue_comment_url":"https://api.github.com/repos/petr-muller/ci-operator-prowgen/issues/comments{/number}","contents_url":"https://api.github.com/repos/petr-muller/ci-operator-prowgen/contents/{+path}","compare_url":"https://api.github.com/repos/petr-muller/ci-operator-prowgen/compare/{base}...{head}","merges_url":"https://api.github.com/repos/petr-muller/ci-operator-prowgen/merges","archive_url":"https://api.github.com/repos/petr-muller/ci-operator-prowgen/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/petr-muller/ci-operator-prowgen/downloads","issues_url":"https://api.github.com/repos/petr-muller/ci-operator-prowgen/issues{/number}","pulls_url":"https://api.github.com/repos/petr-muller/ci-operator-prowgen/pulls{/number}","milestones_url":"https://api.github.com/repos/petr-muller/ci-operator-prowgen/milestones{/number}","notifications_url":"https://api.github.com/repos/petr-muller/ci-operator-prowgen/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/petr-muller/ci-operator-prowgen/labels{/name}","releases_url":"https://api.github.com/repos/petr-muller/ci-operator-prowgen/releases{/id}","deployments_url":"https://api.github.com/repos/petr-muller/ci-operator-prowgen/deployments","created_at":"2018-08-27T12:20:32Z","updated_at":"2018-08-27T12:20:34Z","pushed_at":"2019-01-02T17:07:03Z","git_url":"git://github.com/petr-muller/ci-operator-prowgen.git","ssh_url":"git@github.com:petr-muller/ci-operator-prowgen.git","clone_url":"https://github.com/petr-muller/ci-operator-prowgen.git","svn_url":"https://github.com/petr-muller/ci-operator-prowgen","homepage":null,"size":27243,"stargazers_count":0,"watchers_count":0,"language":"Go","has_issues":false,"has_projects":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":0,"mirror_url":null,"archived":false,"open_issues_count":0,"license":null,"forks":0,"open_issues":0,"watchers":0,"default_branch":"master"}},"base":{"label":"openshift:master","ref":"master","sha":"0c584f7c7d6871cc1c64d7e54ccfa54c38ef8081","user":{"login":"openshift","id":792337,"node_id":"MDEyOk9yZ2FuaXphdGlvbjc5MjMzNw==","avatar_url":"https://avatars3.githubusercontent.com/u/792337?v=4","gravatar_id":"","url":"https://api.github.com/users/openshift","html_url":"https://github.com/openshift","followers_url":"https://api.github.com/users/openshift/followers","following_url":"https://api.github.com/users/openshift/following{/other_user}","gists_url":"https://api.github.com/users/openshift/gists{/gist_id}","starred_url":"https://api.github.com/users/openshift/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/openshift/subscriptions","organizations_url":"https://api.github.com/users/openshift/orgs","repos_url":"https://api.github.com/users/openshift/repos","events_url":"https://api.github.com/users/openshift/events{/privacy}","received_events_url":"https://api.github.com/users/openshift/received_events","type":"Organization","site_admin":false},"repo":{"id":145899484,"node_id":"MDEwOlJlcG9zaXRvcnkxNDU4OTk0ODQ=","name":"ci-operator-prowgen","full_name":"openshift/ci-operator-prowgen","private":false,"owner":{"login":"openshift","id":792337,"node_id":"MDEyOk9yZ2FuaXphdGlvbjc5MjMzNw==","avatar_url":"https://avatars3.githubusercontent.com/u/792337?v=4","gravatar_id":"","url":"https://api.github.com/users/openshift","html_url":"https://github.com/openshift","followers_url":"https://api.github.com/users/openshift/followers","following_url":"https://api.github.com/users/openshift/following{/other_user}","gists_url":"https://api.github.com/users/openshift/gists{/gist_id}","starred_url":"https://api.github.com/users/openshift/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/openshift/subscriptions","organizations_url":"https://api.github.com/users/openshift/orgs","repos_url":"https://api.github.com/users/openshift/repos","events_url":"https://api.github.com/users/openshift/events{/privacy}","received_events_url":"https://api.github.com/users/openshift/received_events","type":"Organization","site_admin":false},"html_url":"https://github.com/openshift/ci-operator-prowgen","description":"A generator for Prow job configuration from CI Operator configuration","fork":false,"url":"https://api.github.com/repos/openshift/ci-operator-prowgen","forks_url":"https://api.github.com/repos/openshift/ci-operator-prowgen/forks","keys_url":"https://api.github.com/repos/openshift/ci-operator-prowgen/keys{/key_id}","collaborators_url":"https://api.github.com/repos/openshift/ci-operator-prowgen/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/openshift/ci-operator-prowgen/teams","hooks_url":"https://api.github.com/repos/openshift/ci-operator-prowgen/hooks","issue_events_url":"https://api.github.com/repos/openshift/ci-operator-prowgen/issues/events{/number}","events_url":"https://api.github.com/repos/openshift/ci-operator-prowgen/events","assignees_url":"https://api.github.com/repos/openshift/ci-operator-prowgen/assignees{/user}","branches_url":"https://api.github.com/repos/openshift/ci-operator-prowgen/branches{/branch}","tags_url":"https://api.github.com/repos/openshift/ci-operator-prowgen/tags","blobs_url":"https://api.github.com/repos/openshift/ci-operator-prowgen/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/openshift/ci-operator-prowgen/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/openshift/ci-operator-prowgen/git/refs{/sha}","trees_url":"https://api.github.com/repos/openshift/ci-operator-prowgen/git/trees{/sha}","statuses_url":"https://api.github.com/repos/openshift/ci-operator-prowgen/statuses/{sha}","languages_url":"https://api.github.com/repos/openshift/ci-operator-prowgen/languages","stargazers_url":"https://api.github.com/repos/openshift/ci-operator-prowgen/stargazers","contributors_url":"https://api.github.com/repos/openshift/ci-operator-prowgen/contributors","subscribers_url":"https://api.github.com/repos/openshift/ci-operator-prowgen/subscribers","subscription_url":"https://api.github.com/repos/openshift/ci-operator-prowgen/subscription","commits_url":"https://api.github.com/repos/openshift/ci-operator-prowgen/commits{/sha}","git_commits_url":"https://api.github.com/repos/openshift/ci-operator-prowgen/git/commits{/sha}","comments_url":"https://api.github.com/repos/openshift/ci-operator-prowgen/comments{/number}","issue_comment_url":"https://api.github.com/repos/openshift/ci-operator-prowgen/issues/comments{/number}","contents_url":"https://api.github.com/repos/openshift/ci-operator-prowgen/contents/{+path}","compare_url":"https://api.github.com/repos/openshift/ci-operator-prowgen/compare/{base}...{head}","merges_url":"https://api.github.com/repos/openshift/ci-operator-prowgen/merges","archive_url":"https://api.github.com/repos/openshift/ci-operator-prowgen/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/openshift/ci-operator-prowgen/downloads","issues_url":"https://api.github.com/repos/openshift/ci-operator-prowgen/issues{/number}","pulls_url":"https://api.github.com/repos/openshift/ci-operator-prowgen/pulls{/number}","milestones_url":"https://api.github.com/repos/openshift/ci-operator-prowgen/milestones{/number}","notifications_url":"https://api.github.com/repos/openshift/ci-operator-prowgen/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/openshift/ci-operator-prowgen/labels{/name}","releases_url":"https://api.github.com/repos/openshift/ci-operator-prowgen/releases{/id}","deployments_url":"https://api.github.com/repos/openshift/ci-operator-prowgen/deployments","created_at":"2018-08-23T19:42:28Z","updated_at":"2018-12-20T12:39:51Z","pushed_at":"2019-01-02T17:07:08Z","git_url":"git://github.com/openshift/ci-operator-prowgen.git","ssh_url":"git@github.com:openshift/ci-operator-prowgen.git","clone_url":"https://github.com/openshift/ci-operator-prowgen.git","svn_url":"https://github.com/openshift/ci-operator-prowgen","homepage":null,"size":27227,"stargazers_count":4,"watchers_count":4,"language":"Go","has_issues":true,"has_projects":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":10,"mirror_url":null,"archived":false,"open_issues_count":3,"license":null,"forks":10,"open_issues":3,"watchers":4,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/openshift/ci-operator-prowgen/pulls/49"},"html":{"href":"https://github.com/openshift/ci-operator-prowgen/pull/49"},"issue":{"href":"https://api.github.com/repos/openshift/ci-operator-prowgen/issues/49"},"comments":{"href":"https://api.github.com/repos/openshift/ci-operator-prowgen/issues/49/comments"},"review_comments":{"href":"https://api.github.com/repos/openshift/ci-operator-prowgen/pulls/49/comments"},"review_comment":{"href":"https://api.github.com/repos/openshift/ci-operator-prowgen/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/openshift/ci-operator-prowgen/pulls/49/commits"},"statuses":{"href":"https://api.github.com/repos/openshift/ci-operator-prowgen/statuses/e92169e8de150e425c91535b8d538ab34381b64d"}},"author_association":"MEMBER"}}
{"actor":{"display_login":"petr-muller"}}