summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSho Sakuma <me@m1sk9.dev>2026-03-26 08:39:51 +0900
committerGitHub <noreply@github.com>2026-03-26 08:39:51 +0900
commita9c776933f2a53635260da592a49abc8ccf1c73c (patch)
tree240aee3517ed9dc2308f748e7b38bb00860bac0f
parent217b8b38a757db04babd645e39f2c9e1846b40f0 (diff)
parentb4ad3086eaaa5280855816a5dd6ed37b939a4659 (diff)
downloadLunaticChat-a9c776933f2a53635260da592a49abc8ccf1c73c.tar.gz
LunaticChat-a9c776933f2a53635260da592a49abc8ccf1c73c.tar.bz2
LunaticChat-a9c776933f2a53635260da592a49abc8ccf1c73c.zip
Merge pull request #154 from m1sk9/ci/support-nightly-release
ci: Support nightly release
-rw-r--r--.github/workflows/nightly.yaml112
-rw-r--r--.github/workflows/release.yaml28
-rw-r--r--.gitignore1
-rw-r--r--CHANGELOG.md17
-rw-r--r--build.gradle.kts2
-rw-r--r--codecov.yml8
-rw-r--r--docker/paper/compose.yaml47
-rw-r--r--platform-paper/build.gradle.kts8
-rw-r--r--platform-paper/src/main/kotlin/dev/m1sk9/lunaticChat/paper/BuildInfo.kt4
-rw-r--r--platform-paper/src/main/kotlin/dev/m1sk9/lunaticChat/paper/command/impl/lc/StatusCommand.kt18
-rw-r--r--platform-paper/src/main/kotlin/dev/m1sk9/lunaticChat/paper/command/impl/lcv/VelocityStatusCommand.kt11
-rw-r--r--platform-paper/src/main/kotlin/dev/m1sk9/lunaticChat/paper/listener/PlayerChatListener.kt2
-rw-r--r--platform-paper/src/main/kotlin/dev/m1sk9/lunaticChat/paper/listener/PlayerPresenceListener.kt21
-rw-r--r--platform-paper/src/main/resources/build-info.properties1
-rw-r--r--platform-paper/src/main/resources/languages/en.yml6
-rw-r--r--platform-paper/src/main/resources/languages/ja.yml6
-rw-r--r--platform-paper/src/test/kotlin/dev/m1sk9/lunaticChat/paper/command/impl/lc/StatusCommandTest.kt39
-rw-r--r--platform-velocity/build.gradle.kts20
-rw-r--r--platform-velocity/src/main/kotlin/dev/m1sk9/lunaticChat/velocity/BuildInfo.kt23
-rw-r--r--platform-velocity/src/main/resources/build-info.properties3
-rwxr-xr-xx234
21 files changed, 496 insertions, 115 deletions
diff --git a/.github/workflows/nightly.yaml b/.github/workflows/nightly.yaml
new file mode 100644
index 0000000..6a162a2
--- /dev/null
+++ b/.github/workflows/nightly.yaml
@@ -0,0 +1,112 @@
+name: Nightly Release
+
+on:
+ push:
+ branches:
+ - main
+ paths-ignore:
+ - 'docs/**'
+ - '*.md'
+ - 'LICENSE'
+
+concurrency:
+ group: nightly-release
+ cancel-in-progress: true
+
+jobs:
+ build:
+ runs-on: ubuntu-24.04
+ outputs:
+ version: ${{ steps.version.outputs.version }}
+ paper_jar_name: ${{ steps.version.outputs.paper_jar_name }}
+ velocity_jar_name: ${{ steps.version.outputs.velocity_jar_name }}
+ steps:
+ - name: Checkout repository
+ uses: actions/checkout@v6
+
+ - name: Compute nightly version
+ id: version
+ run: |
+ BASE_VERSION=$(grep ' version = ' build.gradle.kts | sed 's/.*version = "\(.*\)"/\1/' | sed "s/findProperty.*?: \"\(.*\)\"/\1/")
+ # Fallback: extract version from the default value
+ if [ -z "$BASE_VERSION" ] || echo "$BASE_VERSION" | grep -q 'findProperty'; then
+ BASE_VERSION="1.0.0"
+ fi
+ SHORT_HASH=$(git rev-parse --short HEAD)
+ NIGHTLY_VERSION="${BASE_VERSION}-nightly.${SHORT_HASH}"
+ echo "version=$NIGHTLY_VERSION" >> $GITHUB_OUTPUT
+ echo "paper_jar_name=LunaticChat-${NIGHTLY_VERSION}.jar" >> $GITHUB_OUTPUT
+ echo "velocity_jar_name=LunaticChat-${NIGHTLY_VERSION}-velocity.jar" >> $GITHUB_OUTPUT
+ echo "Nightly version: $NIGHTLY_VERSION"
+
+ - name: Setup Development Environment
+ uses: jdx/mise-action@v3
+
+ - name: Setup Gradle
+ uses: gradle/actions/setup-gradle@v5
+
+ - name: Grant execute permission for gradlew
+ run: chmod +x gradlew
+
+ - name: Build with shadowJar
+ run: |
+ ./gradlew :platform-paper:shadowJar :platform-velocity:shadowJar \
+ -Pversion=${{ steps.version.outputs.version }} \
+ -PisNightly=true \
+ --parallel --no-daemon
+
+ - name: Upload build artifacts
+ uses: actions/upload-artifact@v7
+ with:
+ name: LunaticChat-nightly-${{ steps.version.outputs.version }}
+ path: |
+ platform-paper/build/libs/${{ steps.version.outputs.paper_jar_name }}
+ platform-velocity/build/libs/${{ steps.version.outputs.velocity_jar_name }}
+ retention-days: 7
+
+ release:
+ runs-on: ubuntu-24.04
+ needs: build
+ permissions:
+ contents: write
+ steps:
+ - name: Checkout repository
+ uses: actions/checkout@v6
+
+ - name: Download build artifact
+ uses: actions/download-artifact@v8
+ with:
+ name: LunaticChat-nightly-${{ needs.build.outputs.version }}
+
+ - name: Delete existing nightly release
+ env:
+ GH_TOKEN: ${{ github.token }}
+ run: |
+ gh release delete nightly --yes --cleanup-tag 2>/dev/null || true
+
+ - name: Create nightly release
+ env:
+ GH_TOKEN: ${{ github.token }}
+ run: |
+ VERSION=${{ needs.build.outputs.version }}
+ PAPER_JAR_NAME=${{ needs.build.outputs.paper_jar_name }}
+ VELOCITY_JAR_NAME=${{ needs.build.outputs.velocity_jar_name }}
+
+ gh release create nightly \
+ "platform-paper/build/libs/$PAPER_JAR_NAME" \
+ "platform-velocity/build/libs/$VELOCITY_JAR_NAME" \
+ --title "Nightly Build ($VERSION)" \
+ --prerelease \
+ --notes "$(cat <<'EOF'
+ ## ⚠️ Nightly Build
+
+ This is an automatically generated nightly build from the latest `main` branch.
+
+ **Warning:** This build may be unstable or contain bugs. Do not use in production environments.
+
+ - **Version:** `${{ needs.build.outputs.version }}`
+ - **Commit:** ${{ github.sha }}
+
+ If you encounter any issues, please report them on [GitHub Issues](https://github.com/m1sk9/LunaticChat/issues).
+ EOF
+ )"
diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml
index e40f4b2..f0da20c 100644
--- a/.github/workflows/release.yaml
+++ b/.github/workflows/release.yaml
@@ -81,7 +81,7 @@ jobs:
permissions:
contents: write
env:
- MODRINTH_CHANNEL: beta
+ MODRINTH_CHANNEL: release
MODRINTH_GAME_VERSIONS: "1.21.x"
MODRINTH_MC_VERSION: "1.21.11"
steps:
@@ -106,12 +106,36 @@ jobs:
PAPER_JAR_NAME=${{ needs.validate.outputs.paper_jar_name }}
VELOCITY_JAR_NAME=${{ needs.validate.outputs.velocity_jar_name }}
+ cat > /tmp/release-notes.md <<EOF
+ LunaticChat v${VERSION} has been released.
+
+ ## Download
+
+ - [GitHub](https://github.com/m1sk9/LunaticChat/releases/tag/v${VERSION})
+ - Modrinth: [Paper/Folia](https://modrinth.com/plugin/lunaticchat/version/${VERSION}), [Velocity](https://modrinth.com/plugin/lunaticchat/version/${VERSION}-velocity)
+
+ ## What's new
+
+ ### Highlights
+
+ ### New Features
+
+ ### Improvements
+
+ ### Changes
+
+ ### Bug Fixes
+
+ ### Notes
+
+ EOF
+
gh release create "$TAG_NAME" \
"platform-paper/build/libs/$PAPER_JAR_NAME" \
"platform-velocity/build/libs/$VELOCITY_JAR_NAME" \
--title "$TAG_NAME" \
--draft \
- --notes ""
+ --notes-file /tmp/release-notes.md
- name: Publish to Modrinth (Paper/Folia)
uses: cloudnode-pro/modrinth-publish@0be4916ad5f081d936eb5615aa35ce3f0949979c # v2
diff --git a/.gitignore b/.gitignore
index 729de3c..dc37cdd 100644
--- a/.gitignore
+++ b/.gitignore
@@ -23,3 +23,4 @@ gradle-app.setting
.idea/
docs/.vitepress/cache/deps
+/docker/paper/plugins
diff --git a/CHANGELOG.md b/CHANGELOG.md
index ec0507c..6f7753e 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -2,14 +2,23 @@
## v1
-### v1.0.0 (Unreleased)
+### v1.0.0
-#### Features
+#### Announcement: Support for Nightly Releases
+
+- We have started distributing Nightly releases
+ - Whenever updates are made to `main` (the default branch), we will distribute the current build via GitHub Releases
+ - Since the Nightly version is a work-in-progress, it may be unstable or contain bugs. If you encounter any issues, please report them on GitHub Issues
+
+> [!WARNING]
+>
+> The Nightly version is not available on Modrinth
+
+#### New Features
- Paper 26.1 (Minecraft 26.1) is now supported.
- Support for Paper 1.21.X, Folia 1.21.X (and later) has been dropped.
-
-## v0
+- We have added warnings when running `/lc status` or `/lcv status`, or when logging in, if you are using the Nightly version.
### v0.11.0
diff --git a/build.gradle.kts b/build.gradle.kts
index 9bda715..ee27d45 100644
--- a/build.gradle.kts
+++ b/build.gradle.kts
@@ -14,7 +14,7 @@ plugins {
allprojects {
group = "dev.m1sk9"
- version = "0.11.0"
+ version = findProperty("version")?.toString()?.takeIf { it != "unspecified" } ?: "1.0.0"
repositories {
mavenCentral()
diff --git a/codecov.yml b/codecov.yml
index 9bc314e..e23de4b 100644
--- a/codecov.yml
+++ b/codecov.yml
@@ -16,3 +16,11 @@ ignore:
# Listener classes are tightly coupled to the Paper/Minecraft runtime and exercised via
# end-to-end/server tests, so we exclude them from unit-test coverage metrics.
- "platform-paper/src/main/kotlin/dev/m1sk9/lunaticChat/paper/listener/**"
+ # BuildInfo loads build-time resources at class init and is verified via integration tests.
+ - "platform-paper/src/main/kotlin/dev/m1sk9/lunaticChat/paper/BuildInfo.kt"
+ # VelocityStatusCommand is tightly coupled to VelocityConnectionManager and has no unit-test
+ # infrastructure; it is exercised via end-to-end multi-server tests.
+ - "platform-paper/src/main/kotlin/dev/m1sk9/lunaticChat/paper/command/impl/lcv/VelocityStatusCommand.kt"
+ # The Velocity platform has no unit-test infrastructure; it is exercised via end-to-end
+ # multi-server tests (docker compose).
+ - "platform-velocity/src/main/kotlin/**"
diff --git a/docker/paper/compose.yaml b/docker/paper/compose.yaml
new file mode 100644
index 0000000..5e171eb
--- /dev/null
+++ b/docker/paper/compose.yaml
@@ -0,0 +1,47 @@
+services:
+ paper:
+ image: itzg/minecraft-server:java21
+ container_name: debug-paper
+ ports:
+ - "25565:25565"
+ - "25575:25575"
+ volumes:
+ - lunatic-debug-paper-data:/data
+ - ./plugins:/data/plugins
+ - ../velocity/bukkit.yml:/data/bukkit.yml
+ environment:
+ EULA: "TRUE"
+ TYPE: "PAPER"
+ VERSION: "1.21.11"
+ MEMORY: "1G"
+
+ # デバッグ用高速化設定
+ LEVEL_TYPE: "flat"
+ VIEW_DISTANCE: "3"
+ SIMULATION_DISTANCE: "3"
+ GENERATE_STRUCTURES: "false"
+ SPAWN_PROTECTION: "0"
+ ALLOW_NETHER: "false"
+
+ # 権限関連
+ OVERRIDE_SERVER_PROPERTIES: "true"
+
+ ENABLE_RCON: "true"
+ RCON_PASSWORD: "minecraft"
+ RCON_PORT: 25575
+
+ DIFFICULTY: "peaceful"
+ MAX_PLAYERS: "3"
+ ONLINE_MODE: "false"
+ SYNC_SKIP_NEWER_IN_DESTINATION: "false"
+ healthcheck:
+ test: mc-health
+ start_period: 60s
+ interval: 10s
+ timeout: 5s
+ retries: 3
+ tty: true
+ stdin_open: true
+
+volumes:
+ lunatic-debug-paper-data:
diff --git a/platform-paper/build.gradle.kts b/platform-paper/build.gradle.kts
index 0647a1d..b6d452e 100644
--- a/platform-paper/build.gradle.kts
+++ b/platform-paper/build.gradle.kts
@@ -51,7 +51,13 @@ tasks {
.get()
.trim()
- val props = mapOf("version" to project.version, "gitCommitHash" to gitCommitHash)
+ val isNightly = providers.gradleProperty("isNightly").orNull?.toBoolean() ?: false
+ val props =
+ mapOf(
+ "version" to project.version,
+ "gitCommitHash" to gitCommitHash,
+ "channel" to if (isNightly) "nightly" else "stable",
+ )
inputs.properties(props)
filteringCharset = "UTF-8"
filesMatching("paper-plugin.yml") {
diff --git a/platform-paper/src/main/kotlin/dev/m1sk9/lunaticChat/paper/BuildInfo.kt b/platform-paper/src/main/kotlin/dev/m1sk9/lunaticChat/paper/BuildInfo.kt
index 5609fe9..bac9107 100644
--- a/platform-paper/src/main/kotlin/dev/m1sk9/lunaticChat/paper/BuildInfo.kt
+++ b/platform-paper/src/main/kotlin/dev/m1sk9/lunaticChat/paper/BuildInfo.kt
@@ -5,6 +5,7 @@ import java.util.Properties
object BuildInfo {
val version: String
val commitHash: String
+ val channel: String
init {
val props = Properties()
@@ -13,7 +14,10 @@ object BuildInfo {
}
version = props.getProperty("version", "unknown")
commitHash = props.getProperty("commit", "unknown")
+ channel = props.getProperty("channel", "stable")
}
+ val isNightly: Boolean get() = channel == "nightly"
+
fun versionWithCommit(): String = "$version ($commitHash)"
}
diff --git a/platform-paper/src/main/kotlin/dev/m1sk9/lunaticChat/paper/command/impl/lc/StatusCommand.kt b/platform-paper/src/main/kotlin/dev/m1sk9/lunaticChat/paper/command/impl/lc/StatusCommand.kt
index 82dcd9f..6b6fd09 100644
--- a/platform-paper/src/main/kotlin/dev/m1sk9/lunaticChat/paper/command/impl/lc/StatusCommand.kt
+++ b/platform-paper/src/main/kotlin/dev/m1sk9/lunaticChat/paper/command/impl/lc/StatusCommand.kt
@@ -101,6 +101,16 @@ class StatusCommand(
sender.apply {
sendMessage(versionLine)
+
+ // Nightly warning
+ if (BuildInfo.isNightly) {
+ sendMessage(
+ MessageFormatter
+ .format(languageManager.getMessage("general.nightlyWarning"))
+ .color(NamedTextColor.YELLOW),
+ )
+ }
+
sendMessage(healthLine)
// --- Features ---
@@ -121,6 +131,14 @@ class StatusCommand(
)
sendMessage(getToggleLine(languageManager.getMessage("status.config.debug"), configuration.debug))
sendMessage(getToggleLine(languageManager.getMessage("status.config.checkForUpdates"), configuration.checkForUpdates))
+ val channelLabel = languageManager.getMessage("status.channel.${BuildInfo.channel}")
+ val channelColor = if (BuildInfo.isNightly) NamedTextColor.YELLOW else NamedTextColor.GREEN
+ sendMessage(
+ Component
+ .text(" • ", NamedTextColor.GRAY)
+ .append(Component.text("${languageManager.getMessage("status.releaseChannel")}: ", NamedTextColor.GRAY))
+ .append(Component.text(channelLabel, channelColor)),
+ )
sendMessage(
Component
.text(" • ", NamedTextColor.GRAY)
diff --git a/platform-paper/src/main/kotlin/dev/m1sk9/lunaticChat/paper/command/impl/lcv/VelocityStatusCommand.kt b/platform-paper/src/main/kotlin/dev/m1sk9/lunaticChat/paper/command/impl/lcv/VelocityStatusCommand.kt
index 6ebb4f4..439a29a 100644
--- a/platform-paper/src/main/kotlin/dev/m1sk9/lunaticChat/paper/command/impl/lcv/VelocityStatusCommand.kt
+++ b/platform-paper/src/main/kotlin/dev/m1sk9/lunaticChat/paper/command/impl/lcv/VelocityStatusCommand.kt
@@ -4,6 +4,7 @@ import com.mojang.brigadier.builder.LiteralArgumentBuilder
import dev.m1sk9.lunaticChat.engine.command.CommandResult
import dev.m1sk9.lunaticChat.engine.permission.LunaticChatPermissionNode
import dev.m1sk9.lunaticChat.engine.protocol.ProtocolVersion
+import dev.m1sk9.lunaticChat.paper.BuildInfo
import dev.m1sk9.lunaticChat.paper.LunaticChat
import dev.m1sk9.lunaticChat.paper.command.annotation.Command
import dev.m1sk9.lunaticChat.paper.command.annotation.Permission
@@ -138,6 +139,16 @@ class VelocityStatusCommand(
languageManager.getMessage("velocity.status.header"),
),
)
+
+ // Nightly warning
+ if (BuildInfo.isNightly) {
+ sendMessage(
+ MessageFormatter
+ .format(languageManager.getMessage("general.nightlyWarning"))
+ .color(NamedTextColor.YELLOW),
+ )
+ }
+
// Connection status details
connectionStatus.forEach { line ->
line?.let { sendMessage(it) }
diff --git a/platform-paper/src/main/kotlin/dev/m1sk9/lunaticChat/paper/listener/PlayerChatListener.kt b/platform-paper/src/main/kotlin/dev/m1sk9/lunaticChat/paper/listener/PlayerChatListener.kt
index 19b284b..3bd2d4a 100644
--- a/platform-paper/src/main/kotlin/dev/m1sk9/lunaticChat/paper/listener/PlayerChatListener.kt
+++ b/platform-paper/src/main/kotlin/dev/m1sk9/lunaticChat/paper/listener/PlayerChatListener.kt
@@ -85,7 +85,7 @@ class PlayerChatListener(
when {
hasActiveChannel && !hasPrefix -> {
// Channel chat: player is in a channel and no '!' prefix
- if (channelManager != null && channelMessageHandler != null) {
+ if (channelMessageHandler != null) {
event.isCancelled = true
event.viewers().clear()
event.message(Component.empty())
diff --git a/platform-paper/src/main/kotlin/dev/m1sk9/lunaticChat/paper/listener/PlayerPresenceListener.kt b/platform-paper/src/main/kotlin/dev/m1sk9/lunaticChat/paper/listener/PlayerPresenceListener.kt
index 56cbe59..fc79ffe 100644
--- a/platform-paper/src/main/kotlin/dev/m1sk9/lunaticChat/paper/listener/PlayerPresenceListener.kt
+++ b/platform-paper/src/main/kotlin/dev/m1sk9/lunaticChat/paper/listener/PlayerPresenceListener.kt
@@ -1,6 +1,7 @@
package dev.m1sk9.lunaticChat.paper.listener
import dev.m1sk9.lunaticChat.engine.permission.LunaticChatPermissionNode
+import dev.m1sk9.lunaticChat.paper.BuildInfo
import dev.m1sk9.lunaticChat.paper.LunaticChat
import dev.m1sk9.lunaticChat.paper.chat.channel.ChannelManager
import dev.m1sk9.lunaticChat.paper.common.hasAnyPermission
@@ -8,6 +9,7 @@ import dev.m1sk9.lunaticChat.paper.i18n.LanguageManager
import dev.m1sk9.lunaticChat.paper.i18n.MessageFormatter
import dev.m1sk9.lunaticChat.paper.settings.PlayerSettingsManager
import net.kyori.adventure.text.event.ClickEvent
+import net.kyori.adventure.text.format.NamedTextColor
import org.bukkit.event.EventHandler
import org.bukkit.event.Listener
import org.bukkit.event.player.PlayerJoinEvent
@@ -39,6 +41,25 @@ class PlayerPresenceListener(
}, 3, TimeUnit.SECONDS)
}
+ // Nightly build warning
+ if (BuildInfo.isNightly) {
+ lunaticChat.server.asyncScheduler.runDelayed(lunaticChat, { _ ->
+ if (player.isOnline) {
+ player.sendMessage(
+ MessageFormatter
+ .format(languageManager.getMessage("general.nightlyWarning"))
+ .color(NamedTextColor.YELLOW),
+ )
+ player.sendMessage(
+ MessageFormatter
+ .format(languageManager.getMessage("general.nightlyReportIssue"))
+ .clickEvent(ClickEvent.openUrl("https://github.com/m1sk9/LunaticChat/issues"))
+ .color(NamedTextColor.YELLOW),
+ )
+ }
+ }, 6, TimeUnit.SECONDS)
+ }
+
// Restore active channel from membership and notify (delayed to avoid being buried by other plugins' join messages)
channelManager?.let { manager ->
val context = manager.restorePlayerChannel(player.uniqueId)
diff --git a/platform-paper/src/main/resources/build-info.properties b/platform-paper/src/main/resources/build-info.properties
index f093468..1f8dbc2 100644
--- a/platform-paper/src/main/resources/build-info.properties
+++ b/platform-paper/src/main/resources/build-info.properties
@@ -1,2 +1,3 @@
version=${version}
commit=${gitCommitHash}
+channel=${channel}
diff --git a/platform-paper/src/main/resources/languages/en.yml b/platform-paper/src/main/resources/languages/en.yml
index 04ca56a..7db632f 100644
--- a/platform-paper/src/main/resources/languages/en.yml
+++ b/platform-paper/src/main/resources/languages/en.yml
@@ -56,6 +56,10 @@ status:
ok: "OK"
degraded: "Degraded"
degradedHover: "Velocity integration is enabled but the connection failed. Use /lcv status for details."
+ releaseChannel: "Release Channel"
+ channel:
+ stable: "Stable"
+ nightly: "Nightly"
settings:
availableValues: "Available settings value: {values}"
@@ -200,6 +204,8 @@ general:
newUpdateAvailable: "The new version of LunaticChat is now available! You can download it from GitHub or Modrinth."
noPermission: "You do not have permission to execute this command."
spyMessage: "You have been granted permission, so this message is displayed in spy mode."
+ nightlyWarning: "You are running a nightly build of LunaticChat. This build may be unstable or contain bugs."
+ nightlyReportIssue: "If you encounter any issues, please report them on GitHub Issues."
toggle:
off: "Disabled"
diff --git a/platform-paper/src/main/resources/languages/ja.yml b/platform-paper/src/main/resources/languages/ja.yml
index 74f2dfb..9a472b9 100644
--- a/platform-paper/src/main/resources/languages/ja.yml
+++ b/platform-paper/src/main/resources/languages/ja.yml
@@ -56,6 +56,10 @@ status:
ok: "正常"
degraded: "問題あり"
degradedHover: "Velocity 連携が有効ですが接続に失敗しました。/lcv status を確認してください。"
+ releaseChannel: "リリースチャンネル"
+ channel:
+ stable: "安定版"
+ nightly: "ナイトリー"
settings:
availableValues: "使用可能な設定値: {values}"
@@ -200,6 +204,8 @@ general:
newUpdateAvailable: "LunaticChat の新しいバージョンが利用可能です。GitHubまたはModrinthからダウンロードできます"
noPermission: "このコマンドを実行する権限がありません"
spyMessage: "あなたに権限が付与されているため、このメッセージはスパイ状態で表示されています"
+ nightlyWarning: "LunaticChat のナイトリービルドを使用しています。このビルドは不安定であったり、バグが含まれている可能性があります。"
+ nightlyReportIssue: "問題を発見した場合は、GitHub Issues で報告してください。"
toggle:
on: "有効"
diff --git a/platform-paper/src/test/kotlin/dev/m1sk9/lunaticChat/paper/command/impl/lc/StatusCommandTest.kt b/platform-paper/src/test/kotlin/dev/m1sk9/lunaticChat/paper/command/impl/lc/StatusCommandTest.kt
index 95c8b92..63cf908 100644
--- a/platform-paper/src/test/kotlin/dev/m1sk9/lunaticChat/paper/command/impl/lc/StatusCommandTest.kt
+++ b/platform-paper/src/test/kotlin/dev/m1sk9/lunaticChat/paper/command/impl/lc/StatusCommandTest.kt
@@ -45,13 +45,25 @@ class StatusCommandTest {
val mockPlayer: org.bukkit.entity.Player,
)
+ private fun mockBuildInfoStable() {
+ every { BuildInfo.versionWithCommit() } returns "0.10.0-test"
+ every { BuildInfo.isNightly } returns false
+ every { BuildInfo.channel } returns "stable"
+ }
+
+ private fun mockBuildInfoNightly() {
+ every { BuildInfo.versionWithCommit() } returns "0.10.0-nightly.1-test"
+ every { BuildInfo.isNightly } returns true
+ every { BuildInfo.channel } returns "nightly"
+ }
+
@Test
fun `execute should return Success`() {
val deps = createDependencies()
mockkObject(BuildInfo)
try {
- every { BuildInfo.versionWithCommit() } returns "0.10.0-test"
+ mockBuildInfoStable()
val result = deps.command.execute(deps.ctx)
@@ -67,7 +79,7 @@ class StatusCommandTest {
mockkObject(BuildInfo)
try {
- every { BuildInfo.versionWithCommit() } returns "0.10.0-test"
+ mockBuildInfoStable()
deps.command.execute(deps.ctx)
@@ -96,7 +108,7 @@ class StatusCommandTest {
mockkObject(BuildInfo)
try {
- every { BuildInfo.versionWithCommit() } returns "0.10.0-test"
+ mockBuildInfoStable()
val result = deps.command.execute(deps.ctx)
@@ -112,7 +124,7 @@ class StatusCommandTest {
mockkObject(BuildInfo)
try {
- every { BuildInfo.versionWithCommit() } returns "0.10.0-test"
+ mockBuildInfoStable()
deps.command.execute(deps.ctx)
@@ -122,4 +134,23 @@ class StatusCommandTest {
unmockkObject(BuildInfo)
}
}
+
+ @Test
+ fun `execute with nightly build should display nightly warning and channel`() {
+ val deps = createDependencies()
+
+ mockkObject(BuildInfo)
+ try {
+ mockBuildInfoNightly()
+
+ val result = deps.command.execute(deps.ctx)
+
+ assertIs<CommandResult.Success>(result)
+ // Nightly warning + version + health + features header + 4 features + config header +
+ // debug + checkForUpdates + releaseChannel + language + 3 links = at least 15 messages
+ verify(atLeast = 15) { deps.mockPlayer.sendMessage(any<Component>()) }
+ } finally {
+ unmockkObject(BuildInfo)
+ }
+ }
}
diff --git a/platform-velocity/build.gradle.kts b/platform-velocity/build.gradle.kts
index cc8af58..f6a4e57 100644
--- a/platform-velocity/build.gradle.kts
+++ b/platform-velocity/build.gradle.kts
@@ -36,12 +36,30 @@ tasks {
}
processResources {
- val props = mapOf("version" to project.version)
+ val gitCommitHash =
+ providers
+ .exec {
+ commandLine("git", "rev-parse", "--short", "HEAD")
+ }.standardOutput
+ .asText
+ .get()
+ .trim()
+
+ val isNightly = providers.gradleProperty("isNightly").orNull?.toBoolean() ?: false
+ val props =
+ mapOf(
+ "version" to project.version,
+ "gitCommitHash" to gitCommitHash,
+ "channel" to if (isNightly) "nightly" else "stable",
+ )
inputs.properties(props)
filteringCharset = "UTF-8"
filesMatching("velocity-plugin.json") {
expand(props)
}
+ filesMatching("build-info.properties") {
+ expand(props)
+ }
}
build {
diff --git a/platform-velocity/src/main/kotlin/dev/m1sk9/lunaticChat/velocity/BuildInfo.kt b/platform-velocity/src/main/kotlin/dev/m1sk9/lunaticChat/velocity/BuildInfo.kt
new file mode 100644
index 0000000..1cb13d4
--- /dev/null
+++ b/platform-velocity/src/main/kotlin/dev/m1sk9/lunaticChat/velocity/BuildInfo.kt
@@ -0,0 +1,23 @@
+package dev.m1sk9.lunaticChat.velocity
+
+import java.util.Properties
+
+object BuildInfo {
+ val version: String
+ val commitHash: String
+ val channel: String
+
+ init {
+ val props = Properties()
+ BuildInfo::class.java.getResourceAsStream("/build-info.properties")?.use {
+ props.load(it)
+ }
+ version = props.getProperty("version", "unknown")
+ commitHash = props.getProperty("commit", "unknown")
+ channel = props.getProperty("channel", "stable")
+ }
+
+ val isNightly: Boolean get() = channel == "nightly"
+
+ fun versionWithCommit(): String = "$version ($commitHash)"
+}
diff --git a/platform-velocity/src/main/resources/build-info.properties b/platform-velocity/src/main/resources/build-info.properties
new file mode 100644
index 0000000..1f8dbc2
--- /dev/null
+++ b/platform-velocity/src/main/resources/build-info.properties
@@ -0,0 +1,3 @@
+version=${version}
+commit=${gitCommitHash}
+channel=${channel}
diff --git a/x b/x
index a52964c..aa9a210 100755
--- a/x
+++ b/x
@@ -2,70 +2,107 @@
set -e
+DC_PAPER="docker compose -f docker/paper/compose.yaml"
DC_VELOCITY="docker compose -f docker/velocity/compose.yaml"
DC_FOLIA="docker compose -f docker/folia/compose.yaml"
+GRADLE_EXTRA_ARGS=""
+
help() {
cat <<EOF
-Usage: ./x <command> [options]
-
-Velocity environment (Paper s1 + s2 + Velocity proxy):
- start Build Paper+Velocity and start all containers
- start-s1 Build Paper and start only s1 container
- restart Restart s1, s2 and velocity containers
- stop Stop velocity environment
- clean Stop velocity environment and remove volumes
- rcon [server] Open rcon-cli for server container (default: s1)
- Available servers: s1, s2
- logs [server] Show server container logs (default: s1)
- Available servers: s1, s2
- vlogs Show velocity proxy container logs
-
-Folia environment (single Folia server):
- folia start Build Paper and start Folia server
- folia restart Restart Folia server
- folia stop Stop Folia server
- folia clean Stop Folia server and remove volumes
- folia rcon Open rcon-cli for Folia server
- folia logs Show Folia server logs
-
-General:
- help Show this help message
+Usage: ./x <action> <platform> [--stable]
+
+Actions:
+ start Build and start containers
+ stop Stop containers
+ log Show container logs
+ clean Stop containers and remove volumes
+ rcon Open rcon-cli console (velocity: ./x rcon velocity [s1|s2])
+ help Show this help message
+
+Platforms:
+ paper Single Paper server (localhost:25565)
+ velocity Velocity proxy + Paper s1 & s2 (localhost:25577)
+ folia Single Folia server (localhost:25565)
+
+Options:
+ --stable Build as stable release (default: nightly)
+
+Examples:
+ ./x start paper Build nightly and start Paper server
+ ./x start velocity Build nightly and start Velocity environment
+ ./x start folia Build nightly and start Folia server
+ ./x start paper --stable Build stable and start Paper server
+ ./x log velocity Show Velocity environment logs
+ ./x rcon paper Open rcon-cli for Paper server
+ ./x stop velocity Stop Velocity environment
+ ./x clean folia Stop Folia and remove volumes
EOF
}
+setup_nightly() {
+ SHORT_HASH=$(git rev-parse --short HEAD)
+ GRADLE_EXTRA_ARGS="-Pversion=1.0.0-nightly.${SHORT_HASH} -PisNightly=true"
+ echo "==> Nightly build: 1.0.0-nightly.${SHORT_HASH}"
+}
+
ensure_plugin_dir() {
mkdir -p "$1"
}
-# --- Folia commands ---
-folia_cmd() {
- case "${1:-}" in
- start)
- ./gradlew :platform-paper:clean :platform-paper:shadowJar
+# Parse --stable flag (only setup build for actions that need it)
+ACTION="${1:-}"
+PLATFORM="${2:-}"
+
+if [[ "$ACTION" == "start" ]]; then
+ STABLE=false
+ for arg in "$@"; do
+ if [[ "$arg" == "--stable" ]]; then
+ STABLE=true
+ fi
+ done
+
+ if [[ "$STABLE" == "false" ]]; then
+ setup_nightly
+ else
+ echo "==> Stable build"
+ fi
+fi
+
+# --- Actions per platform ---
+
+do_start() {
+ case "$1" in
+ paper)
+ ./gradlew :platform-paper:clean :platform-paper:shadowJar $GRADLE_EXTRA_ARGS
+ ensure_plugin_dir docker/paper/plugins
+ rm -f docker/paper/plugins/*.jar
+ cp platform-paper/build/libs/*.jar docker/paper/plugins/
+ $DC_PAPER up
+ ;;
+ velocity)
+ ./gradlew :platform-paper:clean :platform-paper:shadowJar :platform-velocity:clean :platform-velocity:shadowJar $GRADLE_EXTRA_ARGS
+ ensure_plugin_dir docker/velocity/plugins-paper-s1
+ ensure_plugin_dir docker/velocity/plugins-paper-s2
+ ensure_plugin_dir docker/velocity/plugins-velocity
+ rm -f docker/velocity/plugins-paper-s1/*.jar
+ rm -f docker/velocity/plugins-paper-s2/*.jar
+ rm -f docker/velocity/plugins-velocity/*.jar
+ cp platform-paper/build/libs/*.jar docker/velocity/plugins-paper-s1/
+ cp platform-paper/build/libs/*.jar docker/velocity/plugins-paper-s2/
+ cp platform-velocity/build/libs/*.jar docker/velocity/plugins-velocity/
+ $DC_VELOCITY up
+ ;;
+ folia)
+ ./gradlew :platform-paper:clean :platform-paper:shadowJar $GRADLE_EXTRA_ARGS
ensure_plugin_dir docker/folia/plugins
rm -f docker/folia/plugins/*.jar
cp platform-paper/build/libs/*.jar docker/folia/plugins/
$DC_FOLIA up
;;
- restart)
- $DC_FOLIA restart folia
- ;;
- stop)
- $DC_FOLIA down
- ;;
- clean)
- $DC_FOLIA down -v
- ;;
- rcon)
- $DC_FOLIA exec folia rcon-cli
- ;;
- logs)
- $DC_FOLIA logs -f folia
- ;;
*)
- echo "Unknown folia command: ${1:-}"
+ echo "Unknown platform: ${1:-}"
echo ""
help
exit 1
@@ -73,64 +110,59 @@ folia_cmd() {
esac
}
+do_stop() {
+ case "$1" in
+ paper) $DC_PAPER down ;;
+ velocity) $DC_VELOCITY down ;;
+ folia) $DC_FOLIA down ;;
+ *) echo "Unknown platform: ${1:-}"; exit 1 ;;
+ esac
+}
+
+do_log() {
+ case "$1" in
+ paper) $DC_PAPER logs -f paper ;;
+ velocity) $DC_VELOCITY logs -f ;;
+ folia) $DC_FOLIA logs -f folia ;;
+ *) echo "Unknown platform: ${1:-}"; exit 1 ;;
+ esac
+}
+
+do_clean() {
+ case "$1" in
+ paper) $DC_PAPER down -v ;;
+ velocity) $DC_VELOCITY down -v ;;
+ folia) $DC_FOLIA down -v ;;
+ *) echo "Unknown platform: ${1:-}"; exit 1 ;;
+ esac
+}
+
+do_rcon() {
+ case "$1" in
+ paper) $DC_PAPER exec paper rcon-cli ;;
+ velocity)
+ local server="${2:-s1}"
+ if [[ "$server" != "s1" && "$server" != "s2" ]]; then
+ echo "Error: Invalid server '$server'. Available: s1, s2"
+ exit 1
+ fi
+ $DC_VELOCITY exec "$server" rcon-cli
+ ;;
+ folia) $DC_FOLIA exec folia rcon-cli ;;
+ *) echo "Unknown platform: ${1:-}"; exit 1 ;;
+ esac
+}
+
# --- Main ---
-case "${1:-}" in
- folia)
- folia_cmd "${2:-}"
- ;;
- start)
- ./gradlew :platform-paper:clean :platform-paper:shadowJar :platform-velocity:clean :platform-velocity:shadowJar
- ensure_plugin_dir docker/velocity/plugins-paper-s1
- ensure_plugin_dir docker/velocity/plugins-paper-s2
- ensure_plugin_dir docker/velocity/plugins-velocity
- rm -f docker/velocity/plugins-paper-s1/*.jar
- rm -f docker/velocity/plugins-paper-s2/*.jar
- rm -f docker/velocity/plugins-velocity/*.jar
- cp platform-paper/build/libs/*.jar docker/velocity/plugins-paper-s1/
- cp platform-paper/build/libs/*.jar docker/velocity/plugins-paper-s2/
- cp platform-velocity/build/libs/*.jar docker/velocity/plugins-velocity/
- $DC_VELOCITY up
- ;;
- start-s1)
- ./gradlew :platform-paper:clean :platform-paper:shadowJar
- ensure_plugin_dir docker/velocity/plugins-paper-s1
- rm -f docker/velocity/plugins-paper-s1/*.jar
- cp platform-paper/build/libs/*.jar docker/velocity/plugins-paper-s1/
- $DC_VELOCITY up s1
- ;;
- restart)
- $DC_VELOCITY restart s1 s2 velocity
- ;;
- stop)
- $DC_VELOCITY down
- ;;
- clean)
- $DC_VELOCITY down -v
- ;;
- rcon)
- SERVER="${2:-s1}"
- if [[ "$SERVER" != "s1" && "$SERVER" != "s2" ]]; then
- echo "Error: Invalid server '$SERVER'. Available servers: s1, s2"
- exit 1
- fi
- $DC_VELOCITY exec "$SERVER" rcon-cli
- ;;
- logs)
- SERVER="${2:-s1}"
- if [[ "$SERVER" != "s1" && "$SERVER" != "s2" ]]; then
- echo "Error: Invalid server '$SERVER'. Available servers: s1, s2"
- exit 1
- fi
- $DC_VELOCITY logs -f "$SERVER"
- ;;
- vlogs)
- $DC_VELOCITY logs -f velocity
- ;;
- help|"")
- help
- ;;
+case "$ACTION" in
+ start) do_start "$PLATFORM" ;;
+ stop) do_stop "$PLATFORM" ;;
+ log) do_log "$PLATFORM" ;;
+ clean) do_clean "$PLATFORM" ;;
+ rcon) do_rcon "$PLATFORM" "${3:-}" ;;
+ help|"") help ;;
*)
- echo "Unknown command: $1"
+ echo "Unknown action: $ACTION"
echo ""
help
exit 1