Skip to content

Commit ce40d67

Browse files
committed
add initial custom action implementation
1 parent 5fb2216 commit ce40d67

31 files changed

+980
-55
lines changed

README.md

Lines changed: 49 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,50 @@
11
# backlog-github-integration-action
2-
github integration action for Nulab's backlog
2+
3+
This action helps integrate with [Nulab's backlog](https://nulab.com/products/backlog/) via GitHub events.
4+
5+
Here are the features.
6+
7+
* updates a Pull Request link into related issues when it has opened.
8+
9+
## Precondition to run
10+
11+
Set environment variables.
12+
13+
```bash
14+
export APP_LOCALE="en_US"
15+
export APP_LOG_LEVEL="debug"
16+
export BACKLOG_FQDN="YOUR-SPACE.backlog.com"
17+
export BACKLOG_API_KEY="..."
18+
export BACKLOG_PROJECT_KEY="TEST"
19+
export GITHUB_TOKEN="..."
20+
```
21+
22+
## How to run
23+
24+
```bash
25+
$ ./gradlew run --args="pull_request --repository kazamori/backlog-github-integration-action --pr-number 1"
26+
```
27+
28+
## for debugging
29+
30+
### GitHub Client
31+
32+
```bash
33+
$ ./gradlew githubClient --args='--repository kazamori/backlog-github-integration-action --pr-number 1'
34+
```
35+
36+
### Backlog Client
37+
38+
```bash
39+
$ ./gradlew backlogClient --args="--issue-id PROJECT-1"
40+
```
41+
42+
```bash
43+
$ ./gradlew backlogClient --args='--issue-id PROJECT-3 --custom-field "MyTextField" --issue-comment "* comment from REST API"'
44+
```
45+
46+
## How to test
47+
48+
```bash
49+
$ ./gradlew test --info
50+
```

app/build.gradle

Lines changed: 43 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,38 +1,65 @@
1-
/*
2-
* This file was generated by the Gradle 'init' task.
3-
*
4-
* This generated file contains a sample Java application project to get you started.
5-
* For more details take a look at the 'Building Java & JVM projects' chapter in the Gradle
6-
* User Manual available at https://docs.gradle.org/7.4/userguide/building_java_projects.html
7-
* This project uses @Incubating APIs which are subject to change.
8-
*/
9-
101
plugins {
11-
// Apply the application plugin to add support for building a CLI application in Java.
122
id 'application'
133
}
144

155
repositories {
16-
// Use Maven Central for resolving dependencies.
176
mavenCentral()
187
}
198

209
dependencies {
21-
// This dependency is used by the application.
10+
// app
11+
implementation 'com.nulab-inc:backlog4j:2.4.4'
12+
implementation 'com.typesafe:config:1.4.2'
13+
implementation 'info.picocli:picocli:4.6.3'
14+
implementation 'org.kohsuke:github-api:1.303'
15+
16+
// logging
17+
implementation 'org.slf4j:slf4j-api:1.7.36'
18+
implementation 'org.slf4j:slf4j-simple:1.7.36'
19+
20+
// build
2221
implementation 'com.google.guava:guava:30.1.1-jre'
22+
compileOnly 'org.projectlombok:lombok:1.18.22'
23+
annotationProcessor 'org.projectlombok:lombok:1.18.22'
24+
25+
// testing
26+
testCompileOnly 'org.projectlombok:lombok:1.18.22'
27+
testAnnotationProcessor 'org.projectlombok:lombok:1.18.22'
28+
// mock
29+
testImplementation 'org.mockito:mockito-core:4.4.0'
30+
testImplementation 'org.mockito:mockito-junit-jupiter:4.4.0'
2331
}
2432

2533
testing {
2634
suites {
27-
// Configure the built-in test suite
2835
test {
29-
// Use JUnit Jupiter test framework
3036
useJUnitJupiter('5.8.1')
3137
}
3238
}
3339
}
3440

3541
application {
36-
// Define the main class for the application.
37-
mainClass = 'jp.kazamori.github.actions.backlog.App'
42+
mainClass = 'jp.kazamori.github.actions.backlog.Main'
43+
}
44+
45+
task githubClient(type: JavaExec) {
46+
mainClass = 'jp.kazamori.github.actions.backlog.cli.GitHubClientCli'
47+
classpath = sourceSets.main.runtimeClasspath
48+
}
49+
50+
task backlogClient(type: JavaExec) {
51+
mainClass = 'jp.kazamori.github.actions.backlog.cli.BacklogClientCli'
52+
classpath = sourceSets.main.runtimeClasspath
53+
}
54+
55+
task config(type: JavaExec) {
56+
mainClass = 'jp.kazamori.github.actions.backlog.cli.ConfigCli'
57+
classpath = sourceSets.main.runtimeClasspath
58+
}
59+
60+
tasks.withType(JavaExec) {
61+
jvmArgs += '--add-opens'
62+
jvmArgs += 'java.base/sun.net.www.protocol.https=ALL-UNNAMED'
63+
jvmArgs += '--add-opens'
64+
jvmArgs += 'java.base/java.net=ALL-UNNAMED'
3865
}

app/src/main/java/jp/kazamori/github/actions/backlog/App.java

Lines changed: 0 additions & 14 deletions
This file was deleted.
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
/*
2+
* This Java source file was generated by the Gradle 'init' task.
3+
*/
4+
package jp.kazamori.github.actions.backlog;
5+
6+
import com.typesafe.config.ConfigFactory;
7+
import jp.kazamori.github.actions.backlog.client.BacklogClientUtil;
8+
import jp.kazamori.github.actions.backlog.client.GitHubClient;
9+
import jp.kazamori.github.actions.backlog.command.PullRequest;
10+
import jp.kazamori.github.actions.backlog.config.ConfigUtil;
11+
import lombok.val;
12+
import picocli.CommandLine;
13+
import picocli.CommandLine.Command;
14+
import picocli.CommandLine.HelpCommand;
15+
16+
@Command(name = "Backlog GitHub integration action",
17+
subcommands = {HelpCommand.class},
18+
description = "provides functionalities to integrate with Backlog")
19+
public class Main {
20+
21+
public static void main(String[] args) {
22+
val config = ConfigFactory.load();
23+
ConfigUtil.setLogLevel(config);
24+
val backlogClient = BacklogClientUtil.createClient(config);
25+
val githubClient = GitHubClient.create(config);
26+
val exitCode = new CommandLine(new Main())
27+
.addSubcommand(new PullRequest(backlogClient, githubClient))
28+
.execute(args);
29+
System.exit(exitCode);
30+
}
31+
}
Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
package jp.kazamori.github.actions.backlog.cli;
2+
3+
import com.nulabinc.backlog4j.api.option.AddIssueCommentParams;
4+
import com.nulabinc.backlog4j.api.option.UpdateIssueParams;
5+
import com.typesafe.config.Config;
6+
import com.typesafe.config.ConfigFactory;
7+
import jp.kazamori.github.actions.backlog.client.BacklogClientUtil;
8+
import jp.kazamori.github.actions.backlog.config.AppConst;
9+
import jp.kazamori.github.actions.backlog.config.ConfigUtil;
10+
import lombok.val;
11+
import org.slf4j.Logger;
12+
import org.slf4j.LoggerFactory;
13+
import picocli.CommandLine;
14+
15+
import java.util.Optional;
16+
17+
@CommandLine.Command(name = "Backlog client debug cli",
18+
description = "run backlog client for debugging")
19+
public class BacklogClientCli implements Runnable {
20+
private final Logger logger = LoggerFactory.getLogger(BacklogClientCli.class);
21+
private final Config config;
22+
23+
public BacklogClientCli(Config config) {
24+
this.config = config;
25+
}
26+
27+
@CommandLine.Option(names = "--issue-id",
28+
required = true,
29+
description = "set issue id associates with the pull request")
30+
private String issueId;
31+
32+
@CommandLine.Option(names = "--issue-comment",
33+
description = "set issue comment")
34+
private Optional<String> issueComment;
35+
36+
@CommandLine.Option(names = "--issue-description",
37+
description = "set issue description")
38+
private Optional<String> issueDescription;
39+
40+
@CommandLine.Option(names = "--custom-field",
41+
description = "set custom field name")
42+
private Optional<String> customField;
43+
44+
@Override
45+
public void run() {
46+
val client = BacklogClientUtil.createClient(this.config);
47+
val util = new BacklogClientUtil(this.config, client);
48+
val issue = client.getIssue(this.issueId);
49+
logger.info(" * summary: {}", issue.getSummary());
50+
51+
if (issueComment.isPresent()) {
52+
val params = new AddIssueCommentParams(this.issueId, this.issueComment.get());
53+
val comment = client.addIssueComment(params);
54+
logger.info(" * comment id: {}", comment.getId());
55+
}
56+
57+
if (issueDescription.isPresent()) {
58+
val desc = issue.getDescription();
59+
val params = new UpdateIssueParams(this.issueId)
60+
.description(desc + "\n" + this.issueDescription.get());
61+
val updated = client.updateIssue(params);
62+
logger.info("Updated issue description:\n{}", updated.getDescription());
63+
}
64+
65+
if (customField.isPresent()) {
66+
val customFieldName = this.customField.get();
67+
util.updateCustomFieldOfIssue(issue, customFieldName, this.issueComment.get());
68+
}
69+
}
70+
71+
public static void main(String[] args) {
72+
val config = ConfigFactory.load(AppConst.LOCAL_DEV_CONF);
73+
ConfigUtil.setLogLevel(config);
74+
val exitCode = new CommandLine(new BacklogClientCli(config)).execute(args);
75+
System.exit(exitCode);
76+
}
77+
}
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
package jp.kazamori.github.actions.backlog.cli;
2+
3+
import com.typesafe.config.Config;
4+
import com.typesafe.config.ConfigFactory;
5+
import jp.kazamori.github.actions.backlog.config.*;
6+
import lombok.val;
7+
import org.slf4j.Logger;
8+
import org.slf4j.LoggerFactory;
9+
import picocli.CommandLine;
10+
11+
@CommandLine.Command(name = "Loading config file debug cli",
12+
description = "load config file for debugging")
13+
public class ConfigCli implements Runnable {
14+
private final Logger logger = LoggerFactory.getLogger(ConfigCli.class);
15+
private final Config config;
16+
17+
public ConfigCli(Config config) {
18+
this.config = config;
19+
}
20+
21+
@Override
22+
public void run() {
23+
// app
24+
logger.info(" * app.locale: {}", this.config.getString(AppConfigKey.LOCALE.get()));
25+
logger.info(" * app.logLevel: {}", this.config.getString(AppConfigKey.LOG_LEVEL.get()));
26+
// backlog
27+
logger.info(" * backlog.apiKey: {}", this.config.getString(BacklogConfigKey.API_KEY.get()));
28+
logger.info(" * backlog.fqdn: {}", this.config.getString(BacklogConfigKey.FQDN.get()));
29+
logger.info(" * backlog.projectKey: {}", this.config.getString(BacklogConfigKey.PROJECT_KEY.get()));
30+
// github
31+
logger.info(" * github.token: {}", this.config.getString(GitHubConfigKey.TOKEN.get()));
32+
logger.info("");
33+
34+
// util
35+
logger.trace(" * trace message");
36+
logger.debug(" * debug message");
37+
logger.info(" * info message");
38+
logger.warn(" * warn message");
39+
logger.error(" * error message");
40+
val locale = ConfigUtil.getLocale(this.config);
41+
logger.info(" * locale: {}", locale);
42+
}
43+
44+
public static void main(String[] args) {
45+
val config = ConfigFactory.load(AppConst.LOCAL_DEV_CONF);
46+
ConfigUtil.setLogLevel(config);
47+
val exitCode = new CommandLine(new ConfigCli(config)).execute(args);
48+
System.exit(exitCode);
49+
}
50+
}
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
package jp.kazamori.github.actions.backlog.cli;
2+
3+
import com.typesafe.config.Config;
4+
import com.typesafe.config.ConfigFactory;
5+
import jp.kazamori.github.actions.backlog.client.GitHubClient;
6+
import jp.kazamori.github.actions.backlog.config.AppConst;
7+
import jp.kazamori.github.actions.backlog.config.ConfigUtil;
8+
import lombok.val;
9+
import org.slf4j.Logger;
10+
import org.slf4j.LoggerFactory;
11+
import picocli.CommandLine;
12+
13+
@CommandLine.Command(name = "Github client debug cli",
14+
description = "run github client for debugging")
15+
public class GitHubClientCli implements Runnable {
16+
private final Logger logger = LoggerFactory.getLogger(GitHubClientCli.class);
17+
private final Config config;
18+
19+
public GitHubClientCli(Config config) {
20+
this.config = config;
21+
}
22+
23+
@CommandLine.Option(names = "--repository",
24+
required = true,
25+
description = "set repository (owner/repo) that the pull request was created")
26+
private String repository;
27+
28+
@CommandLine.Option(names = "--pr-number",
29+
required = true,
30+
description = "set number of the pull request was created")
31+
private int prNumber;
32+
33+
@Override
34+
public void run() {
35+
val locale = ConfigUtil.getLocale(this.config);
36+
val client = GitHubClient.create(this.config);
37+
val info = client.getIssueIds(this.repository, this.prNumber);
38+
logger.info(" * link: {}", info.makeLink());
39+
logger.info(" * comment: {}", info.makeComment(locale));
40+
}
41+
42+
public static void main(String[] args) {
43+
val config = ConfigFactory.load(AppConst.LOCAL_DEV_CONF);
44+
ConfigUtil.setLogLevel(config);
45+
val exitCode = new CommandLine(new GitHubClientCli(config)).execute(args);
46+
System.exit(exitCode);
47+
}
48+
}

0 commit comments

Comments
 (0)