Skip to content

Commit b4ad0c8

Browse files
committed
Jar packaging
1 parent 64d003f commit b4ad0c8

File tree

8 files changed

+158
-83
lines changed

8 files changed

+158
-83
lines changed

README.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,8 +30,10 @@ Enables and starts the systemd service of the Cockpit web-based management inter
3030

3131
- App
3232

33+
Download latest version from the [Releases](https://github.com/lfir/fedora-setup-script/releases) page and execute in the terminal
34+
3335
```
34-
java src/main/java/cf/maybelambda/fedora/PostInstallUpdater.java
36+
java -jar fedora-setup-script-X.Y.Z.jar
3537
```
3638

3739
`--help` can be passed to see available [options](https://github.com/lfir/fedora-setup-script/blob/main/src/main/resources/help.txt).

pom.xml

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66

77
<groupId>cf.maybelambda</groupId>
88
<artifactId>fedora-setup-script</artifactId>
9-
<version>3.0.1</version>
9+
<version>3.0.2</version>
1010

1111
<properties>
1212
<maven.compiler.source>21</maven.compiler.source>
@@ -19,15 +19,14 @@
1919
<dependency>
2020
<groupId>org.junit.jupiter</groupId>
2121
<artifactId>junit-jupiter</artifactId>
22-
<version>5.14.0</version>
22+
<version>6.0.0</version>
2323
<scope>test</scope>
2424
</dependency>
25-
2625
<!-- https://mvnrepository.com/artifact/org.mockito/mockito-core -->
2726
<dependency>
2827
<groupId>org.mockito</groupId>
2928
<artifactId>mockito-core</artifactId>
30-
<version>5.18.0</version>
29+
<version>5.20.0</version>
3130
<scope>test</scope>
3231
</dependency>
3332
</dependencies>
@@ -43,6 +42,20 @@
4342
<useModulePath>false</useModulePath>
4443
</configuration>
4544
</plugin>
45+
<!-- https://mvnrepository.com/artifact/org.apache.maven.plugins/maven-jar-plugin -->
46+
<plugin>
47+
<groupId>org.apache.maven.plugins</groupId>
48+
<artifactId>maven-jar-plugin</artifactId>
49+
<version>3.4.2</version>
50+
<configuration>
51+
<archive>
52+
<manifest>
53+
<addClasspath>true</addClasspath>
54+
<mainClass>cf.maybelambda.fedora.PostInstallUpdater</mainClass>
55+
</manifest>
56+
</archive>
57+
</configuration>
58+
</plugin>
4659
</plugins>
4760
</build>
4861
</project>
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
package cf.maybelambda.fedora;
2+
3+
import java.io.BufferedReader;
4+
import java.io.IOException;
5+
import java.io.InputStreamReader;
6+
import java.nio.charset.StandardCharsets;
7+
import java.nio.file.Files;
8+
import java.nio.file.Path;
9+
import java.util.ArrayList;
10+
import java.util.List;
11+
12+
public class ConfigManager {
13+
private static final String CONFIG_DIR = "src/main/resources";
14+
15+
static List<String> readResourceLines(String filename) throws IOException {
16+
Path path = Path.of(CONFIG_DIR, filename);
17+
if (Files.exists(path)) {
18+
return Files.readAllLines(path, StandardCharsets.UTF_8);
19+
}
20+
try (var in = PostInstallUpdater.class.getResourceAsStream("/" + filename)) {
21+
if (in == null) throw new IOException("Resource not found: " + filename);
22+
return new BufferedReader(new InputStreamReader(in, StandardCharsets.UTF_8)).lines().toList();
23+
}
24+
}
25+
26+
static List<String> loadPackageNamesFrom(String filename) {
27+
List<String> packages = new ArrayList<>();
28+
try {
29+
List<String> lines = readResourceLines(filename);
30+
for (String line : lines) {
31+
String trimmed = line.trim();
32+
if (!trimmed.isEmpty() && !trimmed.startsWith("#")) {
33+
packages.add(trimmed);
34+
}
35+
}
36+
} catch (IOException e) {
37+
System.err.println("Failed to read package list from " + filename + ": " + e.getMessage());
38+
}
39+
40+
return packages;
41+
}
42+
}

src/main/java/cf/maybelambda/fedora/PostInstallUpdater.java

Lines changed: 9 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,6 @@
33
import java.io.BufferedReader;
44
import java.io.IOException;
55
import java.io.InputStreamReader;
6-
import java.nio.charset.StandardCharsets;
7-
import java.nio.file.Files;
8-
import java.nio.file.Path;
96
import java.util.ArrayList;
107
import java.util.Arrays;
118
import java.util.HashSet;
@@ -16,22 +13,21 @@
1613

1714
public class PostInstallUpdater {
1815
private static final List<String> gpgKeys = List.of(
19-
"https://rpmfusion.org/keys?action=AttachFile&do=get&target=RPM-GPG-KEY-rpmfusion-free-fedora-2020",
20-
"https://rpmfusion.org/keys?action=AttachFile&do=get&target=RPM-GPG-KEY-rpmfusion-nonfree-fedora-2020"
16+
"https://rpmfusion.org/keys?action=AttachFile&do=get&target=RPM-GPG-KEY-rpmfusion-free-fedora-2020",
17+
"https://rpmfusion.org/keys?action=AttachFile&do=get&target=RPM-GPG-KEY-rpmfusion-nonfree-fedora-2020"
2118
);
2219
private static final List<String> rpmfusionRepos = List.of(
23-
"https://download1.rpmfusion.org/free/fedora/rpmfusion-free-release-42.noarch.rpm",
24-
"https://download1.rpmfusion.org/nonfree/fedora/rpmfusion-nonfree-release-42.noarch.rpm"
20+
"https://download1.rpmfusion.org/free/fedora/rpmfusion-free-release-42.noarch.rpm",
21+
"https://download1.rpmfusion.org/nonfree/fedora/rpmfusion-nonfree-release-42.noarch.rpm"
2522
);
2623

2724
private static final String flatpakRemoteName = "flathub";
2825
private static final String flatpakRemoteUrl = "https://dl.flathub.org/repo/flathub.flatpakrepo";
2926

3027
private static final List<String> groupList = List.of(
31-
"docker", "libvirt", "vboxsf", "vboxusers"
28+
"docker", "libvirt", "vboxsf", "vboxusers"
3229
);
3330

34-
private static final String CONFIG_DIR = "src/main/resources";
3531
private static final String DNF_INSTALL_FILE = "dnf-install.cf";
3632
private static final String DNF_REMOVE_FILE = "dnf-remove.cf";
3733
private static final String FLATPAK_INSTALL_FILE = "flatpak-install.cf";
@@ -48,9 +44,9 @@ public static void main(String[] args) {
4844
return;
4945
}
5046

51-
List<String> dnfInstallPackages = loadPackageNamesFrom(DNF_INSTALL_FILE);
52-
List<String> dnfRemovePackages = loadPackageNamesFrom(DNF_REMOVE_FILE);
53-
List<String> flatpakInstallPackages = loadPackageNamesFrom(FLATPAK_INSTALL_FILE);
47+
List<String> dnfInstallPackages = ConfigManager.loadPackageNamesFrom(DNF_INSTALL_FILE);
48+
List<String> dnfRemovePackages = ConfigManager.loadPackageNamesFrom(DNF_REMOVE_FILE);
49+
List<String> flatpakInstallPackages = ConfigManager.loadPackageNamesFrom(FLATPAK_INSTALL_FILE);
5450
Scanner scanner = new Scanner(System.in);
5551

5652
System.out.println("Fedora Post Install Actions\n");
@@ -59,7 +55,6 @@ public static void main(String[] args) {
5955
System.out.println("---[Dry Run Mode] Shell Commands will not be executed.---\n");
6056
}
6157

62-
// 1. Install RPMFusion repos
6358
if (confirm(scanner, "Install RPMFusion repos?")) {
6459
for (String key : gpgKeys) {
6560
runCommand(new String[]{"sudo", "rpm", "--import", key});
@@ -76,7 +71,6 @@ public static void main(String[] args) {
7671
runCommand(cmd);
7772
}
7873

79-
// 2. DNF install packages
8074
if (confirm(scanner, "Install additional packages with DNF?")) {
8175
List<String> filtered = promptForExclusions(dnfInstallPackages, scanner);
8276
String[] cmd = new String[filtered.size() + 5];
@@ -91,7 +85,6 @@ public static void main(String[] args) {
9185
runCommand(cmd);
9286
}
9387

94-
// 3. DNF remove packages
9588
if (confirm(scanner, "Remove all DNF packages marked for removal?")) {
9689
List<String> filtered = promptForExclusions(dnfRemovePackages, scanner);
9790
String[] cmd = new String[filtered.size() + 4];
@@ -106,7 +99,6 @@ public static void main(String[] args) {
10699
runCommand(new String[]{"sudo", "dnf", "autoremove", "-y"});
107100
}
108101

109-
// 4. Flatpak install apps
110102
if (confirm(scanner, "Install Flatpak apps?")) {
111103
runCommand(new String[]{"flatpak", "remote-add", "--if-not-exists", flatpakRemoteName, flatpakRemoteUrl});
112104
List<String> filtered = promptForExclusions(flatpakInstallPackages, scanner);
@@ -121,7 +113,6 @@ public static void main(String[] args) {
121113
runCommand(cmd);
122114
}
123115

124-
// 5. Ensure groups exist and add user to them
125116
if (confirm(scanner, "Ensure admin groups exist and add current user to them?")) {
126117
String user = System.getProperty("user.name");
127118
for (String group : groupList) {
@@ -135,7 +126,6 @@ public static void main(String[] args) {
135126
}
136127
}
137128

138-
// 6. Enable and start Cockpit service
139129
if (confirm(scanner, "Enable and start cockpit.socket service?")) {
140130
runCommand(new String[]{"sudo", "systemctl", "enable", "--now", "cockpit.socket"});
141131
}
@@ -188,23 +178,6 @@ static int runCommand(String[] command) {
188178
return exitCode;
189179
}
190180

191-
static List<String> loadPackageNamesFrom(String filename) {
192-
List<String> packages = new ArrayList<>();
193-
try {
194-
List<String> lines = Files.readAllLines(Path.of(CONFIG_DIR, filename), StandardCharsets.UTF_8);
195-
for (String line : lines) {
196-
String trimmed = line.trim();
197-
if (!trimmed.isEmpty() && !trimmed.startsWith("#")) {
198-
packages.add(trimmed);
199-
}
200-
}
201-
} catch (IOException e) {
202-
System.err.println("Failed to read package list from " + filename + ": " + e.getMessage());
203-
}
204-
205-
return packages;
206-
}
207-
208181
static List<String> promptForExclusions(List<String> packages, Scanner scanner) {
209182
for (int i = 0; i < packages.size(); i++) {
210183
System.out.printf("%2d. %s\n", i + 1, packages.get(i));
@@ -235,7 +208,7 @@ static List<String> promptForExclusions(List<String> packages, Scanner scanner)
235208

236209
static void printHelp() {
237210
try {
238-
List<String> lines = Files.readAllLines(Path.of(CONFIG_DIR, HELP_FILE), StandardCharsets.UTF_8);
211+
List<String> lines = ConfigManager.readResourceLines(HELP_FILE);
239212
System.out.println(String.join(System.lineSeparator(), lines));
240213
} catch (IOException e) {
241214
System.err.println("Error reading help file: " + e.getMessage());

src/main/resources/help.txt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,12 @@ Fedora Post Install Actions
22
===========================
33

44
Usage:
5-
java PostInstallUpdater.java [options]
5+
java -jar fedora-setup-script-X.Y.Z.jar [options]
66

77
Options:
88
-h, --help Show this help page and exit.
99
--dry-run Print all commands without executing them.
1010

1111
Example:
12-
java PostInstallUpdater.java --dry-run
12+
java -jar fedora-setup-script-3.0.2.jar --dry-run
1313
Goes through all steps without executing system commands.
Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
package cf.maybelambda.fedora;
2+
3+
import org.junit.jupiter.api.Test;
4+
import org.mockito.MockedStatic;
5+
import org.mockito.Mockito;
6+
7+
import java.io.IOException;
8+
import java.nio.charset.Charset;
9+
import java.nio.charset.StandardCharsets;
10+
import java.nio.file.Files;
11+
import java.nio.file.Path;
12+
import java.util.List;
13+
14+
import static org.junit.jupiter.api.Assertions.assertEquals;
15+
import static org.junit.jupiter.api.Assertions.assertThrows;
16+
import static org.junit.jupiter.api.Assertions.assertTrue;
17+
import static org.mockito.ArgumentMatchers.any;
18+
import static org.mockito.ArgumentMatchers.eq;
19+
import static org.mockito.Mockito.CALLS_REAL_METHODS;
20+
import static org.mockito.Mockito.mockStatic;
21+
22+
public class ConfigManagerTests {
23+
24+
@Test
25+
void readResourceLinesReadsFromFilesystemWhenExists() throws IOException {
26+
try (MockedStatic<Files> filesMock = mockStatic(Files.class)) {
27+
filesMock.when(() -> Files.exists(any(Path.class))).thenReturn(true);
28+
filesMock.when(() -> Files.readAllLines(any(Path.class), any(Charset.class))).thenReturn(List.of("line1", "line2"));
29+
30+
List<String> result = ConfigManager.readResourceLines("testfile.txt");
31+
32+
assertEquals(List.of("line1", "line2"), result);
33+
}
34+
}
35+
36+
@Test
37+
void readResourceLinesReadsFromClasspathWhenFileNotExists() throws IOException {
38+
try (MockedStatic<Files> filesMock = mockStatic(Files.class)) {
39+
// Force the filesystem check to say the file is NOT present in CONFIG_DIR
40+
filesMock.when(() -> Files.exists(any(Path.class))).thenReturn(false);
41+
42+
// Ensure the test resource "test.txt" is placed in src/test/resources
43+
List<String> result = ConfigManager.readResourceLines("test.txt");
44+
45+
assertEquals(List.of("one", "two", "three"), result);
46+
47+
filesMock.verify(() -> Files.exists(any(Path.class)));
48+
}
49+
}
50+
51+
@Test
52+
void readResourceLinesThrowsIOExceptionWhenResourceMissing() {
53+
assertThrows(IOException.class, () -> ConfigManager.readResourceLines("missing.txt"));
54+
}
55+
56+
@Test
57+
void loadPackageNamesFromValidFileParsesPackageNamesAndOmitsComments() throws IOException {
58+
try (MockedStatic<ConfigManager> updaterMock = Mockito.mockStatic(ConfigManager.class, CALLS_REAL_METHODS)) {
59+
updaterMock.when(() -> ConfigManager.readResourceLines(any(String.class)))
60+
.thenReturn(List.of("# Comment", "nano", "vim", "", "htop"));
61+
62+
List<String> result = ConfigManager.loadPackageNamesFrom("test-packages.cf");
63+
64+
assertEquals(List.of("nano", "vim", "htop"), result);
65+
}
66+
}
67+
68+
@Test
69+
void loadPackageNamesFromReturnsEmptyListOnIOException() {
70+
try (MockedStatic<Files> filesMock = mockStatic(Files.class)) {
71+
filesMock.when(() -> Files.readAllLines(any(Path.class), eq(StandardCharsets.UTF_8)))
72+
.thenThrow(new IOException("Simulated failure"));
73+
74+
List<String> result = ConfigManager.loadPackageNamesFrom("missing.cf");
75+
76+
assertTrue(result.isEmpty());
77+
}
78+
}
79+
}

0 commit comments

Comments
 (0)