Skip to content

Commit 90c4bf9

Browse files
authored
Add HTTPS support (#33)
1 parent ef5a605 commit 90c4bf9

4 files changed

Lines changed: 100 additions & 31 deletions

File tree

README.md

Lines changed: 39 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,30 +1,58 @@
11
# Add Julia Registry
22

3-
If your package depends on private packages registered in a private registry, you need to handle authentication to that registry and the package repositories in a fully automated way, since you can't manually enter credentials in a CI environment.
4-
This action will deal with all of that for you, all you need is an SSH private key.
3+
Handles Git authentication to private Julia packages and registries such that they can be used within a CI environment. After running this action any GitHub HTTPS request made by Pkg will be automatically authenticated.
54

6-
```yml
5+
Currently, this action only support private packages hosted within GitHub.
6+
7+
Access to private packages requires you to create a [SSH private key](https://docs.github.com/en/authentication/connecting-to-github-with-ssh) or a [personal access token](https://docs.github.com/en/authentication/keeping-your-account-and-data-secure/managing-your-personal-access-tokens) (with the proper repository access) in GitHub.
8+
9+
## SSH Access
10+
11+
```yaml
712
jobs:
813
test:
914
runs-on: ubuntu-latest
1015
steps:
1116
- uses: actions/checkout@v4
1217
- uses: julia-actions/setup-julia@v2
1318
with:
14-
version: 1
19+
version: "1"
1520
- uses: julia-actions/cache@v2
1621
- uses: julia-actions/add-julia-registry@v2
1722
with:
18-
key: ${{ secrets.SSH_KEY }}
1923
registry: MyOrg/MyRegistry
24+
ssh-key: ${{ secrets.SSH_KEY }}
2025
- uses: julia-actions/julia-runtest@v1
2126
```
2227
23-
This action does the following:
28+
When using the SSH protocol this action performs the following steps:
29+
30+
- Starts [`ssh-agent`](https://linux.die.net/man/1/ssh-agent).
31+
- Adds the supplied private key to the SSH agent.
32+
- Configures Git to rewrite HTTPS URLs to SSH URLs (e.g. `https://github.com/foo/bar` to `git@github.com:foo/bar`).
33+
- Downloads the specified registry and the [General](https://github.com/JuliaRegistries/General) registry.
34+
35+
## HTTPS Access
36+
37+
```yaml
38+
jobs:
39+
test:
40+
runs-on: ubuntu-latest
41+
steps:
42+
- uses: actions/checkout@v4
43+
- uses: julia-actions/setup-julia@v2
44+
with:
45+
version: "1"
46+
- uses: julia-actions/cache@v2
47+
- uses: julia-actions/add-julia-registry@v2
48+
with:
49+
registry: MyOrg/MyRegistry
50+
protocol: https
51+
github-token: ${{ secrets.GITHUB_TOKEN }} # Using `${{ github.token }}` won't work for most use cases.
52+
- uses: julia-actions/julia-runtest@v1
53+
```
2454
25-
- Starts [ssh-agent](https://linux.die.net/man/1/ssh-agent)
26-
- Adds your private key to the agent
27-
- Configures Git to rewrite HTTPS URLs (`https://github.com/foo/bar`) to SSH URLs (`git@github.com:foo/bar`)
28-
- Downloads the registry you specify and [General](https://github.com/JuliaRegistries/General)
55+
When using the HTTPS protocol this action performs the following steps:
2956
30-
Therefore, when Pkg tries to download packages from the HTTPS URLs in the registry, it will do so over SSH, using your private key as authentication.
57+
- Configures Git to rewrite unauthenticated HTTPS URLs to authenticated HTTPS URLs (e.g. `https://github.com/foo/bar` to `https://git:ghp_*****@github.com/foo/bar`)
58+
- Downloads the specified registry and the [General](https://github.com/JuliaRegistries/General) registry.

action.yml

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,21 @@ name: Add Julia Registry
22
author: Chris de Graaf
33
description: Clone a private Julia registry and configure Pkg access
44
inputs:
5-
key:
6-
description: SSH private key contents
7-
required: true
85
registry:
96
description: Registry to clone (owner/repo)
107
required: true
8+
protocol:
9+
description: Protocol to use when cloning GitHub repositories. Either `ssh` or `https`.
10+
default: ssh
11+
ssh-key:
12+
description: SSH private key contents when cloning with SSH.
13+
required: false
14+
key:
15+
description: Deprecated input which was replaced by `ssh-key`.
16+
required: false
17+
github-token:
18+
description: The GitHub token to use when cloning with HTTPS.
19+
default: ${{ github.token }}
1120
runs:
1221
using: node20
1322
main: main.js

main.js

Lines changed: 33 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ const io = require("@actions/io");
1212
const HOME = os.homedir();
1313
const DEPOT_PATH = (process.env.JULIA_DEPOT_PATH || path.join(HOME, ".julia")).split(path.delimiter);
1414

15-
async function startAgent() {
15+
async function startSshAgent() {
1616
const { stdout } = await exec.getExecOutput("ssh-agent");
1717
stdout.split("\n").forEach(line => {
1818
const match = /(.*)=(.*?);/.exec(line);
@@ -22,7 +22,7 @@ async function startAgent() {
2222
});
2323
}
2424

25-
async function addKey(key) {
25+
async function addSshKey(key) {
2626
const { name } = tmp.fileSync();
2727
fs.writeFileSync(name, key.trim() + "\n");
2828
await exec.exec(`ssh-add ${name}`);
@@ -73,22 +73,43 @@ async function cloneRegistry(url, name) {
7373
}
7474
};
7575

76-
async function configureGit() {
77-
await exec.exec("git config --global url.git@github.com:.insteadOf https://github.com/");
76+
async function configureGitInsteadOfSsh() {
77+
await exec.exec(`git config --global url."git@github.com:".insteadOf https://github.com/`);
78+
}
79+
80+
async function configureGitInsteadOfHttps(github_token) {
81+
await exec.exec(`git config --global url."https://git:${github_token}@github.com/".insteadOf https://github.com/`);
7882
}
7983

8084
async function main() {
81-
const key = core.getInput("key", { required: true });
8285
const registry = core.getInput("registry", { required: true });
86+
const protocol = core.getInput("protocol", { required: true });
87+
88+
// While we support the deprecated `key` input we need to roll our own `required: protocol == "ssh"`
89+
// const ssh_key = core.getInput("ssh-key", { required: protocol == "ssh" });
90+
const ssh_key = core.getInput("ssh-key") || core.getInput("key");
91+
if (protocol === "ssh" && !ssh_key) {
92+
throw new Error("Input required and not supplied: ssh-key");
93+
}
8394

84-
await startAgent();
85-
await addKey(key);
86-
await updateKnownHosts();
87-
await cloneRegistry(`git@github.com:${registry}.git`);
88-
if (registry != "JuliaRegistries/General") {
89-
await cloneRegistry("git@github.com:JuliaRegistries/General.git", "General");
95+
const github_token = core.getInput("github-token", { required: protocol == "https" });
96+
97+
if (protocol === "ssh") {
98+
await startSshAgent();
99+
await addSshKey(ssh_key);
100+
await updateKnownHosts();
101+
await configureGitInsteadOfSsh();
102+
await cloneRegistry(`git@github.com:${registry}.git`);
103+
if (registry != "JuliaRegistries/General") {
104+
await cloneRegistry("git@github.com:JuliaRegistries/General.git", "General");
105+
}
106+
} else {
107+
await configureGitInsteadOfHttps(github_token);
108+
await cloneRegistry(`https://github.com/${registry}.git`);
109+
if (registry != "JuliaRegistries/General") {
110+
await cloneRegistry("https://github.com/JuliaRegistries/General.git", "General");
111+
}
90112
}
91-
await configureGit();
92113
}
93114

94115
if (!module.parent) {

post.js

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,15 @@
11
const core = require("@actions/core");
22
const exec = require("@actions/exec");
33

4-
async function undoGitConfig() {
5-
await exec.exec("git config --global --unset url.git@github.com:.insteadOf");
4+
async function unsetGitInsteadOfSsh() {
5+
await exec.exec(`git config --global --unset url."git@github.com:".insteadOf`);
66
}
77

8-
async function stopAgent() {
8+
async function unsetGitInsteadOfHttps(github_token) {
9+
await exec.exec(`git config --global --unset url."https://git:${github_token}@github.com/".insteadOf`);
10+
}
11+
12+
async function stopSshAgent() {
913
const { stdout } = await exec.getExecOutput("ssh-agent -k");
1014
stdout.split("\n").forEach(line => {
1115
const match = /unset (.*);/.exec(line);
@@ -16,8 +20,15 @@ async function stopAgent() {
1620
}
1721

1822
async function post() {
19-
await undoGitConfig();
20-
await stopAgent();
23+
const protocol = core.getInput("protocol", { required: true });
24+
const github_token = core.getInput("github-token", { required: protocol == "https" });
25+
26+
if (protocol === "ssh") {
27+
await unsetGitInsteadOfSsh();
28+
await stopSshAgent();
29+
} else {
30+
await unsetGitInsteadOfHttps(github_token);
31+
}
2132
}
2233

2334
if (!module.parent) {

0 commit comments

Comments
 (0)