Skip to content

Commit

Permalink
feat(managed-delivery): Retrieve Managed Delivery manifests from GitHub
Browse files Browse the repository at this point in the history
  • Loading branch information
kzwang committed Aug 1, 2020
1 parent 8eb26f9 commit 6f7bcd6
Show file tree
Hide file tree
Showing 6 changed files with 564 additions and 340 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -71,8 +71,8 @@ class GitHubConfig {
}

@Override
void intercept(RequestInterceptor.RequestFacade request) {
request.addQueryParam("access_token", accessToken)
void intercept(RequestFacade request) {
request.addHeader("Authorization", "token " + accessToken)
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,19 +17,36 @@
package com.netflix.spinnaker.igor.scm.github.client

import com.netflix.spinnaker.igor.scm.github.client.model.CompareCommitsResponse
import com.netflix.spinnaker.igor.scm.github.client.model.GetRepositoryContentResponse
import retrofit.http.GET
import retrofit.http.Path
import retrofit.http.Query

/**
* Interface for interacting with a GitHub REST API
* https://developer.github.com/v3/repos/commits/#list-commits-on-a-repository
*/
interface GitHubClient {
@GET('/repos/{projectKey}/{repositorySlug}/compare/{fromCommit}...{toCommit}')
CompareCommitsResponse getCompareCommits(
@Path('projectKey') String projectKey,
@Path('repositorySlug') String repositorySlug,
@Path('fromCommit') String fromCommit,
@Path('toCommit') String toCommit)
@GET('/repos/{projectKey}/{repositorySlug}/compare/{fromCommit}...{toCommit}')
CompareCommitsResponse getCompareCommits(
@Path('projectKey') String projectKey,
@Path('repositorySlug') String repositorySlug,
@Path('fromCommit') String fromCommit,
@Path('toCommit') String toCommit)

@GET('/repos/{projectKey}/{repositorySlug}/contents/{path}')
GetRepositoryContentResponse getFileContent(
@Path('projectKey') String projectKey,
@Path('repositorySlug') String repositorySlug,
@Path(value = 'path', encode = false) String path,
@Query('ref') String ref
)

@GET('/repos/{projectKey}/{repositorySlug}/contents/{path}')
List<GetRepositoryContentResponse> listDirectory(
@Path('projectKey') String projectKey,
@Path('repositorySlug') String repositorySlug,
@Path(value = 'path', encode = false) String path,
@Query('ref') String ref
)
}

Original file line number Diff line number Diff line change
Expand Up @@ -16,53 +16,63 @@

package com.netflix.spinnaker.igor.scm.github.client

import com.netflix.spinnaker.igor.config.GitHubProperties

import com.netflix.spinnaker.igor.scm.AbstractScmMaster
import com.netflix.spinnaker.retrofit.Slf4jRetrofitLogger
import org.springframework.context.annotation.Bean
import retrofit.Endpoints
import retrofit.RequestInterceptor
import retrofit.RestAdapter
import retrofit.client.OkClient
import retrofit.converter.JacksonConverter
import com.netflix.spinnaker.igor.scm.github.client.model.GetRepositoryContentResponse
import com.netflix.spinnaker.kork.web.exceptions.NotFoundException
import groovy.util.logging.Slf4j
import retrofit.RetrofitError

import javax.validation.Valid
import java.util.stream.Collectors

/**
* Wrapper class for a collection of GitHub clients
*/
class GitHubMaster extends AbstractScmMaster {
GitHubClient gitHubClient
String baseUrl
@Slf4j
class GitHubMaster extends AbstractScmMaster {

@Bean
GitHubMaster gitHubMasters(@Valid GitHubProperties gitHubProperties) {
new GitHubMaster(githubClient : gitHubClient(gitHubProperties.baseUrl, gitHubProperties.accessToken), baseUrl: gitHubProperties.baseUrl)
}
private static final String FILE_CONTENT_TYPE = "file";

GitHubClient gitHubClient
String baseUrl

GitHubClient gitHubClient(String address, String username, String password) {
new RestAdapter.Builder()
.setEndpoint(Endpoints.newFixedEndpoint(address))
.setRequestInterceptor(new BasicAuthRequestInterceptor(accessToken))
.setClient(new OkClient())
.setConverter(new JacksonConverter())
.setLog(new Slf4jRetrofitLogger(GitHubClient))
.build()
.create(GitHubClient)
@Override
List<String> listDirectory(String projectKey, String repositorySlug, String path, String ref) {
try {
List<GetRepositoryContentResponse> response = gitHubClient.listDirectory(projectKey, repositorySlug, path, ref);
return response.stream()
.map({ r -> r.path })
.collect(Collectors.toList())
} catch (RetrofitError e) {
if (e.getKind() == RetrofitError.Kind.NETWORK) {
throw new NotFoundException("Could not find the server ${baseUrl}")
}
log.error(
"Failed to fetch file from {}/{}/{}, reason: {}",
projectKey, repositorySlug, path, e.message
)
throw e
}
}

static class BasicAuthRequestInterceptor implements RequestInterceptor {

private final String accessToken

BasicAuthRequestInterceptor(String accessToken) {
this.accessToken = accessToken
}

@Override
void intercept(RequestInterceptor.RequestFacade request) {
request.addQueryParam("access_token", accessToken)
}
@Override
String getTextFileContents(String projectKey, String repositorySlug, String path, String ref) {
try {
GetRepositoryContentResponse response = gitHubClient.getFileContent(projectKey, repositorySlug, path, ref);
if (FILE_CONTENT_TYPE != response.type) {
throw new NotFoundException("Unexpected content type: ${response.type}");
}
return new String(Base64.mimeDecoder.decode(response.content));
} catch (RetrofitError e) {
if (e.getKind() == RetrofitError.Kind.NETWORK) {
throw new NotFoundException("Could not find the server ${baseUrl}")
}
log.error(
"Failed to fetch file from {}/{}/{}, reason: {}",
projectKey, repositorySlug, path, e.message
)
throw e
}
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
/*
* Copyright 2015 Netflix, Inc.
*
* 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 com.netflix.spinnaker.igor.scm.github.client.model

import com.fasterxml.jackson.annotation.JsonIgnoreProperties

/**
* Response for GitHub REST API get repository content.
* https://docs.github.com/en/rest/reference/repos#get-repository-content
*/
@JsonIgnoreProperties(ignoreUnknown = true)
class GetRepositoryContentResponse extends AbstractGitHubResponse {
String path
String type
String content
}
Loading

0 comments on commit 6f7bcd6

Please sign in to comment.