Skip to content

Commit

Permalink
fix: use appropriate endpoint for GitHub Enterprise assets
Browse files Browse the repository at this point in the history
  • Loading branch information
error418 committed Oct 13, 2017
1 parent f9bc8d9 commit adfecc0
Show file tree
Hide file tree
Showing 4 changed files with 214 additions and 33 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
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 @@ -21,10 +21,10 @@ 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 com.jcabi.http.request.ApacheRequest;
import com.jcabi.http.wire.AutoRedirectingWire;
import javax.ws.rs.core.HttpHeaders
import javax.ws.rs.core.MediaType
import com.jcabi.http.request.ApacheRequest
import com.jcabi.http.wire.AutoRedirectingWire

import java.util.regex.Matcher

Expand Down Expand Up @@ -52,14 +52,18 @@ class GithubRepo extends GitRepo {
}

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

public String getGhBaseUrl() {
return this.ghBaseUrl
}

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

@PackageScope
Expand All @@ -73,22 +77,23 @@ class GithubRepo extends GitRepo {
}

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}")
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)
}

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) {
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
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
package de.gliderpilot.gradle.semanticrelease

import com.jcabi.github.Coordinates
import com.jcabi.github.Release
import com.jcabi.github.ReleaseAssets
import com.jcabi.github.Repo
import com.jcabi.http.Request
import com.jcabi.http.request.FakeRequest

import spock.lang.Shared
import spock.lang.Specification
import spock.lang.Subject

class GhEnterpriseReleaseAssetsSpec extends Specification {
@Shared
@Subject
GhEnterpriseReleaseAssets unit

Request mockRequest
Release mockRelease

def setup() {
def mockRepo = Mock(Repo.class)
mockRepo.coordinates() >> Mock(Coordinates.class)
mockRepo.coordinates().user() >> "test-user"
mockRepo.coordinates().repo() >> "test-repo"

mockRequest = new FakeRequest(
HttpURLConnection.HTTP_CREATED,
"fake request",
Collections.<Map.Entry<String, String>>emptyList(),
"{ \"id\": 1337 }".bytes
)
mockRelease = Mock()

mockRelease.repo() >> mockRepo
mockRelease.number() >> 1337
mockRelease.assets() >> Mock(ReleaseAssets.class)

unit = new GhEnterpriseReleaseAssets("https://enterprise.github", mockRelease, mockRequest)
}

def "should construct correct github upload api base url"() {
when:
unit = new GhEnterpriseReleaseAssets("https://enterprise.github", mockRelease, mockRequest)

then:
unit.githubUploadEndpoint.toString() == "https://enterprise.github/api/uploads"
}

def "should construct correct upload request with given data"() {
given:
def byte[] content = "This is the content"

when:
def uploadRequest = unit.getAssetUploadRequest(content, "test-type", "test-name")

then:
uploadRequest.toString().contains "test-user"
uploadRequest.toString().contains "test-repo"
uploadRequest.toString().contains "test-type"
uploadRequest.uri().toString().contains "test-name"
uploadRequest.body().get() == "This is the content"
}

def "should send an asset upload request and get the asset id"() {
when:
unit.upload("test".bytes, "test-type", "test-name")

then:
1 * mockRelease.assets().get(1337)
}

def "should pass method calls to underlying response class"() {
when:
unit.release()
unit.iterate()
unit.get(0)

then:
1 * mockRelease.assets().release()
1 * mockRelease.assets().iterate()
1 * mockRelease.assets().get(0)
}
}

0 comments on commit adfecc0

Please sign in to comment.