Unverified Commit cfaa09ca authored by Greg Messner's avatar Greg Messner Committed by GitHub
Browse files

Add support for Environments API - #463 (#472)

No related merge requests found
Showing with 859 additions and 2 deletions
+859 -2
......@@ -780,4 +780,27 @@ public interface Constants {
return (enumHelper.toString(this));
}
}
/** Enum to use for specifying the status of a deployment. */
public enum DeploymentStatus {
CREATED, RUNNING, SUCCESS, FAILED, CANCELED;
private static JacksonJsonEnumHelper<DeploymentStatus> enumHelper = new JacksonJsonEnumHelper<>(DeploymentStatus.class);
@JsonCreator
public static DeploymentStatus forValue(String value) {
return enumHelper.forValue(value);
}
@JsonValue
public String toValue() {
return (enumHelper.toString(this));
}
@Override
public String toString() {
return (enumHelper.toString(this));
}
}
}
package org.gitlab4j.api;
import java.util.List;
import java.util.Optional;
import java.util.stream.Stream;
import javax.ws.rs.core.Response;
import org.gitlab4j.api.models.Environment;
/**
* This class provides an entry point to all the GitLab API Environments API calls.
* @see <a href="https://docs.gitlab.com/ce/api/environments.html">Environments API</a>
*/
public class EnvironmentsApi extends AbstractApi {
public EnvironmentsApi(GitLabApi gitLabApi) {
super(gitLabApi);
}
/**
* Get all environments for a given project.
*
* <pre><code>GitLab Endpoint: GET /projects/:id/environments</code></pre>
*
* @param projectIdOrPath id, path of the project, or a Project instance holding the project ID or path
* @return a List of Environment instances
* @throws GitLabApiException if any exception occurs
*/
public List<Environment> getEnvironments(Object projectIdOrPath) throws GitLabApiException {
return (getEnvironments(projectIdOrPath, getDefaultPerPage()).all());
}
/**
* Get a Stream of all environments for a given project.
*
* <pre><code>GitLab Endpoint: GET /projects/:id/environments</code></pre>
*
* @param projectIdOrPath id, path of the project, or a Project instance holding the project ID or path
* @return a Stream of Environment instances
* @throws GitLabApiException if any exception occurs
*/
public Stream<Environment> getEnvironmentsStream(Object projectIdOrPath) throws GitLabApiException {
return (getEnvironments(projectIdOrPath, getDefaultPerPage()).stream());
}
/**
* Get a Pager of all environments for a given project.
*
* <pre><code>GitLab Endpoint: GET /projects/:id/environments</code></pre>
*
* @param projectIdOrPath id, path of the project, or a Project instance holding the project ID or path
* @param itemsPerPage the number of Environment instances that will be fetched per page
* @return a Pager of Environment instances
* @throws GitLabApiException if any exception occurs
*/
public Pager<Environment> getEnvironments(Object projectIdOrPath, int itemsPerPage) throws GitLabApiException {
return (new Pager<Environment>(this, Environment.class, itemsPerPage, null,
"projects", getProjectIdOrPath(projectIdOrPath), "environments"));
}
/**
* Get a specific environment.
*
* <pre><code>GitLab Endpoint: GET /projects/:id/environments/:environment_id</code></pre>
*
* @param projectIdOrPath id, path of the project, or a Project instance holding the project ID or path
* @param environmentId the ID of the environment to get
* @return an Environment instance
* @throws GitLabApiException if any exception occurs
*/
public Environment getEnvironment(Object projectIdOrPath, Integer environmentId) throws GitLabApiException {
Response response = get(Response.Status.OK, null,
"projects", getProjectIdOrPath(projectIdOrPath), "environments", environmentId);
return (response.readEntity(Environment.class));
}
/**
* Get a specific environment. as an Optional instance.
*
* <pre><code>GitLab Endpoint: GET /projects/:id/environments/:environment_id</code></pre>
*
* @param projectIdOrPath id, path of the project, or a Project instance holding the project ID or path
* @param environmentId the ID of the environment to get
* @return the Environment as an Optional instance
*/
public Optional<Environment> getOptionalEnvironment(Object projectIdOrPath, Integer environmentId) {
try {
return (Optional.ofNullable(getEnvironment(projectIdOrPath, environmentId)));
} catch (GitLabApiException glae) {
return (GitLabApi.createOptionalFromException(glae));
}
}
/**
* Create a new environment with the given name and external_url.
*
* <pre><code>GitLab Endpoint:POST /projects/:id/environments</code></pre>
*
* @param projectIdOrPath id, path of the project, or a Project instance holding the project ID or path
* @param name the name of the environment
* @param externalUrl the place to link to for this environment
* @return the created Environment instance
* @throws GitLabApiException if any exception occurs
*/
public Environment createEnvironment(Object projectIdOrPath, String name, String externalUrl) throws GitLabApiException {
GitLabApiForm formData = new GitLabApiForm().withParam("name", name, true).withParam("external_url", externalUrl);
Response response = post(Response.Status.CREATED, formData,
"projects", getProjectIdOrPath(projectIdOrPath), "environments");
return (response.readEntity(Environment.class));
}
/**
* Update an existing environment.
*
* <pre><code>GitLab Endpoint:POST /projects/:id/environments</code></pre>
*
* @param projectIdOrPath id, path of the project, or a Project instance holding the project ID or path
* @param environmentId the ID of the environment to update
* @param name the name of the environment
* @param externalUrl the place to link to for this environment
* @return the created Environment instance
* @throws GitLabApiException if any exception occurs
*/
public Environment updateEnvironment(Object projectIdOrPath, Integer environmentId, String name, String externalUrl) throws GitLabApiException {
GitLabApiForm formData = new GitLabApiForm().withParam("name", name).withParam("external_url", externalUrl);
Response response = putWithFormData(Response.Status.OK, formData, formData,
"projects", getProjectIdOrPath(projectIdOrPath), "environments", environmentId);
return (response.readEntity(Environment.class));
}
/**
* Delete an environment.
*
* <pre><code>GitLab Endpoint: DELETE /projects/:id/environments/:environment_id</code></pre>
*
* @param projectIdOrPath id, path of the project, or a Project instance holding the project ID or path
* @param environmentId the ID of the environment to delete
* @throws GitLabApiException if any exception occurs
*/
public void deleteEnvironment(Object projectIdOrPath, Integer environmentId) throws GitLabApiException {
delete(Response.Status.OK, null,
"projects", getProjectIdOrPath(projectIdOrPath), "environments", environmentId);
}
/**
* Stop an environment.
*
* <pre><code>GitLab Endpoint:POST /projects/:id/environments/:environment_id/stop</code></pre>
*
* @param projectIdOrPath id, path of the project, or a Project instance holding the project ID or path
* @param environmentId the ID of the environment to stop
* @return the Environment instance of the stopped environment
* @throws GitLabApiException if any exception occurs
*/
public Environment createEnvironment(Object projectIdOrPath, Integer environmentId) throws GitLabApiException {
GitLabApiForm formData = new GitLabApiForm();
Response response = post(Response.Status.CREATED, formData,
"projects", getProjectIdOrPath(projectIdOrPath), "environments", environmentId, "stop");
return (response.readEntity(Environment.class));
}
}
\ No newline at end of file
......@@ -59,6 +59,7 @@ public class GitLabApi {
private ContainerRegistryApi containerRegistryApi;
private DiscussionsApi discussionsApi;
private DeployKeysApi deployKeysApi;
private EnvironmentsApi environmentsApi;
private EpicsApi epicsApi;
private EventsApi eventsApi;
private GroupApi groupApi;
......@@ -1054,6 +1055,25 @@ public class GitLabApi {
return (discussionsApi);
}
/**
* Gets the EnvironmentsApi instance owned by this GitLabApi instance. The EnvironmentsApi is used
* to perform all environment related API calls.
*
* @return the EnvironmentsApi instance owned by this GitLabApi instance
*/
public EnvironmentsApi getEnvironmentsApi() {
if (environmentsApi == null) {
synchronized (this) {
if (environmentsApi == null) {
environmentsApi = new EnvironmentsApi(this);
}
}
}
return (environmentsApi);
}
/**
* Gets the EpicsApi instance owned by this GitLabApi instance. The EpicsApi is used
* to perform all Epics and Epic Issues related API calls.
......
......@@ -11,7 +11,7 @@ public class Artifact {
public enum FileType {
ARCHIVE, METADATA, TRACE, JUNIT;
private static JacksonJsonEnumHelper<FileType> enumHelper = new JacksonJsonEnumHelper<>(FileType.class, true);
private static JacksonJsonEnumHelper<FileType> enumHelper = new JacksonJsonEnumHelper<>(FileType.class);
@JsonCreator
public static FileType forValue(String value) {
......
package org.gitlab4j.api.models;
import java.util.Date;
import java.util.List;
import org.gitlab4j.api.Constants.DeploymentStatus;
import org.gitlab4j.api.utils.JacksonJson;
public class Deployable {
private Integer id;
private DeploymentStatus status;
private String stage;
private String name;
private String ref;
private Boolean tag;
private Float coverage;
private Date createdAt;
private Date startedAt;
private Date finishedAt;
private Double duration;
private User user;
private Commit commit;
private Pipeline pipeline;
private String webUrl;
private List<Artifact> artifacts;
private Runner runner;
private Date artifactsExpireAt;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public DeploymentStatus getStatus() {
return status;
}
public void setStatus(DeploymentStatus status) {
this.status = status;
}
public String getStage() {
return stage;
}
public void setStage(String stage) {
this.stage = stage;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getRef() {
return ref;
}
public void setRef(String ref) {
this.ref = ref;
}
public Boolean getTag() {
return tag;
}
public void setTag(Boolean tag) {
this.tag = tag;
}
public Float getCoverage() {
return coverage;
}
public void setCoverage(Float coverage) {
this.coverage = coverage;
}
public Date getCreatedAt() {
return createdAt;
}
public void setCreatedAt(Date createdAt) {
this.createdAt = createdAt;
}
public Date getStartedAt() {
return startedAt;
}
public void setStartedAt(Date startedAt) {
this.startedAt = startedAt;
}
public Date getFinishedAt() {
return finishedAt;
}
public void setFinishedAt(Date finishedAt) {
this.finishedAt = finishedAt;
}
public Double getDuration() {
return duration;
}
public void setDuration(Double duration) {
this.duration = duration;
}
public User getUser() {
return user;
}
public void setUser(User user) {
this.user = user;
}
public Commit getCommit() {
return commit;
}
public void setCommit(Commit commit) {
this.commit = commit;
}
public Pipeline getPipeline() {
return pipeline;
}
public void setPipeline(Pipeline pipeline) {
this.pipeline = pipeline;
}
public String getWebUrl() {
return webUrl;
}
public void setWebUrl(String webUrl) {
this.webUrl = webUrl;
}
public List<Artifact> getArtifacts() {
return artifacts;
}
public void setArtifacts(List<Artifact> artifacts) {
this.artifacts = artifacts;
}
public Runner getRunner() {
return runner;
}
public void setRunner(Runner runner) {
this.runner = runner;
}
public Date getArtifactsExpireAt() {
return artifactsExpireAt;
}
public void setArtifactsExpireAt(Date artifactsExpireAt) {
this.artifactsExpireAt = artifactsExpireAt;
}
@Override
public String toString() {
return (JacksonJson.toJsonString(this));
}
}
package org.gitlab4j.api.models;
import java.util.Date;
import org.gitlab4j.api.Constants.DeploymentStatus;
import org.gitlab4j.api.utils.JacksonJson;
public class Deployment {
private Integer id;
private Integer iid;
private String ref;
private String sha;
private Date createdAt;
private Date updatedAt;
private DeploymentStatus status;
private User user;
private Environment environment;
private Deployable deployable;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public Integer getIid() {
return iid;
}
public void setIid(Integer iid) {
this.iid = iid;
}
public String getRef() {
return ref;
}
public void setRef(String ref) {
this.ref = ref;
}
public String getSha() {
return sha;
}
public void setSha(String sha) {
this.sha = sha;
}
public Date getCreatedAt() {
return createdAt;
}
public void setCreatedAt(Date createdAt) {
this.createdAt = createdAt;
}
public Date getUpdatedAt() {
return updatedAt;
}
public void setUpdatedAt(Date updatedAt) {
this.updatedAt = updatedAt;
}
public DeploymentStatus getStatus() {
return status;
}
public void setStatus(DeploymentStatus status) {
this.status = status;
}
public User getUser() {
return user;
}
public void setUser(User user) {
this.user = user;
}
public Environment getEnvironment() {
return environment;
}
public void setEnvironment(Environment environment) {
this.environment = environment;
}
public Deployable getDeployable() {
return deployable;
}
public void setDeployable(Deployable deployable) {
this.deployable = deployable;
}
@Override
public String toString() {
return (JacksonJson.toJsonString(this));
}
}
package org.gitlab4j.api.models;
import org.gitlab4j.api.utils.JacksonJson;
import org.gitlab4j.api.utils.JacksonJsonEnumHelper;
import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonValue;
public class Environment {
public enum EnvironmentState {
AVAILABLE, STOPPED;
private static JacksonJsonEnumHelper<EnvironmentState> enumHelper = new JacksonJsonEnumHelper<>(EnvironmentState.class);
@JsonCreator
public static EnvironmentState forValue(String value) {
return enumHelper.forValue(value);
}
@JsonValue
public String toValue() {
return (enumHelper.toString(this));
}
@Override
public String toString() {
return (enumHelper.toString(this));
}
}
private Integer id;
private String name;
private String slug;
private String externalUrl;
private EnvironmentState state;
private Deployment lastDeployment;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getSlug() {
return slug;
}
public void setSlug(String slug) {
this.slug = slug;
}
public String getExternalUrl() {
return externalUrl;
}
public void setExternalUrl(String externalUrl) {
this.externalUrl = externalUrl;
}
public EnvironmentState getState() {
return state;
}
public void setState(EnvironmentState state) {
this.state = state;
}
public Deployment getLastDeployment() {
return lastDeployment;
}
public void setLastDeployment(Deployment lastDeployment) {
this.lastDeployment = lastDeployment;
}
@Override
public String toString() {
return (JacksonJson.toJsonString(this));
}
}
package org.gitlab4j.api;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import static org.junit.Assume.assumeNotNull;
import java.util.List;
import java.util.Optional;
import java.util.Random;
import java.util.stream.Stream;
import org.gitlab4j.api.models.Environment;
import org.gitlab4j.api.models.Project;
import org.junit.AfterClass;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
import org.junit.experimental.categories.Category;
/**
* In order for these tests to run you must set the following properties in
* ~/test-gitlab4j.properties
* <p>
* TEST_HOST_URL
* TEST_PRIVATE_TOKEN
* <p>
* If any of the above are NULL, all tests in this class will be skipped.
*/
@Category(IntegrationTest.class)
public class TestEnvironmentsApi extends AbstractIntegrationTest {
private static GitLabApi gitLabApi;
private static Project testProject;
private static final String ENVIRONMENT_NAME = "gitlab4j-testing";
private static final String EXTERNAL_URL = "https:/testing.example.com/";
private static Random randomNumberGenerator = new Random();
public TestEnvironmentsApi() {
super();
}
@BeforeClass
public static void setup() {
// Must setup the connection to the GitLab test server and get the test Project
// instance
gitLabApi = baseTestSetup();
testProject = getTestProject();
deleteAllTestAssets();
}
@AfterClass
public static void teardown() throws GitLabApiException {
deleteAllTestAssets();
}
private static void deleteAllTestAssets() {
if (gitLabApi != null) {
try {
List<Environment> envs = gitLabApi.getEnvironmentsApi().getEnvironments(testProject);
if (envs != null) {
for (Environment env : envs) {
if (env.getName().startsWith(ENVIRONMENT_NAME)) {
gitLabApi.getEnvironmentsApi().deleteEnvironment(testProject, env.getId());
}
}
}
} catch (GitLabApiException ignore) {
}
}
}
@Before
public void beforeMethod() {
assumeNotNull(gitLabApi);
}
private static String getUniqueName() {
return (ENVIRONMENT_NAME + " - " + (randomNumberGenerator.nextInt() + 1));
}
@Test
public void testGetEnvironments() throws GitLabApiException {
final Environment env = gitLabApi.getEnvironmentsApi().createEnvironment(
testProject, getUniqueName(), EXTERNAL_URL);
try {
List<Environment> envs = gitLabApi.getEnvironmentsApi().getEnvironments(testProject);
assertTrue(envs.size() > 0);
Environment foundEnv = envs.stream().filter(
e -> e.getName().equals(env.getName())).findFirst().orElse(null);
assertNotNull(foundEnv);
assertEquals(env.getName(), foundEnv.getName());
} catch (Exception e) {
gitLabApi.getEnvironmentsApi().deleteEnvironment(testProject, env.getId());
}
}
@Test
public void testDeleteEnvironment() throws GitLabApiException {
final Environment env = gitLabApi.getEnvironmentsApi().createEnvironment(
testProject, getUniqueName(), EXTERNAL_URL);
gitLabApi.getEnvironmentsApi().deleteEnvironment(testProject, env.getId());
Stream<Environment> envs = gitLabApi.getEnvironmentsApi().getEnvironmentsStream(testProject);
Environment foundEnv = envs.filter(e -> e.getName().equals(env.getName())).findFirst().orElse(null);
assertNull(foundEnv);
}
@Test
public void testOptionalEnvironment() throws GitLabApiException {
final Environment env = gitLabApi.getEnvironmentsApi().createEnvironment(
testProject, getUniqueName(), EXTERNAL_URL);
Optional<Environment> optionalEnv =
gitLabApi.getEnvironmentsApi().getOptionalEnvironment(testProject, env.getId());
assertTrue(optionalEnv.isPresent());
assertEquals(env.getName(), optionalEnv.get().getName());
gitLabApi.getEnvironmentsApi().deleteEnvironment(testProject, env.getId());
}
}
......@@ -48,9 +48,11 @@ import org.gitlab4j.api.models.CommitStatus;
import org.gitlab4j.api.models.CompareResults;
import org.gitlab4j.api.models.Contributor;
import org.gitlab4j.api.models.DeployKey;
import org.gitlab4j.api.models.Deployment;
import org.gitlab4j.api.models.Diff;
import org.gitlab4j.api.models.Discussion;
import org.gitlab4j.api.models.Email;
import org.gitlab4j.api.models.Environment;
import org.gitlab4j.api.models.Epic;
import org.gitlab4j.api.models.EpicIssue;
import org.gitlab4j.api.models.Event;
......@@ -188,12 +190,24 @@ public class TestGitLabApiBeans {
assertTrue(compareJson(comment, "comment.json"));
}
@Test
public void testDeployment() throws Exception {
Deployment deployment = unmarshalResource(Deployment.class, "deployment.json");
assertTrue(compareJson(deployment, "deployment.json"));
}
@Test
public void testEmails() throws Exception {
List<Email> emails = unmarshalResourceList(Email.class, "emails.json");
assertTrue(compareJson(emails, "emails.json"));
}
@Test
public void testEnvironment() throws Exception {
Environment environment = unmarshalResource(Environment.class, "environment.json");
assertTrue(compareJson(environment, "environment.json"));
}
@Test
public void testEpic() throws Exception {
Epic epic = unmarshalResource(Epic.class, "epic.json");
......
{
"id": 42,
"iid": 2,
"ref": "master",
"sha": "a91957a858320c0e17f3a0eca7cfacbff50ea29a",
"created_at": "2016-08-11T11:32:35.444Z",
"updated_at": "2016-08-11T11:34:01.123Z",
"user": {
"name": "Administrator",
"username": "root",
"id": 1,
"state": "active",
"avatar_url": "http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon",
"web_url": "http://localhost:3000/root"
},
"environment": {
"id": 9,
"name": "production",
"external_url": "https://about.gitlab.com"
},
"deployable": {
"id": 664,
"status": "success",
"stage": "deploy",
"name": "deploy",
"ref": "master",
"tag": false,
"created_at": "2016-08-11T11:32:24.456Z",
"finished_at": "2016-08-11T11:32:35.145Z",
"user": {
"id": 1,
"name": "Administrator",
"username": "root",
"state": "active",
"avatar_url": "http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon",
"web_url": "http://gitlab.dev/root",
"created_at": "2015-12-21T13:14:24.077Z",
"skype": "",
"linkedin": "",
"twitter": "",
"website_url": "",
"organization": ""
},
"commit": {
"id": "a91957a858320c0e17f3a0eca7cfacbff50ea29a",
"short_id": "a91957a8",
"title": "Merge branch 'rename-readme' into 'master'\r",
"author_name": "Administrator",
"author_email": "admin@example.com",
"created_at": "2016-08-11T13:28:26Z",
"message": "Merge branch 'rename-readme' into 'master'\r\n\r\nRename README\r\n\r\n\r\n\r\nSee merge request !2"
}
}
}
\ No newline at end of file
{
"id": 1,
"name": "review/fix-foo",
"slug": "review-fix-foo-dfjre3",
"external_url": "https://review-fix-foo-dfjre3.example.gitlab.com",
"state": "available",
"last_deployment": {
"id": 100,
"iid": 34,
"ref": "fdroid",
"sha": "416d8ea11849050d3d1f5104cf8cf51053e790ab",
"created_at": "2019-03-25T18:55:13.252Z",
"status": "success",
"user": {
"id": 1,
"name": "Administrator",
"state": "active",
"username": "root",
"avatar_url": "http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon",
"web_url": "http://localhost:3000/root"
},
"deployable": {
"id": 710,
"status": "success",
"stage": "deploy",
"name": "staging",
"ref": "fdroid",
"tag": false,
"coverage": 87.65,
"created_at": "2019-03-25T18:55:13.215Z",
"started_at": "2019-03-25T12:54:50.082Z",
"finished_at": "2019-03-25T18:55:13.216Z",
"duration": 21623.13423,
"user": {
"id": 1,
"name": "Administrator",
"username": "root",
"state": "active",
"avatar_url": "http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon",
"web_url": "http://gitlab.dev/root",
"created_at": "2015-12-21T13:14:24.077Z",
"public_email": "",
"skype": "",
"linkedin": "",
"twitter": "",
"website_url": ""
},
"commit": {
"id": "416d8ea11849050d3d1f5104cf8cf51053e790ab",
"short_id": "416d8ea1",
"created_at": "2016-01-02T15:39:18Z",
"parent_ids": [
"e9a4449c95c64358840902508fc827f1a2eab7df"
],
"title": "Removed fabric to fix #40",
"message": "Removed fabric to fix #40\n",
"author_name": "Administrator",
"author_email": "admin@example.com",
"authored_date": "2016-01-02T15:39:18Z",
"committer_name": "Administrator",
"committer_email": "admin@example.com",
"committed_date": "2016-01-02T15:39:18Z"
},
"pipeline": {
"id": 34,
"sha": "416d8ea11849050d3d1f5104cf8cf51053e790ab",
"ref": "fdroid",
"status": "success",
"web_url": "http://localhost:3000/Commit451/lab-coat/pipelines/34"
},
"web_url": "http://localhost:3000/Commit451/lab-coat/-/jobs/710",
"artifacts": [
{
"file_type": "trace",
"size": 1305,
"filename": "job.log"
}
]
}
}
}
\ No newline at end of file
......@@ -30,7 +30,6 @@
"status": "pending"
},
"ref": "master",
"artifacts": [],
"stage": "test",
"started_at": "2015-12-24T17:54:27.722Z",
"status": "failed",
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment