Skip to content

Commit

Permalink
Merge pull request #23 from error418/feature/github-enterprise
Browse files Browse the repository at this point in the history
  • Loading branch information
tschulte committed Oct 18, 2017
2 parents 6efba7f + c14035c commit 82b5e84
Show file tree
Hide file tree
Showing 10 changed files with 378 additions and 30 deletions.
3 changes: 2 additions & 1 deletion .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@ addons:
packages:
- git
language: groovy
jdk: oraclejdk7
jdk:
- oraclejdk8
env: TERM=dumb
cache:
directories:
Expand Down
21 changes: 17 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,12 +25,12 @@ When `semantic-release` got setup it will do that after every successful continu

This module ships with the [AngularJS Commit Message Conventions](https://github.com/angular/angular.js/blob/master/CONTRIBUTING.md#commit) and changelog generator, but you can [define your own](#configuration) style.

> ### Commit Message Format
### Commit Message Format

> Each commit message consists of a **header**, a **body** and a **footer**. The header has a special
Each commit message consists of a **header**, a **body** and a **footer**. The header has a special
format that includes a **type**, a **scope** and a **subject**:

> ```
```
<type>(<scope>): <subject>
<BLANK LINE>
<body>
Expand Down Expand Up @@ -124,7 +124,7 @@ In order to automatically upload the changelog to GitHub, you need a [GitHub tok
```groovy
project.ext.ghToken = project.hasProperty('ghToken') ? project.getProperty('ghToken') : System.getenv('GH_TOKEN') ?: null
semanticRelease {
changeLog {
repo {
ghToken = project.ghToken
}
}
Expand All @@ -151,6 +151,19 @@ semanticRelease {
}
```

### Using with GitHub Enterprise

By specifying `useGhEnterprise` this plugin can be used to publish releases along with the changelog to a GitHub Enterprise server.

```groovy
semanticRelease {
repo {
ghToken = project.ext.ghToken
useGhEnterprise "https://github.enterprise" // GitHub Enterprise URL
}
}
```


### Setup travis-ci

Expand Down
1 change: 1 addition & 0 deletions build.gradle
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
apply plugin: 'de.gliderpilot.semantic-release'
apply plugin: 'idea'
apply plugin: 'eclipse'
apply plugin: 'com.github.ben-manes.versions'

apply from: 'gradle/credentials.gradle'
Expand Down
4 changes: 2 additions & 2 deletions gradle/code-quality.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -37,10 +37,10 @@ license {
strictCheck = true
ignoreFailures = true
mapping {
java = 'SLASHSTAR_STYLE'
java = 'SLASHSTAR_STYLE'
groovy = 'SLASHSTAR_STYLE'
}
ext.year = '2015'
ext.year = '2017'
}

licenseTest {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
/*
* Copyright 2017 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package de.gliderpilot.gradle.semanticrelease

import javax.ws.rs.core.HttpHeaders

import com.jcabi.github.Coordinates
import com.jcabi.github.Release
import com.jcabi.github.ReleaseAsset
import com.jcabi.github.ReleaseAssets
import com.jcabi.http.Request
import com.jcabi.http.response.JsonResponse
import com.jcabi.http.response.RestResponse

/** Adapter class for GitHub Enterprise API endpoints
*
* RtReleaseAssets class is declared final. Therefore this class can not be extended and
* makes a wrapper/adapter class (like this) necessary.
*
* Contents of the methods of this class are modified versions of the RtReleaseAssets class
* (with support for GitHub Enterprise servers)
*/
public class GhEnterpriseReleaseAssets implements ReleaseAssets {

private final Release owner
private final Request entry

final URI githubUploadEndpoint

public GhEnterpriseReleaseAssets(final String githubBaseUrl, Release owner, Request entry) {
this.githubUploadEndpoint = URI.create("${githubBaseUrl}/api/uploads") // base path for asset uploads
this.entry = entry
this.owner = owner
}

@Override
public ReleaseAsset upload(final byte[] content, final String type, final String name) throws IOException {
return this.get(
getAssetUploadRequest(content, type, name)
.fetch().as(RestResponse.class)
.assertStatus(HttpURLConnection.HTTP_CREATED)
.as(JsonResponse.class)
.json().readObject().getInt("id")
)
}

Request getAssetUploadRequest(final byte[] content, final String type, final String name) {
return this.entry.uri()
.set(this.githubUploadEndpoint)
.path("/repos")
.path(this.owner.repo().coordinates().user())
.path(this.owner.repo().coordinates().repo())
.path("/releases")
.path(String.valueOf(this.owner.number()))
.path("/assets")
.queryParam("name", name)
.back()
.method(Request.POST)
.reset(HttpHeaders.CONTENT_TYPE)
.header(HttpHeaders.CONTENT_TYPE, type)
.body().set(content).back()
}

@Override
public Release release() {
return owner.assets().release()
}

@Override
public Iterable<ReleaseAsset> iterate() {
return owner.assets().iterate()
}

@Override
public ReleaseAsset get(final int number) {
return owner.assets().get(number)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,14 @@ package de.gliderpilot.gradle.semanticrelease

import com.jcabi.github.Github
import com.jcabi.github.RtGithub
import com.jcabi.http.request.ApacheRequest
import com.jcabi.http.wire.AutoRedirectingWire
import groovy.transform.Memoized
import groovy.transform.PackageScope
import org.ajoberstar.grgit.Grgit

import javax.ws.rs.core.HttpHeaders
import javax.ws.rs.core.MediaType
import java.util.regex.Matcher

class GithubRepo extends GitRepo {
Expand All @@ -29,34 +33,89 @@ class GithubRepo extends GitRepo {

private Github github

private String ghBaseUrl

private boolean isGhEnterprise

private String ghToken

@PackageScope
Github getGithub() {
github
}

GithubRepo(Grgit grgit) {
this.ghBaseUrl = "https://github.com"
this.grgit = grgit
this.isGhEnterprise = false
}

void setGhToken(String githubToken) {
this.ghToken = githubToken
this.github = buildGithubReference()
}

void setGhToken(String token) {
if (token)
github = new RtGithub(token)
public String getGhBaseUrl() {
return this.ghBaseUrl
}

public void useGhEnterprise(String ghEnterpriseUrl) {
this.ghBaseUrl = ghEnterpriseUrl.replaceAll("/+\$", "") // remove trailing slashes
this.isGhEnterprise = true
this.github = buildGithubReference()
}

@PackageScope
@Memoized
String getMnemo() {
String repositoryUrl = grgit.remote.list().find { it.name == 'origin' }.url
Matcher matcher = repositoryUrl =~ /.*github.com[\/:]((?:.+?)\/(?:.+?))(?:\.git)/
if (!matcher)
return null
return matcher.group(1)
String repositoryUrl = grgit.getRemote().list().find { it.name == 'origin' }.url

return getPathFromRepositoryUrl(repositoryUrl)
}

/** Extracts the path of the repository.
*
* Will not check for the base path defined in ghBasePath
*
* @param repositoryUrl git remote url
* @return null when repository is not a github.com or GitHub Enterprise repository, otherwise path
*/
@PackageScope
String getPathFromRepositoryUrl(String repositoryUrl) {
// pathfinding logic extracted for better testability
boolean isGithubComRepository = (repositoryUrl ==~ /.*github.com[\/:]((?:.+?)\/(?:.+?))(?:\.git)/)
Matcher matcher = (repositoryUrl =~ /.+[\/:](.+?\/.+?)(?:\.git)$/)

if (isGithubComRepository || this.isGhEnterprise) {
return matcher.group(1)
}
return null
}

private RtGithub buildGithubReference() {
if (this.isGhEnterprise) {
// for github enterprise repositories
def request = new ApacheRequest("${ghBaseUrl}/api/v3")
.header(HttpHeaders.USER_AGENT, RtGithub.USER_AGENT)
.header(HttpHeaders.ACCEPT, MediaType.APPLICATION_JSON)
.header(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON)

if (this.ghToken != null) { // also add authentication token, if available
request = request.header(HttpHeaders.AUTHORIZATION, "token ${ghToken}")
}

request = request.through(AutoRedirectingWire.class)

return new RtGithub(request)
} else if (this.ghToken) { // for github.com repositories
return new RtGithub(this.ghToken)
}
}

private String repositoryUrl(String suffix) {
if (!mnemo)
return null
return "https://github.com/${mnemo}/$suffix"
return "${ghBaseUrl}/${mnemo}/$suffix"
}

String diffUrl(String previousTag, String currentTag) {
Expand All @@ -71,4 +130,4 @@ class GithubRepo extends GitRepo {
repositoryUrl("commit/${abbreviatedId}")
}

}
}
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ class SemanticReleaseChangeLogService {
@Deprecated
void setGhToken(String token) {
logger.warn("semanticRelease.changeLog.ghToken is deprecated and will be removed in v2.0.0")
logger.warn("use semanticRelease.gitRepo.ghToken instead")
logger.warn("use semanticRelease.repo.ghToken instead")
repo.ghToken = token
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,25 +15,27 @@
*/
package de.gliderpilot.gradle.semanticrelease

import org.ajoberstar.gradle.git.release.base.ReleaseVersion
import org.gradle.api.logging.Logger
import org.gradle.api.logging.Logging

import com.github.zafarkhaja.semver.Version
import com.jcabi.github.Coordinates
import com.jcabi.github.Release
import com.jcabi.github.ReleaseAsset
import com.jcabi.github.Repo

import groovy.transform.PackageScope
import org.ajoberstar.gradle.git.release.base.ReleaseVersion
import org.gradle.api.logging.Logger
import org.gradle.api.logging.Logging

@PackageScope
class UpdateGithubReleaseService {

private final Logger logger = Logging.getLogger(getClass())

void updateGithubRelease(SemanticReleaseChangeLogService changeLog,
GithubRepo githubRepo,
ReleaseVersion version,
String tagName) {
GithubRepo githubRepo,
ReleaseVersion version,
String tagName) {
Repo repo = githubRepo.github.repos().get(new Coordinates.Simple(githubRepo.mnemo))

// check for the existance of the tag using the api -> #3
Expand All @@ -43,12 +45,25 @@ class UpdateGithubReleaseService {

Release release = repo.releases().create(tagName)
def commits = changeLog.commits(Version.valueOf(version.previousVersion))
new Release.Smart(release).body(changeLog.changeLog(commits, version).toString())

Release uploadGate = new Release.Smart(release)
uploadGate.body(changeLog.changeLog(commits, version).toString())

def releaseAssets

if (githubRepo.isGhEnterprise) { // handle assets for GitHub Enterprise
releaseAssets = new GhEnterpriseReleaseAssets(githubRepo.getGhBaseUrl(), uploadGate, githubRepo.github.entry())
} else { // handle assets for github.com
releaseAssets = uploadGate.assets()
}

githubRepo.releaseAssets.each { asset ->
ReleaseAsset releaseAsset = release.assets().upload(asset.file.bytes, asset.contentType, asset.name)
if (asset.label)
ReleaseAsset releaseAsset = releaseAssets.upload(asset.file.bytes, asset.contentType, asset.name)
if (asset.label) {
new ReleaseAsset.Smart(releaseAsset).label(asset.label)
}
}

}

private boolean tagExists(Repo repo, String tag) {
Expand Down
Loading

0 comments on commit 82b5e84

Please sign in to comment.