Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
Merge branch 'master' into story/JENKINS-42791-editor-prompt-github-t…
…oken

# Conflicts:
#	src/main/js/EditorPage.jsx
  • Loading branch information
Cliff Meyers committed Aug 8, 2017
2 parents ccfaa78 + e9596fc commit 49a8029
Show file tree
Hide file tree
Showing 5 changed files with 91 additions and 43 deletions.
3 changes: 0 additions & 3 deletions Jenkinsfile
Expand Up @@ -8,9 +8,6 @@ pipeline {
}
}
post {
success {
archive 'target/blueocean-pipeline-editor.hpi'
}
always {
junit 'target/**/*.xml'
}
Expand Down
15 changes: 15 additions & 0 deletions PULL_REQUEST_TEMPLATE
@@ -0,0 +1,15 @@
# Description

See [JENKINS-XXXXX](https://issues.jenkins-ci.org/browse/JENKINS-XXXXX).

# Submitter checklist
- [ ] Link to JIRA ticket in description, if appropriate.
- [ ] Change is code complete and matches issue description
- [ ] Appropriate unit or acceptance tests or explanation to why this change has no tests
- [ ] Reviewer's manual test instructions provided in PR description. See Reviewer's first task below.

# Reviewer checklist
- [ ] Run the changes and verified the change matches the issue description
- [ ] Reviewed the code
- [ ] Verified that the appropriate tests have been written or valid explanation given

37 changes: 22 additions & 15 deletions README.md
Expand Up @@ -6,18 +6,25 @@ This repository houses the [Jenkins](https://jenkins.io/) plugin for creating an

:exclamation: **Important!** This software is a work-in-progress and is not complete.

## Project Layout

(here be dragons, this may not be up-to-date, etc)

* /.storybook - Configuration files for [React Storybook](https://getstorybook.io/).
* /doc - Documentation resources
* /src
* /main
* /js - Some top-level things like ExtensionPoint implementations, and jenkins-js-extension.yaml metadata, etc
* /components - Contains EditorDemo.jsx, showing an example usage of the visual editor component
* /editor - Contains components and shared utils / types for the visual editor
* /declarations - Flowtype declarations for externals
* /stories - Test case stories for React Storybook
* /less - CSS Styles, in .less format
* /resources - Misc plugin resources. Contains index.jelly required for Jenkins HPI
## Running Locally

To start a new jenkins and run this pluging for development purposes:

```
# Start a local Jenkins
mvn hpi:run
```

And in another term,
```
# Watch and build the JS
npm run bundle:watch
```


## Running in another development Jenkins Instance

```
# Link this as a plugin into your Blue Ocean Jenkins' hpi:run server
mvn hpi:hpl -DjenkinsHome=<path-to-blueocean-home/blueocean/work>
```
38 changes: 24 additions & 14 deletions src/main/js/EditorPage.jsx
Expand Up @@ -213,11 +213,11 @@ class PipelineLoader extends React.Component {
if (!branch) {
const split = pipeline.split('/');
const team = split[0];
const repo = split[1];
const provider = 'github';
Fetch.fetchJSON(`${getRestUrl({organization})}scm/${provider}/`)
const repo = split.length > 1 ? split[1] : team;
const scmId = this.state.scmSource.id;
Fetch.fetchJSON(`${getRestUrl({organization})}scm/${scmId}/`)
.then( ({ credentialId }) =>
Fetch.fetchJSON(`${getRestUrl({organization})}scm/${provider}/organizations/${team}/repositories/${repo}/?credentialId=${credentialId}`)
Fetch.fetchJSON(`${getRestUrl({organization})}scm/${scmId}/organizations/${team}/repositories/${repo}/?credentialId=${credentialId}`)
)
.then( ({ defaultBranch }) => {
this.defaultBranch = defaultBranch || 'master';
Expand Down Expand Up @@ -430,7 +430,7 @@ class PipelineLoader extends React.Component {
this.setState({dialog: null});
});
}

showSaveDialog() {
pipelineValidator.validate(err => {
if (!pipelineValidator.hasValidationErrors(pipelineStore.pipeline)) {
Expand All @@ -447,7 +447,7 @@ class PipelineLoader extends React.Component {
const split = pipeline.split('/');
const team = split[0];
const repo = split[1];
const saveMessage = commitMessage || (this.state.sha ? 'Updated Jenkinsfile' : 'Added Jenkinsfile');
const saveMessage = commitMessage || (this.state.isSaved ? 'Updated Jenkinsfile' : 'Added Jenkinsfile');
convertJsonToPipeline(JSON.stringify(pipelineJson), (pipelineScript, err) => {
if (!err) {
const saveParams = {
Expand All @@ -468,19 +468,29 @@ class PipelineLoader extends React.Component {
this.pipelineIsModified = false;
this.lastPipeline = JSON.stringify(convertInternalModelToJson(pipelineStore.pipeline));
// If this is a save on the same branch that already has a Jenkinsfile, just re-run it
if (this.state.sha && branch === data.content.branch) {
if (this.state.isSaved && branch === data.content.branch) {
RunApi.startRun({ _links: { self: { href: this.href + 'branches/' + encodeURIComponent(branch) + '/' }}})
.then(() => this.goToActivity())
.catch(err => errorHandler(err, body));
} else {
// otherwise, call indexing so this branch gets picked up
const { credential, scmSource} = this.state;
saveApi.index(organization, team, repo, scmSource.apiUrl, credential.credentialId,
() => this.goToActivity(),
err => errorHandler(err),
);
// if a different branch, call indexing so this one gets picked up
// only time we have 'github' is when we are using an org folder
// in which case use the existing saveApi
const scmId = this.state.scmSource.id;
if (scmId.startsWith('github')) {
const {credential, scmSource} = this.state;
saveApi.index(organization, team, repo, scmSource.apiUrl, credential.credentialId,
() => this.goToActivity(),
err => errorHandler(err),
);
} else {
//other scms, which are always MBP
RunApi.startRun({ _links: { self: { href: this.href + '/' }}})
.then(() => this.goToActivity())
.catch(err => errorHandler(err, body));
}
}
this.setState({ sha: data.sha });
this.setState({ sha: data.sha, isSaved: true });
})
.catch(err => {
errorHandler(err, body);
Expand Down
41 changes: 30 additions & 11 deletions src/main/js/PipelineEditorLink.jsx
Expand Up @@ -3,22 +3,14 @@
import React, { PropTypes } from 'react';
import { Link } from 'react-router';
import { Icon } from '@jenkins-cd/react-material-icons';
import { Paths, pipelineService } from '@jenkins-cd/blueocean-core-js';
import { Paths, pipelineService, AppConfig } from '@jenkins-cd/blueocean-core-js';
import Security from './services/Security';

class PipelineEditorLink extends React.Component {
state = {};

componentWillMount() {
const { pipeline } = this.props;
const folder = pipeline.fullName.split('/')[0];
const href = Paths.rest.apiRoot() + '/organizations/' + pipeline.organization + '/pipelines/' + folder + '/';
pipelineService.fetchPipeline(href, { useCache: true })
.then(pipeline => {
if (pipeline._class === 'io.jenkins.blueocean.blueocean_github_pipeline.GithubOrganizationFolder') {
this.setState({ supportsSave: true });
}
});
this._loadPipeline();
}

render() {
Expand All @@ -41,11 +33,38 @@ class PipelineEditorLink extends React.Component {
const baseUrl = `/organizations/${pipeline.organization}/pipeline-editor/${encodeURIComponent(pipelinePath.join('/'))}/${branch}/`;

return (
<Link className="pipeline-editor-link" to={baseUrl}>
<Link className="pipeline-editor-link" to={baseUrl} title="Edit">
<Icon icon="mode_edit" size={24} />
</Link>
);
}

_loadPipeline() {
const { pipeline } = this.props;
const folder = pipeline.fullName.split('/')[0];
const href = Paths.rest.apiRoot() + '/organizations/' + pipeline.organization + '/pipelines/' + folder + '/';
pipelineService.fetchPipeline(href, { useCache: true, disableCapabilites: false })
.then(pipeline => {
if (this._canSavePipeline(pipeline)) {
this.setState({ supportsSave: true });
}
});
}

_canSavePipeline(pipeline) {
if (pipeline.scmSource && pipeline.scmSource.id === 'git') {
if (AppConfig.isFeatureEnabled('GIT_PIPELINE_EDITOR', false)) {
return true;
} else {
return false;
}
}
if (pipeline._capabilities && pipeline._capabilities
.find(capability => capability === 'io.jenkins.blueocean.rest.model.BluePipelineScm')) {
return true;
}
return false;
}
}

PipelineEditorLink.propTypes = {
Expand Down

0 comments on commit 49a8029

Please sign in to comment.