Skip to content

Commit

Permalink
Add HTTPS support
Browse files Browse the repository at this point in the history
  • Loading branch information
omus committed Jan 17, 2025
1 parent ef5a605 commit 9383136
Show file tree
Hide file tree
Showing 4 changed files with 91 additions and 32 deletions.
52 changes: 40 additions & 12 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,30 +1,58 @@
# Add Julia Registry

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.
This action will deal with all of that for you, all you need is an SSH private key.
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.

```yml
Currently, this action only support private packages hosted within GitHub.

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.

## SSH Access

```yaml
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: julia-actions/setup-julia@v2
with:
version: 1
version: "1"
- uses: julia-actions/cache@v2
- uses: julia-actions/add-julia-registry@v2
- uses: julia-actions/add-julia-registry@v3
with:
key: ${{ secrets.SSH_KEY }}
registry: MyOrg/MyRegistry
ssh-key: ${{ secrets.SSH_KEY }}
- uses: julia-actions/julia-runtest@v1
```
This action does the following:
When using the SSH protocol this action performs the following steps:
- Starts [`ssh-agent`](https://linux.die.net/man/1/ssh-agent).
- Adds the supplied private key to the SSH agent.
- Configures Git to rewrite HTTPS URLs to SSH URLs (e.g. `https://github.com/foo/bar` to `[email protected]:foo/bar`).
- Downloads the specified registry and the [General](https://github.com/JuliaRegistries/General) registry.

## HTTPS Access

```yaml
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: julia-actions/setup-julia@v2
with:
version: "1"
- uses: julia-actions/cache@v2
- uses: julia-actions/add-julia-registry@v3
with:
registry: MyOrg/MyRegistry
protocol: https
github-token: ${{ secrets.GITHUB_TOKEN }} # Using `${{ github.token }}` won't work for most use cases.
- uses: julia-actions/julia-runtest@v1
```
- Starts [ssh-agent](https://linux.die.net/man/1/ssh-agent)
- Adds your private key to the agent
- Configures Git to rewrite HTTPS URLs (`https://github.com/foo/bar`) to SSH URLs (`[email protected]:foo/bar`)
- Downloads the registry you specify and [General](https://github.com/JuliaRegistries/General)
When using the HTTPS protocol this action performs the following steps:
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.
- 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`)
- Downloads the specified registry and the [General](https://github.com/JuliaRegistries/General) registry.
12 changes: 9 additions & 3 deletions action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,18 @@ name: Add Julia Registry
author: Chris de Graaf
description: Clone a private Julia registry and configure Pkg access
inputs:
key:
description: SSH private key contents
required: true
registry:
description: Registry to clone (owner/repo)
required: true
protocol:
description: Protocol to use when cloning GitHub repositories. Either `ssh` or `https`.
default: ssh
ssh-key:
description: SSH private key contents when cloning with SSH.
required: false
github-token:
description: The GitHub token to use when cloning with HTTPS.
default: ${{ github.token }}
runs:
using: node20
main: main.js
Expand Down
38 changes: 26 additions & 12 deletions main.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ const io = require("@actions/io");
const HOME = os.homedir();
const DEPOT_PATH = (process.env.JULIA_DEPOT_PATH || path.join(HOME, ".julia")).split(path.delimiter);

async function startAgent() {
async function startSshAgent() {
const { stdout } = await exec.getExecOutput("ssh-agent");
stdout.split("\n").forEach(line => {
const match = /(.*)=(.*?);/.exec(line);
Expand All @@ -22,7 +22,7 @@ async function startAgent() {
});
}

async function addKey(key) {
async function addSshKey(key) {
const { name } = tmp.fileSync();
fs.writeFileSync(name, key.trim() + "\n");
await exec.exec(`ssh-add ${name}`);
Expand Down Expand Up @@ -73,22 +73,36 @@ async function cloneRegistry(url, name) {
}
};

async function configureGit() {
await exec.exec("git config --global [email protected]:.insteadOf https://github.com/");
async function configureGitInsteadOfSsh() {
await exec.exec(`git config --global url."[email protected]:".insteadOf https://github.com/`);
}

async function configureGitInsteadOfHttps(github_token) {
await exec.exec(`git config --global url."https://git:${github_token}@github.com/".insteadOf https://github.com/`);
}

async function main() {
const key = core.getInput("key", { required: true });
const registry = core.getInput("registry", { required: true });
const protocol = core.getInput("protocol", { required: true });
const ssh_key = core.getInput("ssh-key", { required: protocol == "ssh" });
const github_token = core.getInput("github-token", { required: protocol == "https" });

await startAgent();
await addKey(key);
await updateKnownHosts();
await cloneRegistry(`[email protected]:${registry}.git`);
if (registry != "JuliaRegistries/General") {
await cloneRegistry("[email protected]:JuliaRegistries/General.git", "General");
if (protocol === "ssh") {
await startSshAgent();
await addSshKey(ssh_key);
await updateKnownHosts();
await configureGitInsteadOfSsh();
await cloneRegistry(`[email protected]:${registry}.git`);
if (registry != "JuliaRegistries/General") {
await cloneRegistry("[email protected]:JuliaRegistries/General.git", "General");
}
} else {
await configureGitInsteadOfHttps(github_token);
await cloneRegistry(`https://github.com/${registry}.git`);
if (registry != "JuliaRegistries/General") {
await cloneRegistry("https://github.com/JuliaRegistries/General.git", "General");
}
}
await configureGit();
}

if (!module.parent) {
Expand Down
21 changes: 16 additions & 5 deletions post.js
Original file line number Diff line number Diff line change
@@ -1,11 +1,15 @@
const core = require("@actions/core");
const exec = require("@actions/exec");

async function undoGitConfig() {
await exec.exec("git config --global --unset [email protected]:.insteadOf");
async function unsetGitInsteadOfSsh() {
await exec.exec(`git config --global --unset url."[email protected]:".insteadOf`);
}

async function stopAgent() {
async function unsetGitInsteadOfHttps(github_token) {
await exec.exec(`git config --global --unset url."https://git:${github_token}@github.com/".insteadOf`);
}

async function stopSshAgent() {
const { stdout } = await exec.getExecOutput("ssh-agent -k");
stdout.split("\n").forEach(line => {
const match = /unset (.*);/.exec(line);
Expand All @@ -16,8 +20,15 @@ async function stopAgent() {
}

async function post() {
await undoGitConfig();
await stopAgent();
const protocol = core.getInput("protocol", { required: true });
const github_token = core.getInput("github-token", { required: protocol == "https" });

if (protocol === "ssh") {
await unsetGitInsteadOfSsh();
await stopSshAgent();
} else {
await unsetGitInsteadOfHttps(github_token);
}
}

if (!module.parent) {
Expand Down

0 comments on commit 9383136

Please sign in to comment.