Support cloning via SSH #2

Merged
ansv7779 merged 1 commits from private-repo-support into main 2025-09-29 15:31:32 +02:00
4 changed files with 60 additions and 12 deletions

View File

@@ -72,6 +72,17 @@ There are many specifics that you have to adhere to in the Compose file used tha
These specifics are related to how traffic gets routed to your services and how to isolate your services from other
deployments on the same server. This is explained in the [Compose file section](#compose-file-1) below.
### clone-using
How to clone the repository. Valid values are `ssh` and `https`.
Defaults to `https`.
If using `ssh` you need to make sure that the following
public SSH key has read access to the repository
`ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIHVy+36j5AUdxkifVpA/akT3Y1ZkZPnEpaLaZWPRpNlW root@branch`
SSH cloning is required for private repositories.
## Outputs
### url
The complete URL where the system can be accessed.

View File

@@ -17,6 +17,10 @@ inputs:
description: 'The Docker Compose file to use'
default: 'compose.yaml'
required: true
clone-using:
description: 'The method to use for cloning the repository, either ssh or https'
default: 'https'
required: true
outputs:
url:
description: 'The URL of the deployed branch'

27
dist/index.js vendored
View File

@@ -52,24 +52,39 @@ function getSSHKey() {
return core.getInput('ssh-key', { required: true });
}
}
function getCloneUrl(serverUrl, owner, repositoryName) {
const cloneUsing = core.getInput('clone-using', { required: true });
if (cloneUsing === 'https') {
return `${serverUrl}/${owner}/${repositoryName}.git`;
}
else if (cloneUsing === 'ssh') {
const url = new URL(serverUrl);
return `git@${url.hostname}:${owner}/${repositoryName}.git`;
}
else {
throw new Error("Invalid clone-using option, use 'ssh' or 'https'");
}
}
function main() {
return __awaiter(this, void 0, void 0, function* () {
const branchName = process.env.GITHUB_HEAD_REF;
const branchName = process.env.GITHUB_HEAD_REF || 'main';
const repositoryName = gitea.context.repo.repo;
const owner = gitea.context.repo.owner;
const serverUrl = gitea.context.serverUrl;
const mangledBranchName = branchName.replace(/\//g, '-').replace(/[^a-zA-Z0-9-]/g, '');
const composeFile = core.getInput('compose-file', { required: true });
const cloneUrl = getCloneUrl(serverUrl, owner, repositoryName);
core.info(`Branch name: ${branchName}`);
core.info(`Repository name: ${repositoryName}`);
core.info(`Cloning from: ${cloneUrl}`);
core.setOutput('url', `https://${repositoryName}-${mangledBranchName}.branch.dsv.su.se`);
const sshKey = getSSHKey();
core.info(`sshKey: ${sshKey.length}`);
fs.writeFileSync('ssh_key', `${sshKey}\n`, { flag: 'w+', mode: "0600" });
const deployCommand = `\
echo "${serverUrl}/${owner}/${repositoryName}.git ${branchName} ${mangledBranchName} ${composeFile}" | \
ssh -i ssh_key -o StrictHostKeyChecking=accept-new branch.dsv.su.se`;
const deployment = yield exec.getExecOutput('sh', ['-c', deployCommand]);
const sshStdin = `${cloneUrl} ${branchName} ${mangledBranchName} ${repositoryName} ${composeFile}`;
core.info(`Deploy arguments: ${sshStdin}`);
const deployment = yield exec.getExecOutput('ssh', ['-i', 'ssh_key', '-o', 'StrictHostKeyChecking=accept-new', 'branch.dsv.su.se'], {
input: Buffer.from(sshStdin)
});
if (deployment.exitCode != 0) {
core.error(`Deployment failed: ${deployment.stderr}`);
}

View File

@@ -12,27 +12,45 @@ function getSSHKey() {
}
}
function getCloneUrl(serverUrl: string, owner: string, repositoryName: string) {
const cloneUsing = core.getInput('clone-using', {required: true});
if (cloneUsing === 'https') {
return `${serverUrl}/${owner}/${repositoryName}.git`;
} else if (cloneUsing === 'ssh') {
const url = new URL(serverUrl);
return `git@${url.hostname}:${owner}/${repositoryName}.git`;
} else {
throw new Error("Invalid clone-using option, use 'ssh' or 'https'");
}
}
async function main() {
const branchName = process.env.GITHUB_HEAD_REF!;
const branchName = process.env.GITHUB_HEAD_REF || 'main';
const repositoryName = gitea.context.repo.repo;
const owner = gitea.context.repo.owner;
const serverUrl = gitea.context.serverUrl;
const mangledBranchName = branchName.replace(/\//g, '-').replace(/[^a-zA-Z0-9-]/g, '');
const composeFile = core.getInput('compose-file', {required: true});
const cloneUrl = getCloneUrl(serverUrl, owner, repositoryName);
core.info(`Branch name: ${branchName}`);
core.info(`Repository name: ${repositoryName}`);
core.info(`Cloning from: ${cloneUrl}`);
core.setOutput('url', `https://${repositoryName}-${mangledBranchName}.branch.dsv.su.se`);
const sshKey = getSSHKey();
core.info(`sshKey: ${sshKey.length}`);
fs.writeFileSync('ssh_key', `${sshKey}\n`, {flag: 'w+', mode: "0600"});
const deployCommand = `\
echo "${serverUrl}/${owner}/${repositoryName}.git ${branchName} ${mangledBranchName} ${composeFile}" | \
ssh -i ssh_key -o StrictHostKeyChecking=accept-new branch.dsv.su.se`;
const deployment = await exec.getExecOutput('sh', ['-c', deployCommand])
const sshStdin = `${cloneUrl} ${branchName} ${mangledBranchName} ${repositoryName} ${composeFile}`;
core.info(`Deploy arguments: ${sshStdin}`);
const deployment = await exec.getExecOutput(
'ssh',
['-i', 'ssh_key', '-o', 'StrictHostKeyChecking=accept-new', 'branch.dsv.su.se'],
{
input: Buffer.from(sshStdin)
}
);
if (deployment.exitCode != 0) {
core.error(`Deployment failed: ${deployment.stderr}`);
} else {