• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

jreleaser / jreleaser / #477

04 Apr 2025 05:53PM UTC coverage: 35.124% (-5.1%) from 40.183%
#477

push

github

aalmiray
fix(deploy): Add missing Forgejo messages

Related to #1842

18210 of 51845 relevant lines covered (35.12%)

0.35 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

0.0
/sdks/jreleaser-ssh-java-sdk/src/main/java/org/jreleaser/sdk/ssh/SshUtils.java
1
/*
2
 * SPDX-License-Identifier: Apache-2.0
3
 *
4
 * Copyright 2020-2025 The JReleaser authors.
5
 *
6
 * Licensed under the Apache License, Version 2.0 (the "License");
7
 * you may not use this file except in compliance with the License.
8
 * You may obtain a copy of the License at
9
 *
10
 *     https://www.apache.org/licenses/LICENSE-2.0
11
 *
12
 * Unless required by applicable law or agreed to in writing, software
13
 * distributed under the License is distributed on an "AS IS" BASIS,
14
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
 * See the License for the specific language governing permissions and
16
 * limitations under the License.
17
 */
18
package org.jreleaser.sdk.ssh;
19

20
import net.schmizz.sshj.SSHClient;
21
import net.schmizz.sshj.common.SSHException;
22
import net.schmizz.sshj.connection.channel.direct.Session;
23
import net.schmizz.sshj.sftp.SFTPClient;
24
import net.schmizz.sshj.transport.verification.FingerprintVerifier;
25
import net.schmizz.sshj.transport.verification.PromiscuousVerifier;
26
import net.schmizz.sshj.userauth.password.PasswordFinder;
27
import net.schmizz.sshj.userauth.password.PasswordUtils;
28
import org.jreleaser.bundle.RB;
29
import org.jreleaser.model.internal.JReleaserContext;
30
import org.jreleaser.model.internal.common.Ssh;
31
import org.jreleaser.model.internal.download.SshDownloader;
32
import org.jreleaser.model.internal.upload.SshUploader;
33
import org.jreleaser.model.spi.download.DownloadException;
34
import org.jreleaser.model.spi.upload.UploadException;
35

36
import java.io.IOException;
37
import java.nio.file.Files;
38
import java.nio.file.Path;
39
import java.nio.file.Paths;
40
import java.util.concurrent.TimeUnit;
41

42
import static org.jreleaser.util.StringUtils.isNotBlank;
43

44
/**
45
 * @author Andres Almiray
46
 * @since 1.1.0
47
 */
