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 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. 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 ## Outputs
### url ### url
The complete URL where the system can be accessed. The complete URL where the system can be accessed.

View File

@ -17,6 +17,10 @@ inputs:
description: 'The Docker Compose file to use' description: 'The Docker Compose file to use'
default: 'compose.yaml' default: 'compose.yaml'
required: true required: true
clone-using:
description: 'The method to use for cloning the repository, either ssh or https'
default: 'https'
required: true
outputs: outputs:
url: url:
description: 'The URL of the deployed branch' 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 }); 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() { function main() {
return __awaiter(this, void 0, void 0, function* () { 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 repositoryName = gitea.context.repo.repo;
const owner = gitea.context.repo.owner; const owner = gitea.context.repo.owner;
const serverUrl = gitea.context.serverUrl; const serverUrl = gitea.context.serverUrl;
const mangledBranchName = branchName.replace(/\//g, '-').replace(/[^a-zA-Z0-9-]/g, ''); const mangledBranchName = branchName.replace(/\//g, '-').replace(/[^a-zA-Z0-9-]/g, '');
const composeFile = core.getInput('compose-file', { required: true }); const composeFile = core.getInput('compose-file', { required: true });
const cloneUrl = getCloneUrl(serverUrl, owner, repositoryName);
core.info(`Branch name: ${branchName}`); core.info(`Branch name: ${branchName}`);
core.info(`Repository name: ${repositoryName}`); core.info(`Repository name: ${repositoryName}`);
core.info(`Cloning from: ${cloneUrl}`);
core.setOutput('url', `https://${repositoryName}-${mangledBranchName}.branch.dsv.su.se`); core.setOutput('url', `https://${repositoryName}-${mangledBranchName}.branch.dsv.su.se`);
const sshKey = getSSHKey(); const sshKey = getSSHKey();
core.info(`sshKey: ${sshKey.length}`);
fs.writeFileSync('ssh_key', `${sshKey}\n`, { flag: 'w+', mode: "0600" }); fs.writeFileSync('ssh_key', `${sshKey}\n`, { flag: 'w+', mode: "0600" });
const deployCommand = `\ const sshStdin = `${cloneUrl} ${branchName} ${mangledBranchName} ${repositoryName} ${composeFile}`;
echo "${serverUrl}/${owner}/${repositoryName}.git ${branchName} ${mangledBranchName} ${composeFile}" | \ core.info(`Deploy arguments: ${sshStdin}`);
ssh -i ssh_key -o StrictHostKeyChecking=accept-new branch.dsv.su.se`; const deployment = yield exec.getExecOutput('ssh', ['-i', 'ssh_key', '-o', 'StrictHostKeyChecking=accept-new', 'branch.dsv.su.se'], {
const deployment = yield exec.getExecOutput('sh', ['-c', deployCommand]); input: Buffer.from(sshStdin)
});
if (deployment.exitCode != 0) { if (deployment.exitCode != 0) {
core.error(`Deployment failed: ${deployment.stderr}`); 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() { 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 repositoryName = gitea.context.repo.repo;
const owner = gitea.context.repo.owner; const owner = gitea.context.repo.owner;
const serverUrl = gitea.context.serverUrl; const serverUrl = gitea.context.serverUrl;
const mangledBranchName = branchName.replace(/\//g, '-').replace(/[^a-zA-Z0-9-]/g, ''); const mangledBranchName = branchName.replace(/\//g, '-').replace(/[^a-zA-Z0-9-]/g, '');
const composeFile = core.getInput('compose-file', {required: true}); const composeFile = core.getInput('compose-file', {required: true});
const cloneUrl = getCloneUrl(serverUrl, owner, repositoryName);
core.info(`Branch name: ${branchName}`); core.info(`Branch name: ${branchName}`);
core.info(`Repository name: ${repositoryName}`); core.info(`Repository name: ${repositoryName}`);
core.info(`Cloning from: ${cloneUrl}`);
core.setOutput('url', `https://${repositoryName}-${mangledBranchName}.branch.dsv.su.se`); core.setOutput('url', `https://${repositoryName}-${mangledBranchName}.branch.dsv.su.se`);
const sshKey = getSSHKey(); const sshKey = getSSHKey();
core.info(`sshKey: ${sshKey.length}`);
fs.writeFileSync('ssh_key', `${sshKey}\n`, {flag: 'w+', mode: "0600"}); fs.writeFileSync('ssh_key', `${sshKey}\n`, {flag: 'w+', mode: "0600"});
const deployCommand = `\ const sshStdin = `${cloneUrl} ${branchName} ${mangledBranchName} ${repositoryName} ${composeFile}`;
echo "${serverUrl}/${owner}/${repositoryName}.git ${branchName} ${mangledBranchName} ${composeFile}" | \ core.info(`Deploy arguments: ${sshStdin}`);
ssh -i ssh_key -o StrictHostKeyChecking=accept-new branch.dsv.su.se`; const deployment = await exec.getExecOutput(
const deployment = await exec.getExecOutput('sh', ['-c', deployCommand]) 'ssh',
['-i', 'ssh_key', '-o', 'StrictHostKeyChecking=accept-new', 'branch.dsv.su.se'],
{
input: Buffer.from(sshStdin)
}
);
if (deployment.exitCode != 0) { if (deployment.exitCode != 0) {
core.error(`Deployment failed: ${deployment.stderr}`); core.error(`Deployment failed: ${deployment.stderr}`);
} else { } else {