diff --git a/.github/workflows/maven.yaml b/.github/workflows/maven.yaml
index fb14674..3a326c5 100644
--- a/.github/workflows/maven.yaml
+++ b/.github/workflows/maven.yaml
@@ -20,4 +20,4 @@ jobs:
distribution: 'temurin'
cache: maven
- name: Build with Maven
- run: mvn clean install -Pqulice --batch-mode --update-snapshots
+ run: mvn clean install --batch-mode --update-snapshots
diff --git a/pom.xml b/pom.xml
index 05db501..0c67179 100644
--- a/pom.xml
+++ b/pom.xml
@@ -23,10 +23,20 @@
21
+
+ com.jcabi
+ jcabi-http
+ 2.0.0
+
+
+ org.glassfish
+ jakarta.json
+ 1.1.6
+
com.github.ArtemGet
entrys
- 0.3.0
+ 0.4.0
com.github.ArtemGet
diff --git a/src/main/java/io/github/artemget/tagrelease/Entrypoint.java b/src/main/java/io/github/artemget/tagrelease/Entrypoint.java
index b3ac843..955f510 100644
--- a/src/main/java/io/github/artemget/tagrelease/Entrypoint.java
+++ b/src/main/java/io/github/artemget/tagrelease/Entrypoint.java
@@ -24,28 +24,33 @@
package io.github.artemget.tagrelease;
+import io.github.artemget.entrys.Entry;
import io.github.artemget.entrys.EntryException;
-import io.github.artemget.entrys.system.EEnv;
+import io.github.artemget.entrys.file.EVal;
+import io.github.artemget.entrys.operation.ESplit;
import io.github.artemget.tagrelease.bot.Bot;
import io.github.artemget.tagrelease.bot.BotReg;
-import io.github.artemget.tagrelease.command.CmdListStand;
+import io.github.artemget.tagrelease.command.CmdBuildTags;
+import io.github.artemget.tagrelease.command.CmdEcho;
+import io.github.artemget.tagrelease.command.CmdEchoReply;
+import io.github.artemget.tagrelease.command.CmdListServices;
+import io.github.artemget.tagrelease.command.CmdListServicesAll;
import io.github.artemget.tagrelease.command.CmdListStands;
-import io.github.artemget.tagrelease.domain.StandsGitlab;
-import io.github.artemget.tagrelease.entry.ESplit;
+import io.github.artemget.tagrelease.domain.Services;
+import io.github.artemget.tagrelease.domain.ServicesAll;
+import io.github.artemget.tagrelease.domain.Stands;
+import io.github.artemget.tagrelease.domain.StandsGl;
import io.github.artemget.tagrelease.match.MatchAdmin;
-import io.github.artemget.tagrelease.match.MatchChats;
-import io.github.artemget.teleroute.match.MatchAll;
+import io.github.artemget.tagrelease.match.MatchReply;
import io.github.artemget.teleroute.match.MatchRegex;
import io.github.artemget.teleroute.route.RouteDfs;
-import io.github.artemget.teleroute.route.RouteEnd;
import io.github.artemget.teleroute.route.RouteFork;
import org.telegram.telegrambots.meta.exceptions.TelegramApiException;
/**
* Entrypoint. Application starts here.
- *
- * @since 0.1.0
* @checkstyle HideUtilityClassConstructorCheck (20 lines)
+ * @since 0.1.0
*/
@SuppressWarnings(
{
@@ -57,32 +62,55 @@
)
public class Entrypoint {
public static void main(final String[] args) throws EntryException, TelegramApiException {
+ final Entry host = new EVal("provider.host");
+ final Entry release = new EVal("provider.release");
+ final Entry token = new EVal("provider.token");
+ final Entry project = new EVal("provider.project");
+ final Services all = new ServicesAll(host, project, token);
+ final Stands stands = new StandsGl(host, release, token);
new BotReg(
new Bot(
- new EEnv("BOT_NAME"),
- new EEnv("BOT_TOKEN"),
+ new EVal("bot.name"),
+ new EVal("bot.token"),
new RouteFork<>(
- new MatchAll<>(
- new MatchChats(new ESplit(new EEnv("BOT_CHATS"))),
- new MatchAdmin(new ESplit(new EEnv("BOT_ADMINS")))
- ),
+ new MatchAdmin(new ESplit(new EVal("bot.admins"))),
new RouteDfs<>(
new RouteFork<>(
- new MatchRegex<>("Покажи сервисы"),
- new CmdListStands(new StandsGitlab())
+ new MatchRegex<>("[Э]эхо"),
+ new RouteFork<>(
+ new MatchReply(),
+ new CmdEchoReply(),
+ new CmdEcho()
+ )
),
new RouteFork<>(
- new MatchRegex<>("Покажи сервис"),
- new CmdListStand(new StandsGitlab())
+ new MatchRegex<>("[Пп]окажи сервисы"),
+ new CmdListServicesAll(all)
),
new RouteFork<>(
- new MatchRegex<>("Собери тэги по стенду"),
- new RouteEnd<>(),
- new RouteFork<>(
- new MatchRegex<>("Собери тэг"),
- new RouteEnd<>()
- )
+ new MatchRegex<>("[Пп]окажи сервисы \\{([^{}]*)\\}$"),
+ new CmdListServices(stands)
+ ),
+ new RouteFork<>(
+ new MatchRegex<>("[Пп]окажи стенды"),
+ new CmdListStands(stands)
+ ),
+ new RouteFork<>(
+ new MatchRegex<>("[Сс]обери сервисы \\{([^{}]*)\\}\\s+префикс\\s+\\{([^{}]*)\\}$"),
+ new CmdBuildTags(host, project, token)
)
+// new RouteFork<>(
+// new MatchRegex<>("Покажи стенд"),
+// new CmdListStand(new StandsGitlab())
+// ),
+// new RouteFork<>(
+// new MatchRegex<>("Собери тэги по стенду"),
+// new RouteEnd<>(),
+// new RouteFork<>(
+// new MatchRegex<>("Собери тэг"),
+// new RouteEnd<>()
+// )
+// )
)
)
)
diff --git a/src/main/java/io/github/artemget/tagrelease/command/CmdBuildTags.java b/src/main/java/io/github/artemget/tagrelease/command/CmdBuildTags.java
new file mode 100644
index 0000000..f8d566a
--- /dev/null
+++ b/src/main/java/io/github/artemget/tagrelease/command/CmdBuildTags.java
@@ -0,0 +1,127 @@
+/*
+ * MIT License
+ *
+ * Copyright (c) 2024-2025. Artem Getmanskii
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+package io.github.artemget.tagrelease.command;
+
+import io.github.artemget.entrys.Entry;
+import io.github.artemget.entrys.EntryException;
+import io.github.artemget.entrys.operation.ESplit;
+import io.github.artemget.entrys.operation.EUnwrap;
+import io.github.artemget.tagrelease.domain.Service;
+import io.github.artemget.tagrelease.domain.Services;
+import io.github.artemget.tagrelease.domain.ServicesAll;
+import io.github.artemget.tagrelease.domain.Tag;
+import io.github.artemget.tagrelease.domain.Tags;
+import io.github.artemget.tagrelease.domain.TagsGl;
+import io.github.artemget.tagrelease.exception.DomainException;
+import io.github.artemget.teleroute.command.Cmd;
+import io.github.artemget.teleroute.command.CmdException;
+import io.github.artemget.teleroute.send.Send;
+import io.github.artemget.teleroute.telegrambots.send.SendMessageWrap;
+import java.util.ArrayList;
+import java.util.List;
+import org.apache.commons.lang3.StringUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.telegram.telegrambots.meta.api.methods.send.SendMessage;
+import org.telegram.telegrambots.meta.api.objects.Update;
+import org.telegram.telegrambots.meta.bots.AbsSender;
+
+public class CmdBuildTags implements Cmd {
+ private final Logger log = LoggerFactory.getLogger(CmdBuildTags.class);
+ private final Services services;
+ private final Tags tags;
+
+ public CmdBuildTags(
+ final Entry host,
+ final Entry project,
+ final Entry token
+ ) {
+ this(new ServicesAll(host, project, token), new TagsGl(host, token));
+ }
+
+ public CmdBuildTags(final Services services, final Tags tags) {
+ this.services = services;
+ this.tags = tags;
+ }
+
+ @Override
+ public Send execute(Update update) throws CmdException {
+ final List names;
+ final String branch;
+ final String prefix;
+ final String[] values = StringUtils.substringsBetween(update.getMessage().getText(), "{", "}");
+ try {
+ names = new ESplit(new EUnwrap(values[0]), ",").value();
+ } catch (final EntryException exception) {
+ throw new CmdException("Failed to parse service names for tag build", exception);
+ }
+ try {
+ prefix = new EUnwrap(values[1]).value();
+ } catch (final EntryException exception) {
+ throw new CmdException("Failed to parse prefix name for tag build", exception);
+ }
+ try {
+ if (values.length >= 3) {
+ branch = new EUnwrap(values[2]).value();
+ } else {
+ branch = "develop";
+ }
+ } catch (final EntryException exception) {
+ throw new CmdException("Failed to parse branch name for tag build", exception);
+ }
+ final List succeed = new ArrayList<>();
+ final List failed = new ArrayList<>();
+ for (final String name : names) {
+ Service service;
+ try {
+ service = this.services.service(name);
+ } catch (final DomainException exception) {
+ log.error("Failed to fetch service:'{}' for tag build", name, exception);
+ failed.add(name);
+ continue;
+ }
+ final Tag tag;
+ try {
+ tag = this.tags.buildNew(service.id(), branch, prefix);
+ } catch (final DomainException exception) {
+ log.error("Failed to build tag for service:'{}'", name, exception);
+ failed.add(name);
+ continue;
+ }
+ succeed.add(tag);
+ }
+ final SendMessage message = new SendMessage(
+ update.getMessage().getChatId().toString(),
+ String.format(
+ "Собраны сервисы:\n%s\nОшибка сборки сервисов:\n%s",
+ new Tag.Printed(succeed).asString(),
+ String.join("\n", failed)
+ )
+ );
+ message.setReplyToMessageId(update.getMessage().getMessageId());
+ message.enableMarkdownV2(true);
+ return new SendMessageWrap<>(message);
+ }
+}
diff --git a/src/main/java/io/github/artemget/tagrelease/command/CmdEcho.java b/src/main/java/io/github/artemget/tagrelease/command/CmdEcho.java
new file mode 100644
index 0000000..db50e29
--- /dev/null
+++ b/src/main/java/io/github/artemget/tagrelease/command/CmdEcho.java
@@ -0,0 +1,44 @@
+/*
+ * MIT License
+ *
+ * Copyright (c) 2024-2025. Artem Getmanskii
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+package io.github.artemget.tagrelease.command;
+
+import io.github.artemget.teleroute.command.Cmd;
+import io.github.artemget.teleroute.command.CmdException;
+import io.github.artemget.teleroute.send.Send;
+import io.github.artemget.teleroute.telegrambots.send.SendMessageWrap;
+import org.telegram.telegrambots.meta.api.methods.send.SendMessage;
+import org.telegram.telegrambots.meta.api.objects.Update;
+import org.telegram.telegrambots.meta.bots.AbsSender;
+public class CmdEcho implements Cmd {
+ @Override
+ public Send execute(Update update) throws CmdException {
+ return new SendMessageWrap<>(
+ new SendMessage(
+ update.getMessage().getChatId().toString(),
+ update.getMessage().getFrom().getId().toString()
+ )
+ );
+ }
+}
diff --git a/src/main/java/io/github/artemget/tagrelease/command/CmdEchoReply.java b/src/main/java/io/github/artemget/tagrelease/command/CmdEchoReply.java
new file mode 100644
index 0000000..cf62b59
--- /dev/null
+++ b/src/main/java/io/github/artemget/tagrelease/command/CmdEchoReply.java
@@ -0,0 +1,44 @@
+/*
+ * MIT License
+ *
+ * Copyright (c) 2024-2025. Artem Getmanskii
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+package io.github.artemget.tagrelease.command;
+
+import io.github.artemget.teleroute.command.Cmd;
+import io.github.artemget.teleroute.command.CmdException;
+import io.github.artemget.teleroute.send.Send;
+import io.github.artemget.teleroute.telegrambots.send.SendMessageWrap;
+import org.telegram.telegrambots.meta.api.methods.send.SendMessage;
+import org.telegram.telegrambots.meta.api.objects.Update;
+import org.telegram.telegrambots.meta.bots.AbsSender;
+public class CmdEchoReply implements Cmd {
+ @Override
+ public Send execute(Update update) throws CmdException {
+ return new SendMessageWrap<>(
+ new SendMessage(
+ update.getMessage().getChatId().toString(),
+ update.getMessage().getReplyToMessage().getFrom().getId().toString()
+ )
+ );
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/io/github/artemget/tagrelease/command/CmdListStand.java b/src/main/java/io/github/artemget/tagrelease/command/CmdListServices.java
similarity index 62%
rename from src/main/java/io/github/artemget/tagrelease/command/CmdListStand.java
rename to src/main/java/io/github/artemget/tagrelease/command/CmdListServices.java
index 8b96ffd..9bb7b70 100644
--- a/src/main/java/io/github/artemget/tagrelease/command/CmdListStand.java
+++ b/src/main/java/io/github/artemget/tagrelease/command/CmdListServices.java
@@ -24,25 +24,26 @@
package io.github.artemget.tagrelease.command;
-import io.github.artemget.tagrelease.domain.Stand;
+import io.github.artemget.entrys.EntryException;
+import io.github.artemget.entrys.operation.EUnwrap;
+import io.github.artemget.tagrelease.domain.Service;
import io.github.artemget.tagrelease.domain.Stands;
+import io.github.artemget.tagrelease.exception.DomainException;
import io.github.artemget.teleroute.command.Cmd;
import io.github.artemget.teleroute.command.CmdException;
import io.github.artemget.teleroute.send.Send;
import io.github.artemget.teleroute.telegrambots.send.SendMessageWrap;
-import org.cactoos.text.Replaced;
-import org.cactoos.text.TextOf;
-import org.cactoos.text.Trimmed;
+import java.util.stream.Collectors;
import org.telegram.telegrambots.meta.api.methods.send.SendMessage;
import org.telegram.telegrambots.meta.api.objects.Update;
import org.telegram.telegrambots.meta.bots.AbsSender;
/**
- * Lists stand and it's services.
+ * Lists services by stand.
*
* @since 0.1.0
*/
-public final class CmdListStand implements Cmd {
+public final class CmdListServices implements Cmd {
/**
* Available stands.
*/
@@ -52,7 +53,7 @@ public final class CmdListStand implements Cmd {
* Main ctor.
* @param stands Available stands.
*/
- public CmdListStand(final Stands stands) {
+ public CmdListServices(final Stands stands) {
this.stands = stands;
}
@@ -60,25 +61,36 @@ public CmdListStand(final Stands stands) {
@SuppressWarnings("PMD.AvoidCatchingGenericException")
@Override
public Send execute(final Update update) throws CmdException {
+ final String request = update.getMessage().getText();
+ final String name;
+ try {
+ name = new EUnwrap(update.getMessage().getText()).value();
+ } catch (final EntryException exception) {
+ throw new CmdException(
+ String.format("Failed to get value from cmd:'%s'", request),
+ exception
+ );
+ }
final SendMessage message;
try {
message = new SendMessage(
update.getMessage().getChatId().toString(),
- new Stand.Printed(
- this.stands.stand(
- new Trimmed(
- new Replaced(
- new TextOf(update.getMessage().getText()),
- "Покажи сервис",
- ""
- )
- ).asString()
- )
- ).toString()
+ String.format(
+ "```\n %s\n```",
+ this.stands.stand(name).services().services()
+ .stream().map(Service::name).collect(Collectors.joining("\n"))
+ )
);
- } catch (final Exception exception) {
+ } catch (final DomainException exception) {
throw new CmdException(
- String.format("Failed to eject value from cmd %s", update.getMessage().getText()),
+ String.format(
+ "Failed get services from stand:'%s' from cmd:'%s'. From user:'%s', userId:'%s' in chat:'%s'",
+ name,
+ request,
+ update.getMessage().getFrom().getUserName(),
+ update.getMessage().getFrom().getId(),
+ update.getMessage().getChatId()
+ ),
exception
);
}
diff --git a/src/main/java/io/github/artemget/tagrelease/command/CmdListServicesAll.java b/src/main/java/io/github/artemget/tagrelease/command/CmdListServicesAll.java
new file mode 100644
index 0000000..dd67504
--- /dev/null
+++ b/src/main/java/io/github/artemget/tagrelease/command/CmdListServicesAll.java
@@ -0,0 +1,90 @@
+/*
+ * MIT License
+ *
+ * Copyright (c) 2024-2025. Artem Getmanskii
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+package io.github.artemget.tagrelease.command;
+
+import io.github.artemget.entrys.Entry;
+import io.github.artemget.tagrelease.domain.Service;
+import io.github.artemget.tagrelease.domain.Services;
+import io.github.artemget.tagrelease.domain.ServicesAll;
+import io.github.artemget.tagrelease.exception.DomainException;
+import io.github.artemget.teleroute.command.Cmd;
+import io.github.artemget.teleroute.command.CmdException;
+import io.github.artemget.teleroute.send.Send;
+import io.github.artemget.teleroute.telegrambots.send.SendMessageWrap;
+import java.util.List;
+import java.util.stream.Collectors;
+import org.telegram.telegrambots.meta.api.methods.send.SendMessage;
+import org.telegram.telegrambots.meta.api.objects.Update;
+import org.telegram.telegrambots.meta.bots.AbsSender;
+
+/**
+ * Bot command.
+ * List all repositories in gitlab and send reply to user message.
+ *
+ * @since 0.0.1
+ */
+public final class CmdListServicesAll implements Cmd {
+ private final Services services;
+
+ public CmdListServicesAll(
+ final Entry host,
+ final Entry project,
+ final Entry token
+ ) {
+ this(new ServicesAll(host, project, token));
+ }
+
+ public CmdListServicesAll(final Services services) {
+ this.services = services;
+ }
+
+ @Override
+ public Send execute(final Update update) throws CmdException {
+ List srvs;
+ try {
+ srvs = this.services.services();
+ } catch (final DomainException exception) {
+ throw new CmdException(
+ String.format(
+ "Error list all services. From user:'%s', userId:'%s' in chat:'%s'",
+ update.getMessage().getFrom().getUserName(),
+ update.getMessage().getFrom().getId(),
+ update.getMessage().getChatId()
+ ),
+ exception
+ );
+ }
+ final SendMessage message = new SendMessage(
+ update.getMessage().getChatId().toString(),
+ String.format(
+ "```\n%s```",
+ srvs.stream().map(Service::name).collect(Collectors.joining("\n"))
+ )
+ );
+ message.setReplyToMessageId(update.getMessage().getMessageId());
+ message.enableMarkdownV2(true);
+ return new SendMessageWrap<>(message);
+ }
+}
diff --git a/src/main/java/io/github/artemget/tagrelease/command/CmdListStands.java b/src/main/java/io/github/artemget/tagrelease/command/CmdListStands.java
index c877735..bef6501 100644
--- a/src/main/java/io/github/artemget/tagrelease/command/CmdListStands.java
+++ b/src/main/java/io/github/artemget/tagrelease/command/CmdListStands.java
@@ -24,17 +24,21 @@
package io.github.artemget.tagrelease.command;
+import io.github.artemget.tagrelease.domain.Stand;
import io.github.artemget.tagrelease.domain.Stands;
+import io.github.artemget.tagrelease.exception.DomainException;
import io.github.artemget.teleroute.command.Cmd;
+import io.github.artemget.teleroute.command.CmdException;
import io.github.artemget.teleroute.send.Send;
import io.github.artemget.teleroute.telegrambots.send.SendMessageWrap;
+import java.util.List;
+import java.util.stream.Collectors;
import org.telegram.telegrambots.meta.api.methods.send.SendMessage;
import org.telegram.telegrambots.meta.api.objects.Update;
import org.telegram.telegrambots.meta.bots.AbsSender;
/**
* Lists available stands and it's services.
- *
* @since 0.1.0
*/
public final class CmdListStands implements Cmd {
@@ -52,10 +56,27 @@ public CmdListStands(final Stands stands) {
}
@Override
- public Send execute(final Update update) {
+ public Send execute(final Update update) throws CmdException {
+ final List stands;
+ try {
+ stands = this.stands.stands();
+ } catch (final DomainException exception) {
+ throw new CmdException(
+ String.format(
+ "Error list all stands. From user:'%s', userId:'%s' in chat:'%s'",
+ update.getMessage().getFrom().getUserName(),
+ update.getMessage().getFrom().getId(),
+ update.getMessage().getChatId()
+ ),
+ exception
+ );
+ }
final SendMessage message = new SendMessage(
update.getMessage().getChatId().toString(),
- new Stands.Printed(this.stands).toString()
+ String.format(
+ "```\n%s```",
+ stands.stream().map(Stand::name).collect(Collectors.joining("\n"))
+ )
);
message.setReplyToMessageId(update.getMessage().getMessageId());
message.enableMarkdownV2(true);
diff --git a/src/main/java/io/github/artemget/tagrelease/domain/Service.java b/src/main/java/io/github/artemget/tagrelease/domain/Service.java
index b1cf289..addc845 100644
--- a/src/main/java/io/github/artemget/tagrelease/domain/Service.java
+++ b/src/main/java/io/github/artemget/tagrelease/domain/Service.java
@@ -24,7 +24,7 @@
package io.github.artemget.tagrelease.domain;
-import io.github.artemget.tagrelease.exception.TagException;
+import io.github.artemget.tagrelease.exception.DomainException;
import org.cactoos.Scalar;
/**
@@ -33,6 +33,7 @@
* @since 0.1.0
*/
public interface Service {
+ String id();
/**
* Returns application name.
*
@@ -45,13 +46,5 @@ public interface Service {
*
* @return Tag
*/
- String tag();
-
- /**
- * Builds new tag.
- *
- * @param rule To build tag
- * @return Service with a new tag
- */
- Service tagged(Scalar rule) throws TagException;
+ String tag() throws DomainException;
}
diff --git a/src/main/java/io/github/artemget/tagrelease/domain/ServiceEa.java b/src/main/java/io/github/artemget/tagrelease/domain/ServiceEa.java
new file mode 100644
index 0000000..ca2e1be
--- /dev/null
+++ b/src/main/java/io/github/artemget/tagrelease/domain/ServiceEa.java
@@ -0,0 +1,117 @@
+/*
+ * MIT License
+ *
+ * Copyright (c) 2024-2025. Artem Getmanskii
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+package io.github.artemget.tagrelease.domain;
+
+import com.amihaiemil.eoyaml.Yaml;
+import com.jcabi.http.Request;
+import com.jcabi.http.response.RestResponse;
+import io.github.artemget.entrys.Entry;
+import io.github.artemget.entrys.EntryException;
+import io.github.artemget.entrys.fake.EFake;
+import io.github.artemget.entrys.json.EJsonStr;
+import io.github.artemget.tagrelease.exception.DomainException;
+import java.io.IOException;
+import java.io.StringReader;
+import javax.json.Json;
+
+/**
+ * Application's source code in gitlab.
+ * @since 0.1.0
+ */
+@SuppressWarnings("PMD.AvoidFieldNameMatchingMethodName")
+public final class ServiceEa implements Service {
+ /**
+ * Repository ID.
+ */
+ private final String id;
+
+ /**
+ * Repository name.
+ */
+ private final String name;
+
+ /**
+ * Last tag.
+ */
+ private final Entry tag;
+
+ public ServiceEa(
+ final Entry id,
+ final Entry name,
+ final Entry tag
+ ) throws EntryException, IOException {
+ this(
+ id.value(),
+ name.value(),
+ new EFake<>(
+ Yaml.createYamlInput(
+ new EJsonStr(
+ Json.createReader(
+ new StringReader(
+ tag.value().fetch().as(RestResponse.class).body()
+ )
+ ).readObject()
+ , "content"
+ ).value()
+ ).readYamlMapping()
+ .yamlMapping("image")
+ .string("tag")
+ )
+ );
+ }
+
+ /**
+ * Main ctor.
+ * @param name Of application
+ * @param tag Of application
+ */
+ public ServiceEa(final String id, final String name, final Entry tag) {
+ this.id = id;
+ this.name = name;
+ this.tag = tag;
+ }
+
+ @Override
+ public String id() {
+ return this.id;
+ }
+
+ @Override
+ public String name() {
+ return this.name;
+ }
+
+ @Override
+ public String tag() throws DomainException {
+ try {
+ return this.tag.value();
+ } catch (final EntryException exception) {
+ throw new DomainException(
+ String.format("Failed ro fetch tag for service:'%s'", this.name()),
+ exception
+ );
+ }
+ }
+}
diff --git a/src/main/java/io/github/artemget/tagrelease/domain/Services.java b/src/main/java/io/github/artemget/tagrelease/domain/Services.java
index 183a171..bee47df 100644
--- a/src/main/java/io/github/artemget/tagrelease/domain/Services.java
+++ b/src/main/java/io/github/artemget/tagrelease/domain/Services.java
@@ -24,35 +24,31 @@
package io.github.artemget.tagrelease.domain;
+import io.github.artemget.tagrelease.exception.DomainException;
import java.util.List;
-import java.util.stream.Collectors;
import org.cactoos.Text;
/**
* Applications.
- *
* @since 0.1.0
*/
public interface Services {
/**
* Returns all services from stand.
- *
* @return Services
*/
- List services();
+ List services() throws DomainException;
/**
* Returns service from stand by it's name.
- *
* @param name Of service
* @return Service
*/
- Service service(String name);
+ Service service(String name) throws DomainException;
/**
* Printed Services.
* Format: ```java %s:%s```\n
- *
* @since 0.1.0
*/
final class Printed implements Text {
@@ -63,7 +59,6 @@ final class Printed implements Text {
/**
* Main ctor.
- *
* @param services Services
*/
public Printed(final Services services) {
@@ -71,17 +66,12 @@ public Printed(final Services services) {
}
@Override
- public String asString() {
- return this.services.services().stream()
- .map(
- service ->
- String.format(
- "```java %s:%s```\n ",
- service.name(),
- service.tag()
- )
- )
- .collect(Collectors.joining());
+ public String asString() throws DomainException {
+ final StringBuilder string = new StringBuilder();
+ for (final Service service : this.services.services()) {
+ string.append(String.format("```java %s:%s```\n", service.name(), service.tag()));
+ }
+ return string.toString();
}
}
}
diff --git a/src/main/java/io/github/artemget/tagrelease/domain/ServicesAll.java b/src/main/java/io/github/artemget/tagrelease/domain/ServicesAll.java
new file mode 100644
index 0000000..11646f8
--- /dev/null
+++ b/src/main/java/io/github/artemget/tagrelease/domain/ServicesAll.java
@@ -0,0 +1,123 @@
+/*
+ * MIT License
+ *
+ * Copyright (c) 2024-2025. Artem Getmanskii
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+package io.github.artemget.tagrelease.domain;
+
+import com.jcabi.http.Request;
+import com.jcabi.http.request.JdkRequest;
+import io.github.artemget.entrys.Entry;
+import io.github.artemget.entrys.EntryException;
+import io.github.artemget.entrys.json.EJsonStr;
+import io.github.artemget.tagrelease.entry.EFetchArr;
+import io.github.artemget.tagrelease.entry.EFunc;
+import io.github.artemget.tagrelease.exception.DomainException;
+import java.util.ArrayList;
+import java.util.List;
+import javax.json.JsonArray;
+import javax.json.JsonObject;
+import javax.json.JsonValue;
+
+/**
+ * Fetch repositories(services) from gitlab project.
+ * @since 0.0.1
+ */
+public final class ServicesAll implements Services {
+ private final EFunc named;
+ private final Entry all;
+
+ public ServicesAll(
+ final Entry host,
+ final Entry project,
+ final Entry token
+ ) {
+ this(
+ (service) -> new EFetchArr(
+ new JdkRequest(
+ String.format("%s/api/v4/groups/%s/projects?search=%s", host.value(), project.value(), service)
+ ).method(Request.GET)
+ .header("Accept", "application/json")
+ .header("PRIVATE-TOKEN", token.value())
+ ).value(),
+ () -> new EFetchArr(
+ new JdkRequest(String.format("%s/api/v4/groups/%s/projects", host.value(), project.value()))
+ .method(Request.GET)
+ .header("Accept", "application/json")
+ .header("PRIVATE-TOKEN", token.value())
+ ).value()
+ );
+ }
+
+ public ServicesAll(final EFunc named, final Entry all) {
+ this.named = named;
+ this.all = all;
+ }
+
+ @Override
+ public List services() throws DomainException {
+ final JsonArray response;
+ try {
+ response = this.all.value();
+ } catch (final EntryException exception) {
+ throw new DomainException("Failed to fetch all services from gitlab", exception);
+ }
+ final List services = new ArrayList<>();
+ for (final JsonValue service : response) {
+ services.add(this.parsed(service));
+ }
+ return services;
+ }
+
+ @Override
+ public Service service(String name) throws DomainException {
+ final JsonArray response;
+ try {
+ response = this.named.apply(name);
+ } catch (final EntryException exception) {
+ throw new DomainException(
+ String.format("Failed to fetch '%s' service from gitlab", name),
+ exception
+ );
+ }
+ for (final JsonValue value : response) {
+ final Service service = this.parsed(value);
+ if (name.equals(service.name())) {
+ return service;
+ }
+ }
+ throw new DomainException(String.format("No service with name: %s", name));
+ }
+
+ private Service parsed(final JsonValue service) throws DomainException {
+ try {
+ JsonObject json = service.asJsonObject();
+ return new ServiceEa(
+ String.valueOf(json.getInt("id")),
+ new EJsonStr(json, "name").value(),
+ () -> ""
+ );
+ } catch (final EntryException | ClassCastException exception) {
+ throw new DomainException("Failed to parse service from gitlab", exception);
+ }
+ }
+}
diff --git a/src/main/java/io/github/artemget/tagrelease/domain/ServicesGl.java b/src/main/java/io/github/artemget/tagrelease/domain/ServicesGl.java
new file mode 100644
index 0000000..5f60a51
--- /dev/null
+++ b/src/main/java/io/github/artemget/tagrelease/domain/ServicesGl.java
@@ -0,0 +1,166 @@
+/*
+ * MIT License
+ *
+ * Copyright (c) 2024-2025. Artem Getmanskii
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+package io.github.artemget.tagrelease.domain;
+
+import com.amihaiemil.eoyaml.Yaml;
+import com.amihaiemil.eoyaml.exceptions.YamlIndentationException;
+import com.jcabi.http.Request;
+import com.jcabi.http.request.JdkRequest;
+import io.github.artemget.entrys.Entry;
+import io.github.artemget.entrys.EntryException;
+import io.github.artemget.entrys.json.EJsonStr;
+import io.github.artemget.tagrelease.entry.EFetchArr;
+import io.github.artemget.tagrelease.entry.EFetchObj;
+import io.github.artemget.tagrelease.entry.EFunc;
+import io.github.artemget.tagrelease.exception.DomainException;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+import javax.json.JsonArray;
+import javax.json.JsonObject;
+import javax.json.JsonValue;
+import org.apache.commons.codec.binary.Base64;
+
+/**
+ * Applications from gitlab.
+ * @since 0.1.0
+ */
+public final class ServicesGl implements Services {
+ /**
+ * List repository tree. Each directory with name not starting with _ prefix - is a service.
+ * GET /projects/:id/repository/tree
+ */
+ private final Entry services;
+
+ /**
+ * Get file from repository. Tag name placed under image:tag: in this file.
+ * GET /projects/:id/repository/files/:file_path
+ */
+ private final EFunc tag;
+
+ /**
+ * Ctor configures https req to gitlab services.
+ * @param url Of gitlab
+ * @param release Where to search services
+ * @param branch Project which services belong to
+ * @param token Api token
+ */
+ public ServicesGl(
+ final Entry url,
+ final Entry release,
+ final Entry branch,
+ final Entry token
+ ) {
+ this(() -> new EFetchArr(
+ new JdkRequest(
+ String.format(
+ "%s/api/v4/projects/%s/repository/tree?ref=%s&per_page=100",
+ url.value(), release.value(), branch.value()
+ )
+ ).method(Request.GET)
+ .header("Accept", "application/json")
+ .header("PRIVATE-TOKEN", token.value())
+ ).value(),
+ (service) -> new EFetchObj(
+ new JdkRequest(
+ String.format(
+ "%s/api/v4/projects/%s/repository/files/%s?ref=%s",
+ url.value(), release.value(), service.concat("%2Fvalues.yaml"), branch.value()
+ )
+ ).method(Request.GET)
+ .header("Accept", "application/json")
+ .header("PRIVATE-TOKEN", token.value())
+ ).value()
+ );
+ }
+
+ /**
+ * Main ctor.
+ * @param services At gitlab
+ */
+ public ServicesGl(final Entry services, final EFunc tag) {
+ this.services = services;
+ this.tag = tag;
+ }
+
+ @Override
+ public List services() throws DomainException {
+ final JsonArray array;
+ try {
+ array = this.services.value();
+ } catch (final EntryException exception) {
+ throw new DomainException("Failed to fetch services from stand", exception);
+ }
+ final List services = new ArrayList<>();
+ for (final JsonValue dir : array) {
+ final JsonObject json = dir.asJsonObject();
+ final String name = json.getString("name");
+ final boolean directory = json.getString("type").equals("tree");
+ final boolean service = !name.startsWith("_");
+ if (directory && service) {
+ services.add(this.service(name));
+ }
+ }
+ return services;
+ }
+
+ @Override
+ public Service service(final String name) throws DomainException {
+ return new ServiceEa(
+ "",
+ name,
+ () -> {
+ final JsonObject json;
+ try {
+ json = this.tag.apply(name);
+ } catch (final EntryException exception) {
+ throw new EntryException(
+ String.format("Failed to fetch '%s' service from stand", name),
+ exception
+ );
+ }
+ final String content;
+ try {
+ content = new String(Base64.decodeBase64(new EJsonStr(json, "content").value()));
+ } catch (final EntryException exception) {
+ throw new EntryException(
+ String.format("Failed to get content for service:'%s' from:'%s'", name, json),
+ exception
+ );
+ }
+ try {
+ return Yaml.createYamlInput(content).readYamlMapping()
+ .yamlMapping("image")
+ .string("tag");
+ } catch (final IOException | YamlIndentationException exception) {
+ throw new EntryException(
+ String.format("Failed to get content for service:'%s' from:'%s'", name, json),
+ exception
+ );
+ }
+ }
+ );
+ }
+}
diff --git a/src/main/java/io/github/artemget/tagrelease/domain/Stand.java b/src/main/java/io/github/artemget/tagrelease/domain/Stand.java
index 66b445d..352b0db 100644
--- a/src/main/java/io/github/artemget/tagrelease/domain/Stand.java
+++ b/src/main/java/io/github/artemget/tagrelease/domain/Stand.java
@@ -24,6 +24,7 @@
package io.github.artemget.tagrelease.domain;
+import io.github.artemget.tagrelease.exception.DomainException;
import org.cactoos.Text;
/**
@@ -44,7 +45,7 @@ public interface Stand {
*
* @return Services
*/
- Services services();
+ Services services() throws DomainException;
/**
* Printed server.
@@ -71,7 +72,7 @@ public Printed(final Stand stand) {
}
@Override
- public String asString() {
+ public String asString() throws DomainException {
return String.format(
"""
Стенд: %s
diff --git a/src/main/java/io/github/artemget/tagrelease/domain/ServiceGitlabEager.java b/src/main/java/io/github/artemget/tagrelease/domain/StandGl.java
similarity index 58%
rename from src/main/java/io/github/artemget/tagrelease/domain/ServiceGitlabEager.java
rename to src/main/java/io/github/artemget/tagrelease/domain/StandGl.java
index 91410ab..f2ca38d 100644
--- a/src/main/java/io/github/artemget/tagrelease/domain/ServiceGitlabEager.java
+++ b/src/main/java/io/github/artemget/tagrelease/domain/StandGl.java
@@ -24,35 +24,22 @@
package io.github.artemget.tagrelease.domain;
-import io.github.artemget.tagrelease.exception.TagException;
-import org.cactoos.Scalar;
+import io.github.artemget.entrys.Entry;
+import io.github.artemget.entrys.EntryException;
+import io.github.artemget.tagrelease.exception.DomainException;
/**
- * Application's source code in gitlab.
+ * Stand for customer.
*
* @since 0.1.0
*/
-@SuppressWarnings("PMD.AvoidFieldNameMatchingMethodName")
-public final class ServiceGitlabEager implements Service {
- /**
- * Application name.
- */
+public final class StandGl implements Stand {
private final String name;
+ private final Entry services;
- /**
- * Application tag.
- */
- private final String tag;
-
- /**
- * Main ctor.
- *
- * @param name Of application
- * @param tag Of application
- */
- public ServiceGitlabEager(final String name, final String tag) {
+ public StandGl(final String name, final Entry services) {
this.name = name;
- this.tag = tag;
+ this.services = services;
}
@Override
@@ -61,19 +48,12 @@ public String name() {
}
@Override
- public String tag() {
- return this.tag;
- }
-
- // @checkstyle IllegalCatchCheck (50 lines)
- @SuppressWarnings("PMD.AvoidCatchingGenericException")
- @Override
- public Service tagged(final Scalar rule) throws TagException {
+ public Services services() throws DomainException {
try {
- return new ServiceGitlabEager(this.name, rule.value());
- } catch (final Exception exception) {
- throw new TagException(
- String.format("Failed to create tag for service: %s", this.name),
+ return this.services.value();
+ } catch (final EntryException exception) {
+ throw new DomainException(
+ String.format("Failed to fetch services from stand:'%s'", this.name),
exception
);
}
diff --git a/src/main/java/io/github/artemget/tagrelease/domain/Stands.java b/src/main/java/io/github/artemget/tagrelease/domain/Stands.java
index 78120af..628a115 100644
--- a/src/main/java/io/github/artemget/tagrelease/domain/Stands.java
+++ b/src/main/java/io/github/artemget/tagrelease/domain/Stands.java
@@ -24,6 +24,7 @@
package io.github.artemget.tagrelease.domain;
+import io.github.artemget.tagrelease.exception.DomainException;
import java.util.List;
import java.util.stream.Collectors;
import org.cactoos.Text;
@@ -39,7 +40,7 @@ public interface Stands {
*
* @return Servers
*/
- List stands();
+ List stands() throws DomainException;
/**
* Returns server by it's name.
@@ -47,7 +48,7 @@ public interface Stands {
* @param name Name
* @return Server
*/
- Stand stand(String name);
+ Stand stand(String name) throws DomainException;
/**
* Printed servers.
@@ -69,7 +70,7 @@ public Printed(final Stands stands) {
}
@Override
- public String asString() {
+ public String asString() throws DomainException {
return this.stands.stands().stream()
.map(st -> new Stand.Printed(st).toString())
.collect(Collectors.joining());
diff --git a/src/main/java/io/github/artemget/tagrelease/domain/StandsGl.java b/src/main/java/io/github/artemget/tagrelease/domain/StandsGl.java
new file mode 100644
index 0000000..4f38740
--- /dev/null
+++ b/src/main/java/io/github/artemget/tagrelease/domain/StandsGl.java
@@ -0,0 +1,133 @@
+/*
+ * MIT License
+ *
+ * Copyright (c) 2024-2025. Artem Getmanskii
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+package io.github.artemget.tagrelease.domain;
+
+import com.jcabi.http.Request;
+import com.jcabi.http.request.JdkRequest;
+import io.github.artemget.entrys.Entry;
+import io.github.artemget.entrys.EntryException;
+import io.github.artemget.entrys.json.EJsonStr;
+import io.github.artemget.tagrelease.entry.EFetchArr;
+import io.github.artemget.tagrelease.entry.EFetchObj;
+import io.github.artemget.tagrelease.entry.EFunc;
+import io.github.artemget.tagrelease.exception.DomainException;
+import java.util.ArrayList;
+import java.util.List;
+import javax.json.JsonArray;
+import javax.json.JsonObject;
+import javax.json.JsonValue;
+
+/**
+ * Servers.
+ * @since 0.1.0
+ */
+public final class StandsGl implements Stands {
+ /**
+ * Gitlab request. List repository branches.
+ * GET /projects/:id/repository/branches
+ */
+ private final Entry stands;
+
+ /**
+ * Gitlab request. List repository branch by name.
+ * GET /projects/:id/repository/branches
+ */
+ private final EFunc stand;
+
+ private final EFunc services;
+
+ public StandsGl(
+ final Entry url,
+ final Entry release,
+ final Entry token
+ ) {
+ this(
+ () -> new EFetchArr(
+ new JdkRequest(
+ String.format("%s/api/v4/projects/%s/repository/branches", url.value(), release.value())
+ ).method(Request.GET)
+ .header("Accept", "application/json")
+ .header("PRIVATE-TOKEN", token.value())
+ ).value(),
+ (name) -> new EFetchObj(
+ new JdkRequest(
+ String.format(
+ "%s/api/v4/projects/%s/repository/branches/%s",
+ url.value(), release.value(), name
+ )
+ ).method(Request.GET)
+ .header("Accept", "application/json")
+ .header("PRIVATE-TOKEN", token.value())
+ ).value(),
+ (branch) -> new ServicesGl(url, release, () -> branch, token)
+ );
+ }
+
+ public StandsGl(
+ final Entry stands,
+ final EFunc stand,
+ final EFunc services
+ ) {
+ this.stands = stands;
+ this.stand = stand;
+ this.services = services;
+ }
+
+ @Override
+ public List stands() throws DomainException {
+ final JsonArray response;
+ try {
+ response = this.stands.value();
+ } catch (final EntryException exception) {
+ throw new DomainException("Failed to fetch all services from gitlab", exception);
+ }
+ final List stands = new ArrayList<>();
+ for (final JsonValue branch : response) {
+ final Stand stand = this.enriched(branch.asJsonObject());
+ if (!"main".equals(stand.name())) {
+ stands.add(stand);
+ }
+ }
+ return stands;
+ }
+
+ @Override
+ public Stand stand(final String name) throws DomainException {
+ try {
+ return this.enriched(this.stand.apply(name));
+ } catch (final EntryException exception) {
+ throw new DomainException("Failed to fetch all services from gitlab", exception);
+ }
+ }
+
+ private Stand enriched(final JsonObject service) throws DomainException {
+ try {
+ final String branch = new EJsonStr(service, "name").value();
+ return new StandGl(branch, () -> this.services.apply(branch));
+ } catch (final EntryException exception) {
+ throw new DomainException("Failed to parse service from gitlab", exception);
+ }
+ }
+}
diff --git a/src/main/java/io/github/artemget/tagrelease/domain/Tag.java b/src/main/java/io/github/artemget/tagrelease/domain/Tag.java
new file mode 100644
index 0000000..288098f
--- /dev/null
+++ b/src/main/java/io/github/artemget/tagrelease/domain/Tag.java
@@ -0,0 +1,65 @@
+/*
+ * MIT License
+ *
+ * Copyright (c) 2024-2025. Artem Getmanskii
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+package io.github.artemget.tagrelease.domain;
+
+import java.util.List;
+import org.cactoos.Text;
+public interface Tag {
+ String repo();
+
+ String name();
+
+ String branch();
+
+ String fromCommit();
+
+ String message();
+
+ String created();
+
+ final class Printed implements Text {
+ /**
+ * Tags.
+ */
+ private final List tags;
+
+ /**
+ * Main ctor.
+ * @param tags Built
+ */
+ public Printed(final List tags) {
+ this.tags = tags;
+ }
+
+ @Override
+ public String asString() {
+ final StringBuilder string = new StringBuilder();
+ for (final Tag tag : this.tags) {
+ string.append(String.format("```%s:%s```\n", tag.repo(), tag.name()));
+ }
+ return string.toString();
+ }
+ }
+}
diff --git a/src/main/java/io/github/artemget/tagrelease/domain/TagEa.java b/src/main/java/io/github/artemget/tagrelease/domain/TagEa.java
new file mode 100644
index 0000000..93da690
--- /dev/null
+++ b/src/main/java/io/github/artemget/tagrelease/domain/TagEa.java
@@ -0,0 +1,80 @@
+/*
+ * MIT License
+ *
+ * Copyright (c) 2024-2025. Artem Getmanskii
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+package io.github.artemget.tagrelease.domain;
+
+public final class TagEa implements Tag {
+ private final String repo;
+ private final String name;
+ private final String branch;
+ private final String commit;
+ private final String message;
+ private final String created;
+
+ public TagEa(
+ final String repo,
+ final String name,
+ final String branch,
+ final String commit,
+ final String message,
+ final String created
+ ) {
+ this.repo = repo;
+ this.name = name;
+ this.branch = branch;
+ this.commit = commit;
+ this.message = message;
+ this.created = created;
+ }
+
+ @Override
+ public String repo() {
+ return this.repo;
+ }
+
+ @Override
+ public String name() {
+ return this.name;
+ }
+
+ @Override
+ public String branch() {
+ return this.branch;
+ }
+
+ @Override
+ public String fromCommit() {
+ return this.commit;
+ }
+
+ @Override
+ public String message() {
+ return this.message;
+ }
+
+ @Override
+ public String created() {
+ return this.created;
+ }
+}
diff --git a/src/main/java/io/github/artemget/tagrelease/domain/StandGitlab.java b/src/main/java/io/github/artemget/tagrelease/domain/Tags.java
similarity index 79%
rename from src/main/java/io/github/artemget/tagrelease/domain/StandGitlab.java
rename to src/main/java/io/github/artemget/tagrelease/domain/Tags.java
index f8135c4..54d4a06 100644
--- a/src/main/java/io/github/artemget/tagrelease/domain/StandGitlab.java
+++ b/src/main/java/io/github/artemget/tagrelease/domain/Tags.java
@@ -24,19 +24,9 @@
package io.github.artemget.tagrelease.domain;
-/**
- * Server at gitlab.
- *
- * @since 0.1.0
- */
-public final class StandGitlab implements Stand {
- @Override
- public String name() {
- throw new UnsupportedOperationException();
- }
+import io.github.artemget.tagrelease.exception.DomainException;
+public interface Tags {
+ Tag buildNew(final String serviceId, final String branch, final String prefix) throws DomainException;
- @Override
- public Services services() {
- throw new UnsupportedOperationException();
- }
+ Tag current(final String serviceId, final String branch, final String prefix) throws DomainException;
}
diff --git a/src/main/java/io/github/artemget/tagrelease/domain/TagsGl.java b/src/main/java/io/github/artemget/tagrelease/domain/TagsGl.java
new file mode 100644
index 0000000..26e5cf0
--- /dev/null
+++ b/src/main/java/io/github/artemget/tagrelease/domain/TagsGl.java
@@ -0,0 +1,237 @@
+/*
+ * MIT License
+ *
+ * Copyright (c) 2024-2025. Artem Getmanskii
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+package io.github.artemget.tagrelease.domain;
+
+import com.jcabi.http.Request;
+import com.jcabi.http.request.JdkRequest;
+import io.github.artemget.entrys.Entry;
+import io.github.artemget.entrys.EntryException;
+import io.github.artemget.tagrelease.entry.EFetchArr;
+import io.github.artemget.tagrelease.entry.EFetchObj;
+import io.github.artemget.tagrelease.entry.EFunc;
+import io.github.artemget.tagrelease.exception.DomainException;
+import javax.json.JsonArray;
+import javax.json.JsonObject;
+import javax.json.JsonValue;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public final class TagsGl implements Tags {
+ private final Logger log = LoggerFactory.getLogger(TagsGl.class);
+ private final EFunc tag;
+ private final EFunc create;
+ private final EFunc message;
+
+ public TagsGl(
+ final Entry url,
+ final Entry token
+ ) {
+ this(
+ (tag) ->
+ new EFetchArr(
+ new JdkRequest(
+ String.format(
+ "%s/api/v4/projects/%s/repository/tags?search=%%5E%s",
+ url.value(),
+ tag.repo(),
+ tag.name().replace(".*", "")
+ )
+ ).method(Request.GET)
+ .header("Accept", "application/json")
+ .header("PRIVATE-TOKEN", token.value())
+ ).value(),
+ (tag) ->
+ new EFetchObj(
+ new JdkRequest(
+ String.format(
+ "%s/api/v4/projects/%s/repository/tags?ref=%s&tag_name=%s",
+ url.value(),
+ tag.repo(),
+ tag.branch(),
+ tag.name()
+ )
+ ).method(Request.POST)
+ .header("Accept", "application/json")
+ .header("PRIVATE-TOKEN", token.value())
+ ).value(),
+ (tag) -> {
+ final StringBuilder message = new StringBuilder();
+ int page = 1;
+ boolean isFound = false;
+ while (page <= 5 && !isFound) {
+ for (final JsonValue value : TagsGl.mrs(tag, url.value(), token.value(), String.valueOf(page))) {
+ final JsonObject mr = value.asJsonObject();
+ final boolean isSquash = !mr.isNull("squash_commit_sha")
+ && tag.fromCommit().equals(mr.getString("squash_commit_sha"));
+ final boolean isMerge = !mr.isNull("merge_commit_sha")
+ && tag.fromCommit().equals(mr.getString("merge_commit_sha"));
+ final boolean isMr = !mr.isNull("sha")
+ && tag.fromCommit().equals(mr.getString("sha"));
+ if (isMerge && isSquash && isMr) {
+ isFound = true;
+ break;
+ }
+ message.append(mr.getString("title")).append("\n\n");
+ page++;
+ }
+ }
+ return message.toString();
+ }
+ );
+ }
+
+ public TagsGl(
+ final EFunc tag,
+ final EFunc create,
+ EFunc message
+ ) {
+ this.tag = tag;
+ this.create = create;
+ this.message = message;
+ }
+
+ @Override
+ public Tag buildNew(final String serviceId, final String branch, final String prefix) throws
+ DomainException {
+ final Tag current = this.current(serviceId, branch, prefix);
+ final JsonObject created;
+ try {
+ created = this.create.apply(
+ new TagEa(
+ current.repo(),
+ TagsGl.next(current.name(), prefix),
+ current.branch(),
+ current.fromCommit(),
+ current.message(),
+ current.created()
+ )
+ );
+ } catch (final EntryException exception) {
+ throw new DomainException(
+ String.format(
+ "Failed to create tag with prefix:'%s' for service:'%s' from branch:'%s'. Latest tag:%s",
+ prefix, serviceId, branch, current.name()
+ ),
+ exception
+ );
+ }
+ final JsonObject commit = created.getJsonObject("commit");
+ String message;
+ try {
+ message = this.message.apply(current);
+ } catch (final EntryException exception) {
+ message = "";
+ log.error(
+ "Failed to fetch merge requests for service:'{}', branch:'{}'. Between tags '{}' - '{}'",
+ serviceId,
+ branch,
+ current.name(),
+ created.getString("name"),
+ exception
+ );
+ }
+ return new TagEa(
+ serviceId,
+ created.getString("name"),
+ branch,
+ commit.getString("id"),
+ message,
+ commit.getString("created_at")
+ );
+ }
+
+ @Override
+ public Tag current(final String serviceId, final String branch, final String prefix) throws
+ DomainException {
+ final JsonArray response;
+ try {
+ response = this.tag.apply(new TagEa(serviceId, prefix, branch, "", "", ""));
+ } catch (final EntryException exception) {
+ throw new DomainException(
+ String.format(
+ "Failed to fetch tag with prefix:'%s' for service:'%s' from branch:'%s'",
+ prefix, serviceId, branch
+ ),
+ exception
+ );
+ }
+ //TODO: add branch check
+ final JsonObject current = response.getJsonObject(0);
+ final JsonObject commit = current.getJsonObject("commit");
+ return new TagEa(
+ serviceId,
+ current.getString("name"),
+ branch,
+ commit.getString("id"),
+ commit.getString("message"),
+ commit.getString("created_at")
+ );
+ }
+
+ public static String next(final String current, final String prefix) {
+ final String trimmed = prefix.replace("*", "");
+ final StringBuilder next = new StringBuilder();
+ final int length = current.toCharArray().length;
+ for (int index = 0; index < length; index++) {
+ if (trimmed.length() == index) {
+ final StringBuilder digit = new StringBuilder();
+ while (index < length && Character.isDigit(current.charAt(index))) {
+ digit.append(current.charAt(index));
+ index++;
+ }
+ next.append(Integer.parseInt(digit.toString()) + 1);
+ if (index < length) {
+ next.append(current.charAt(index));
+ }
+ continue;
+ }
+ if (trimmed.length() < index && Character.isDigit(current.charAt(index))) {
+ next.append('0');
+ } else {
+ next.append(current.charAt(index));
+ }
+ }
+ return next.toString();
+ }
+
+ private static JsonArray mrs(final Tag tag, String url, String token, String page) throws
+ EntryException {
+ return new EFetchArr(
+ new JdkRequest(
+ String.format(
+ "%s/api/v4/projects/%s/merge_requests?state=merged&scope=all&created_after=%s&target_branch=%s&per_page=%s&page=%s",
+ url,
+ tag.repo(),
+ tag.created(),
+ tag.branch(),
+ "20",
+ page
+ )
+ ).method(Request.POST)
+ .header("Accept", "application/json")
+ .header("PRIVATE-TOKEN", token)
+ ).value();
+ }
+}
diff --git a/src/main/java/io/github/artemget/tagrelease/entry/EFetchArr.java b/src/main/java/io/github/artemget/tagrelease/entry/EFetchArr.java
new file mode 100644
index 0000000..d8c4d17
--- /dev/null
+++ b/src/main/java/io/github/artemget/tagrelease/entry/EFetchArr.java
@@ -0,0 +1,52 @@
+/*
+ * MIT License
+ *
+ * Copyright (c) 2024-2025. Artem Getmanskii
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+package io.github.artemget.tagrelease.entry;
+
+import com.jcabi.http.Request;
+import io.github.artemget.entrys.Entry;
+import io.github.artemget.entrys.EntryException;
+import javax.json.JsonArray;
+import javax.json.JsonStructure;
+
+public class EFetchArr implements Entry {
+ private final Entry origin;
+
+ public EFetchArr(final Request request) {
+ this(new EFetchJson(request));
+ }
+
+ public EFetchArr(final Entry origin) {
+ this.origin = origin;
+ }
+
+ @Override
+ public JsonArray value() throws EntryException {
+ try {
+ return this.origin.value().asJsonArray();
+ } catch (final ClassCastException exception) {
+ throw new EntryException("Failed to map json structure to JsonArray", exception);
+ }
+ }
+}
diff --git a/src/main/java/io/github/artemget/tagrelease/entry/EFetchJson.java b/src/main/java/io/github/artemget/tagrelease/entry/EFetchJson.java
new file mode 100644
index 0000000..0a9948c
--- /dev/null
+++ b/src/main/java/io/github/artemget/tagrelease/entry/EFetchJson.java
@@ -0,0 +1,53 @@
+/*
+ * MIT License
+ *
+ * Copyright (c) 2024-2025. Artem Getmanskii
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+package io.github.artemget.tagrelease.entry;
+
+import com.jcabi.http.Request;
+import io.github.artemget.entrys.Entry;
+import io.github.artemget.entrys.EntryException;
+import java.io.IOException;
+import java.io.StringReader;
+import javax.json.Json;
+import javax.json.JsonStructure;
+
+public class EFetchJson implements Entry {
+ private final Request request;
+
+ public EFetchJson(final Request request) {
+ this.request = request;
+ }
+
+ @Override
+ public JsonStructure value() throws EntryException {
+ try {
+ return Json.createReader(new StringReader(request.fetch().body())).read();
+ } catch (final IOException exception) {
+ throw new EntryException(
+ String.format("Failed to fetch json array from resource:%s", this.request.uri()),
+ exception
+ );
+ }
+ }
+}
diff --git a/src/main/java/io/github/artemget/tagrelease/entry/EFetchObj.java b/src/main/java/io/github/artemget/tagrelease/entry/EFetchObj.java
new file mode 100644
index 0000000..6effbf5
--- /dev/null
+++ b/src/main/java/io/github/artemget/tagrelease/entry/EFetchObj.java
@@ -0,0 +1,52 @@
+/*
+ * MIT License
+ *
+ * Copyright (c) 2024-2025. Artem Getmanskii
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+package io.github.artemget.tagrelease.entry;
+
+import com.jcabi.http.Request;
+import io.github.artemget.entrys.Entry;
+import io.github.artemget.entrys.EntryException;
+import javax.json.JsonObject;
+import javax.json.JsonStructure;
+
+public class EFetchObj implements Entry {
+ private final Entry origin;
+
+ public EFetchObj(final Request request) {
+ this(new EFetchJson(request));
+ }
+
+ public EFetchObj(final Entry origin) {
+ this.origin = origin;
+ }
+
+ @Override
+ public JsonObject value() throws EntryException {
+ try {
+ return this.origin.value().asJsonObject();
+ } catch (final ClassCastException exception) {
+ throw new EntryException("Failed to map json structure to JsonObject", exception);
+ }
+ }
+}
diff --git a/src/main/java/io/github/artemget/tagrelease/domain/ServicesGitlab.java b/src/main/java/io/github/artemget/tagrelease/entry/EFunc.java
similarity index 74%
rename from src/main/java/io/github/artemget/tagrelease/domain/ServicesGitlab.java
rename to src/main/java/io/github/artemget/tagrelease/entry/EFunc.java
index 7ab47fb..7117bf1 100644
--- a/src/main/java/io/github/artemget/tagrelease/domain/ServicesGitlab.java
+++ b/src/main/java/io/github/artemget/tagrelease/entry/EFunc.java
@@ -22,23 +22,12 @@
* SOFTWARE.
*/
-package io.github.artemget.tagrelease.domain;
+package io.github.artemget.tagrelease.entry;
-import java.util.List;
-
-/**
- * Applications from gitlab.
- *
- * @since 0.1.0
- */
-public final class ServicesGitlab implements Services {
- @Override
- public List services() {
- throw new UnsupportedOperationException();
- }
+import io.github.artemget.entrys.EntryException;
+import org.cactoos.Func;
+public interface EFunc extends Func {
@Override
- public Service service(final String name) {
- throw new UnsupportedOperationException();
- }
+ Y apply(X x) throws EntryException;
}
diff --git a/src/main/java/io/github/artemget/tagrelease/entry/ESplit.java b/src/main/java/io/github/artemget/tagrelease/entry/ESplit.java
deleted file mode 100644
index 2b343fb..0000000
--- a/src/main/java/io/github/artemget/tagrelease/entry/ESplit.java
+++ /dev/null
@@ -1,84 +0,0 @@
-/*
- * MIT License
- *
- * Copyright (c) 2024-2025. Artem Getmanskii
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in all
- * copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-package io.github.artemget.tagrelease.entry;
-
-import io.github.artemget.entrys.Entry;
-import io.github.artemget.entrys.EntryException;
-import java.util.Set;
-import java.util.regex.PatternSyntaxException;
-
-/**
- * Split entry.
- *
- * @since 0.1.0
- */
-public final class ESplit implements Entry> {
- /**
- * Origin string entry.
- */
- private final Entry origin;
-
- /**
- * Split delimiter.
- */
- private final String delimiter;
-
- /**
- * Creates split entry with default ; delimiter.
- *
- * @param origin Entry
- */
- public ESplit(final Entry origin) {
- this(origin, ";");
- }
-
- /**
- * Main ctor.
- *
- * @param origin Entry
- * @param delimiter For splitting
- */
- public ESplit(final Entry origin, final String delimiter) {
- this.origin = origin;
- this.delimiter = delimiter;
- }
-
- @Override
- public Set value() throws EntryException {
- final String value = this.origin.value();
- try {
- return Set.of(value.split(this.delimiter));
- } catch (final PatternSyntaxException exception) {
- throw new EntryException(
- String.format(
- "Wrong pattern delimiter: %s for entry value: %s",
- this.delimiter,
- value
- ),
- exception
- );
- }
- }
-}
diff --git a/src/main/java/io/github/artemget/tagrelease/exception/TagException.java b/src/main/java/io/github/artemget/tagrelease/exception/DomainException.java
similarity index 84%
rename from src/main/java/io/github/artemget/tagrelease/exception/TagException.java
rename to src/main/java/io/github/artemget/tagrelease/exception/DomainException.java
index 56d0123..0847524 100644
--- a/src/main/java/io/github/artemget/tagrelease/exception/TagException.java
+++ b/src/main/java/io/github/artemget/tagrelease/exception/DomainException.java
@@ -27,23 +27,23 @@
import java.io.Serial;
/**
- * Throws at build/get tag.
+ * Throws at domain logic error.
*
* @since 0.1.0
*/
-public class TagException extends Exception {
+public class DomainException extends Exception {
@Serial
private static final long serialVersionUID = 4172661814037122452L;
- public TagException(final String message) {
+ public DomainException(final String message) {
super(message);
}
- public TagException(final String message, final Throwable cause) {
+ public DomainException(final String message, final Throwable cause) {
super(message, cause);
}
- public TagException(final Throwable cause) {
+ public DomainException(final Throwable cause) {
super(cause);
}
}
diff --git a/src/main/java/io/github/artemget/tagrelease/match/MatchAdmin.java b/src/main/java/io/github/artemget/tagrelease/match/MatchAdmin.java
index 2eae29d..d05f98d 100644
--- a/src/main/java/io/github/artemget/tagrelease/match/MatchAdmin.java
+++ b/src/main/java/io/github/artemget/tagrelease/match/MatchAdmin.java
@@ -28,7 +28,7 @@
import io.github.artemget.entrys.EntryException;
import io.github.artemget.entrys.EntryExceptionUnchecked;
import io.github.artemget.teleroute.update.Wrap;
-import java.util.Set;
+import java.util.List;
import java.util.function.Predicate;
import org.telegram.telegrambots.meta.api.objects.Update;
@@ -41,14 +41,14 @@ public final class MatchAdmin implements Predicate> {
/**
* Admin ids.
*/
- private final Entry> admins;
+ private final Entry> admins;
/**
* Main ctor.
*
* @param admins Of bot.
*/
- public MatchAdmin(final Entry> admins) {
+ public MatchAdmin(final Entry> admins) {
this.admins = admins;
}
diff --git a/src/main/java/io/github/artemget/tagrelease/match/MatchChats.java b/src/main/java/io/github/artemget/tagrelease/match/MatchChats.java
index 4684eb1..d167122 100644
--- a/src/main/java/io/github/artemget/tagrelease/match/MatchChats.java
+++ b/src/main/java/io/github/artemget/tagrelease/match/MatchChats.java
@@ -28,7 +28,7 @@
import io.github.artemget.entrys.EntryException;
import io.github.artemget.entrys.EntryExceptionUnchecked;
import io.github.artemget.teleroute.update.Wrap;
-import java.util.Set;
+import java.util.List;
import java.util.function.Predicate;
import org.telegram.telegrambots.meta.api.objects.Update;
@@ -41,14 +41,14 @@ public final class MatchChats implements Predicate> {
/**
* Chat ids.
*/
- private final Entry> chats;
+ private final Entry> chats;
/**
* Main ctor.
*
* @param chats Where bot is used.
*/
- public MatchChats(final Entry> chats) {
+ public MatchChats(final Entry> chats) {
this.chats = chats;
}
diff --git a/src/main/java/io/github/artemget/tagrelease/domain/StandsGitlab.java b/src/main/java/io/github/artemget/tagrelease/match/MatchReply.java
similarity index 76%
rename from src/main/java/io/github/artemget/tagrelease/domain/StandsGitlab.java
rename to src/main/java/io/github/artemget/tagrelease/match/MatchReply.java
index e5fd2ec..13948c1 100644
--- a/src/main/java/io/github/artemget/tagrelease/domain/StandsGitlab.java
+++ b/src/main/java/io/github/artemget/tagrelease/match/MatchReply.java
@@ -22,23 +22,14 @@
* SOFTWARE.
*/
-package io.github.artemget.tagrelease.domain;
-
-import java.util.List;
-
-/**
- * Servers.
- *
- * @since 0.1.0
- */
-public final class StandsGitlab implements Stands {
- @Override
- public List stands() {
- throw new UnsupportedOperationException();
- }
+package io.github.artemget.tagrelease.match;
+import io.github.artemget.teleroute.update.Wrap;
+import java.util.function.Predicate;
+import org.telegram.telegrambots.meta.api.objects.Update;
+public class MatchReply implements Predicate> {
@Override
- public Stand stand(final String name) {
- throw new UnsupportedOperationException();
+ public boolean test(Wrap wrap) {
+ return wrap.src().getMessage().getReplyToMessage() != null;
}
}
diff --git a/src/main/resources/application.yaml b/src/main/resources/application.yaml
new file mode 100644
index 0000000..5d3ba01
--- /dev/null
+++ b/src/main/resources/application.yaml
@@ -0,0 +1,25 @@
+#Telegram bot settings
+bot:
+ #Bot name. Provided by botfather.
+ name: ${BOT_NAME}
+ #Bot token. Provided by botfather.
+ #Example: 1234567890:AAxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+ token: ${BOT_TOKEN}
+ #Users that could use bot. Array of userid in format id_1;id_2;id3.
+ #Example: -123;-234;-345
+ admins: ${BOT_ADMINS}
+#Source code management settings
+provider:
+ #SCM auth token to make requests. Must have permission to read all project's repos(tags,pull-requests,commits etc),
+ #create tags and push commits to ci/cd repo.
+ #Example:glpat-xxxxxxxxxxxxxxxxxxxx
+ token: ${PROVIDER_TOKEN}
+ #SCM host, with protocol. Only http:// is supported for now.
+ #Example:http://gitlab.blabla123.dev.ts/
+ host: ${PROVIDER_HOST}
+ #ID of project in which all repos is placed. Int value.
+ #Example: 123
+ project: ${PROJECT_ID}
+ #ID of repo where all stands are placed.
+ #Example: 123
+ release: ${RELEASE_ID}
diff --git a/src/test/java/io/github/artemget/tagrelease/domain/TagsGlTest.java b/src/test/java/io/github/artemget/tagrelease/domain/TagsGlTest.java
new file mode 100644
index 0000000..d6ecad8
--- /dev/null
+++ b/src/test/java/io/github/artemget/tagrelease/domain/TagsGlTest.java
@@ -0,0 +1,111 @@
+/*
+ * MIT License
+ *
+ * Copyright (c) 2024-2025. Artem Getmanskii
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+package io.github.artemget.tagrelease.domain;
+
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Test;
+
+class TagsGlTest {
+
+ @Test
+ void returnsLastIncremented() {
+ Assertions.assertEquals(
+ "4.3.1.1",
+ TagsGl.next("4.3.1.0", "4.3.1.*")
+ );
+ }
+
+ @Test
+ void returnsLastIncrementedWithStarting() {
+ Assertions.assertEquals(
+ "v4.3.1.1",
+ TagsGl.next("v4.3.1.0", "v4.3.1.*")
+ );
+ }
+
+ @Test
+ void returnsLastIncrementedWithVersionAndTrailingText() {
+ Assertions.assertEquals(
+ "v4.3.1.1_bla_bla",
+ TagsGl.next("v4.3.1.0_bla_bla", "v4.3.1.*")
+ );
+ }
+
+ @Test
+ void returnsLastIncrementedOverPlaceNumber() {
+ Assertions.assertEquals(
+ "4.3.1.11",
+ TagsGl.next("4.3.1.10", "4.3.1.*")
+ );
+ }
+
+ @Test
+ void returnsThirdIncremented() {
+ Assertions.assertEquals(
+ "4.3.2.0",
+ TagsGl.next("4.3.1.0", "4.3.*")
+ );
+ }
+
+ @Test
+ void returnsThirdIncrementedOverPlaceNumber() {
+ Assertions.assertEquals(
+ "4.3.11.0",
+ TagsGl.next("4.3.10.0", "4.3.*")
+ );
+ }
+
+ @Test
+ void returnsSecondIncremented() {
+ Assertions.assertEquals(
+ "4.4.0.0",
+ TagsGl.next("4.3.1.0", "4.*")
+ );
+ }
+
+ @Test
+ void returnsFirstIncremented() {
+ Assertions.assertEquals(
+ "5.0.0.0",
+ TagsGl.next("4.3.1.0", "*")
+ );
+ }
+
+ @Test
+ void returnsFirstIncrementedOver() {
+ Assertions.assertEquals(
+ "10.0.0.0",
+ TagsGl.next("9.3.1.0", "*")
+ );
+ }
+
+ @Test
+ void returnsFirstIncrementedOverPlaceNumber() {
+ Assertions.assertEquals(
+ "11.0.0.0",
+ TagsGl.next("10.3.1.0", "*")
+ );
+ }
+}