48
public class SshUtils {
49
    private SshUtils() {
50
        // noop
51
    }
52

53
    public static SSHClient createSSHClient(JReleaserContext context, SshUploader<?> uploader) throws UploadException {
54
        if (context.isDryrun()) return null;
×
55

56
        try {
57
            SSHClient client = sshClient(context, uploader);
×
58
            client.setConnectTimeout(uploader.getConnectTimeout() * 1000);
×
59
            client.setTimeout(uploader.getReadTimeout() * 1000);
×
60
            return client;
×
61
        } catch (IOException e) {
×
62
            throw new UploadException(RB.$("ERROR_unexpected_upload_to", uploader.getName()), e);
×
63
        }
64
    }
65

66
    public static SSHClient createSSHClient(JReleaserContext context, SshDownloader<?> downloader) throws DownloadException {
67
        if (context.isDryrun()) return null;
×
68

69
        try {
70
            SSHClient client = sshClient(context, downloader);
×
71
            client.setConnectTimeout(downloader.getConnectTimeout() * 1000);
×
72
            client.setTimeout(downloader.getReadTimeout() * 1000);
×
73
            return client;
×
74
        } catch (IOException e) {
×
75
            throw new DownloadException(RB.$("ERROR_unexpected_download_from", downloader.getName()), e);
×
76
        }
77
    }
78

79
    private static SSHClient sshClient(JReleaserContext context, Ssh ssh) throws IOException {
80
        SSHClient client = new SSHClient();
×
81

82
        Path defaultKnownHostsFilePath = Paths.get(System.getProperty("user.home")).resolve(".ssh/known_hosts");
×
83

84
        if (isNotBlank(ssh.getKnownHostsFile())) {
×
85
            Path knownHostsFilePath = context.getBasedir().resolve(ssh.getKnownHostsFile());
×
86
            if (Files.exists(knownHostsFilePath)) {
×
87
                client.loadKnownHosts(knownHostsFilePath.toFile());
×
88
            } else {
89
                if (!Files.exists(defaultKnownHostsFilePath)) {
×
90
                    Files.createDirectories(defaultKnownHostsFilePath.getParent());
×
91
                    Files.createFile(defaultKnownHostsFilePath);
×
92
                }
93
                client.loadKnownHosts();
×
94
            }
95
        } else {
×
96
            if (!Files.exists(defaultKnownHostsFilePath)) {
×
97
                Files.createDirectories(defaultKnownHostsFilePath.getParent());
×
98
                Files.createFile(defaultKnownHostsFilePath);
×
99
            }
100
            client.loadKnownHosts();
×
101
        }
102

103
        String publicKey = ssh.getPublicKey();
×
104
        String privateKey = ssh.getPrivateKey();
×
105
        String passphrase = ssh.getPassphrase();
×
106
        String fingerprint = ssh.getFingerprint();
×
107

108
        if (isNotBlank(publicKey) && isNotBlank(privateKey)) {
×
109
            PasswordFinder passwordFinder = null;
×
110
            if (isNotBlank(passphrase)) {
×
111
                passwordFinder = PasswordUtils.createOneOff(passphrase.toCharArray());
×
112
            }
113
            client.loadKeys(privateKey, publicKey, passwordFinder);
×
114
        }
115

116
        if (isNotBlank(fingerprint)) {
×
117
            client.addHostKeyVerifier(FingerprintVerifier.getInstance(fingerprint));
×
118
        }
119

120
        if (Boolean.getBoolean("jreleaser.disableSshVerification")) {
×
121
            context.getLogger().warn(RB.$("warn_ssh_disabled"));
×
122
            client.addHostKeyVerifier(new PromiscuousVerifier());
×
123
        }
124

125
        client.connect(ssh.getHost(), ssh.getPort());
×
126
        client.authPassword(ssh.getUsername(), ssh.getPassword());
×
127
        return client;
×
128
    }
129

130
    public static SFTPClient createSFTPClient(SshUploader<?> uploader, SSHClient ssh) throws UploadException {
131
        if (null == ssh) return null;
×
132

133
        try {
134
            return ssh.newSFTPClient();
×
135
        } catch (IOException e) {
×
136
            throw new UploadException(RB.$("ERROR_unexpected_upload_to", uploader.getName()), e);
×
137
        }
138
    }
139

140
    public static SFTPClient createSFTPClient(SshDownloader<?> downloader, SSHClient ssh) throws DownloadException {
141
        if (null == ssh) return null;
×
142

143
        try {
144
            return ssh.newSFTPClient();
×
145
        } catch (IOException e) {
×
146
            throw new DownloadException(RB.$("ERROR_unexpected_download_from", downloader.getName()), e);
×
147
        }
148
    }
149

150
    public static void createDirectories(JReleaserContext context, SshUploader<?> uploader, SSHClient ssh, Path path) throws UploadException {
151
        try (Session session = ssh.startSession()) {
×
152
            Session.Command cmd = session.exec("mkdir -p " + path.toAbsolutePath());
×
153
            cmd.join(uploader.getReadTimeout(), TimeUnit.SECONDS);
×
154
        } catch (SSHException e) {
×
155
            context.getLogger().trace(e);
×
156
            throw new UploadException(RB.$("ERROR_ssh_mkdir", path), e);
×
157
        }
×
158
    }
×
159

160
    public static void disconnect(SshUploader<?> uploader, SSHClient ssh) throws UploadException {
161
        try {
162
            if (null != ssh) ssh.disconnect();
×
163
        } catch (IOException e) {
×
164
            throw new UploadException(RB.$("ERROR_disconnect", uploader.getName()), e);
×
165
        }
×
166
    }
×
167

168
    public static void disconnect(SshDownloader<?> downloader, SSHClient ssh) throws DownloadException {
169
        try {
170
            if (null != ssh) ssh.disconnect();
×
171
        } catch (IOException e) {
×
172
            throw new DownloadException(RB.$("ERROR_disconnect", downloader.getName()), e);
×
173
        }
×
174
    }
×
175

176
    public static void close(SshUploader<?> uploader, SFTPClient sftp) throws UploadException {
177
        try {
178
            if (null != sftp) sftp.close();
×
179
        } catch (IOException e) {
×
180
            throw new UploadException(RB.$("ERROR_disconnect", uploader.getName()), e);
×
181
        }
×
182
    }
×
183

184
    public static void close(SshDownloader<?> downloader, SFTPClient sftp) throws DownloadException {
185
        try {
186
            if (null != sftp) sftp.close();
×
187
        } catch (IOException e) {
×
188
            throw new DownloadException(RB.$("ERROR_disconnect", downloader.getName()), e);
×
189
        }
×
190
    }
×
191
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc