Skip to content

Commit

Permalink
feat: add codespaces support (#114)
Browse files Browse the repository at this point in the history
  • Loading branch information
davisodomhd committed Feb 15, 2024
1 parent b2d20d6 commit fca2fa5
Show file tree
Hide file tree
Showing 6 changed files with 102 additions and 4 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ If this value is set to the name of a valid environment in the target repositori

### `target`

Target where secrets should be stored: `actions` (default) or `dependabot`.
Target where secrets should be stored: `actions` (default), `codespaces` or `dependabot`.

## Usage

Expand Down
58 changes: 58 additions & 0 deletions __tests__/github.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -135,8 +135,10 @@ describe("setSecretForRepo", () => {

let actionsPublicKeyMock: nock.Scope;
let dependabotPublicKeyMock: nock.Scope;
let codespacesPublicKeyMock: nock.Scope;
let setActionsSecretMock: nock.Scope;
let setDependabotSecretMock: nock.Scope;
let setCodespacesSecretMock: nock.Scope;

beforeEach(() => {
nock.cleanAll();
Expand All @@ -151,6 +153,10 @@ describe("setSecretForRepo", () => {
.get(`/repos/${repo.full_name}/dependabot/secrets/public-key`)
.reply(200, publicKey);

codespacesPublicKeyMock = nock("https://api.github.com")
.get(`/repos/${repo.full_name}/codespaces/secrets/public-key`)
.reply(200, publicKey);

setActionsSecretMock = nock("https://api.github.com")
.put(`/repos/${repo.full_name}/actions/secrets/FOO`, (body) => {
expect(body.encrypted_value).toBeTruthy();
Expand All @@ -166,6 +172,14 @@ describe("setSecretForRepo", () => {
return body;
})
.reply(200);

setCodespacesSecretMock = nock("https://api.github.com")
.put(`/repos/${repo.full_name}/codespaces/secrets/FOO`, (body) => {
expect(body.encrypted_value).toBeTruthy();
expect(body.key_id).toEqual(publicKey.key_id);
return body;
})
.reply(200);
});

test("setSecretForRepo with Actions target should retrieve public key for Actions", async () => {
Expand Down Expand Up @@ -194,6 +208,19 @@ describe("setSecretForRepo", () => {
expect(dependabotPublicKeyMock.isDone()).toBeTruthy();
});

test("setSecretForRepo with Codespaces target should retrieve public key for Codespaces", async () => {
await setSecretForRepo(
octokit,
"FOO",
secrets.FOO,
repo,
"",
true,
"codespaces"
);
expect(codespacesPublicKeyMock.isDone()).toBeTruthy();
});

test("setSecretForRepo should not set secret with dry run", async () => {
await setSecretForRepo(
octokit,
Expand Down Expand Up @@ -233,6 +260,19 @@ describe("setSecretForRepo", () => {
);
expect(setDependabotSecretMock.isDone()).toBeTruthy();
});

test("setSecretForRepo with Codespaces target should call set secret endpoint for Codespaces", async () => {
await setSecretForRepo(
octokit,
"FOO",
secrets.FOO,
repo,
"",
false,
"codespaces"
);
expect(setCodespacesSecretMock.isDone()).toBeTruthy();
});
});

describe("setSecretForRepo with environment", () => {
Expand Down Expand Up @@ -336,6 +376,7 @@ describe("deleteSecretForRepo", () => {
const secrets = { FOO: "BAR" };
let deleteActionsSecretMock: nock.Scope;
let deleteDependabotSecretMock: nock.Scope;
let deleteCodespacesSecretMock: nock.Scope;

beforeEach(() => {
nock.cleanAll();
Expand All @@ -347,6 +388,10 @@ describe("deleteSecretForRepo", () => {
deleteDependabotSecretMock = nock("https://api.github.com")
.delete(`/repos/${repo.full_name}/dependabot/secrets/FOO`)
.reply(200);

deleteCodespacesSecretMock = nock("https://api.github.com")
.delete(`/repos/${repo.full_name}/codespaces/secrets/FOO`)
.reply(200);
});

test("deleteSecretForRepo should not delete secret with dry run", async () => {
Expand Down Expand Up @@ -387,6 +432,19 @@ describe("deleteSecretForRepo", () => {
);
expect(deleteDependabotSecretMock.isDone()).toBeTruthy();
});

test("deleteSecretForRepo with Codespaces target should call set secret endpoint for Codespaces", async () => {
await deleteSecretForRepo(
octokit,
"FOO",
secrets.FOO,
repo,
"",
false,
"codespaces"
);
expect(deleteCodespacesSecretMock.isDone()).toBeTruthy();
});
});

describe("deleteSecretForRepo with environment", () => {
Expand Down
2 changes: 1 addition & 1 deletion action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ inputs:
required: false
target:
description: |
Target where secrets should be stored: `actions` (default) or `dependabot`.
Target where secrets should be stored: `actions` (default), `codespaces` or `dependabot`.
default: "actions"
required: false
runs:
Expand Down
19 changes: 18 additions & 1 deletion dist/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -236,6 +236,13 @@ function getPublicKey(octokit, repo, environment, target) {
else {
const [owner, name] = repo.full_name.split("/");
switch (target) {
case "codespaces":
publicKey = (yield octokit.codespaces.getRepoPublicKey({
owner,
repo: name,
})).data;
exports.publicKeyCache.set(repo, publicKey);
return publicKey;
case "dependabot":
publicKey = (yield octokit.dependabot.getRepoPublicKey({
owner,
Expand Down Expand Up @@ -266,6 +273,14 @@ function setSecretForRepo(octokit, name, secret, repo, environment, dry_run, tar
core.info(`Set \`${name} = ***\` on ${repo.full_name}`);
if (!dry_run) {
switch (target) {
case "codespaces":
return octokit.codespaces.createOrUpdateRepoSecret({
owner: repo_owner,
repo: repo_name,
secret_name: name,
key_id: publicKey.key_id,
encrypted_value,
});
case "dependabot":
return octokit.dependabot.createOrUpdateRepoSecret({
owner: repo_owner,
Expand Down Expand Up @@ -306,6 +321,8 @@ function deleteSecretForRepo(octokit, name, secret, repo, environment, dry_run,
if (!dry_run) {
const action = "DELETE";
switch (target) {
case "codespaces":
return octokit.request(`${action} /repos/${repo.full_name}/codespaces/secrets/${name}`);
case "dependabot":
return octokit.request(`${action} /repos/${repo.full_name}/dependabot/secrets/${name}`);
case "actions":
Expand Down Expand Up @@ -397,7 +414,7 @@ function run() {
core.setFailed(`Secrets: no matches with "${config.SECRETS.join(", ")}"`);
return;
}
const allowedTargets = ["dependabot", "actions"];
const allowedTargets = ["dependabot", "actions", "codespaces"];
if (!allowedTargets.some((x) => x === config.TARGET)) {
core.setFailed(`Target: Value not in supported targets: ${allowedTargets}`);
return;
Expand Down
23 changes: 23 additions & 0 deletions src/github.ts
Original file line number Diff line number Diff line change
Expand Up @@ -184,6 +184,17 @@ export async function getPublicKey(
const [owner, name] = repo.full_name.split("/");

switch (target) {
case "codespaces":
publicKey = (
await octokit.codespaces.getRepoPublicKey({
owner,
repo: name,
})
).data as PublicKey;

publicKeyCache.set(repo, publicKey);

return publicKey;
case "dependabot":
publicKey = (
await octokit.dependabot.getRepoPublicKey({
Expand Down Expand Up @@ -232,6 +243,14 @@ export async function setSecretForRepo(

if (!dry_run) {
switch (target) {
case "codespaces":
return octokit.codespaces.createOrUpdateRepoSecret({
owner: repo_owner,
repo: repo_name,
secret_name: name,
key_id: publicKey.key_id,
encrypted_value,
});
case "dependabot":
return octokit.dependabot.createOrUpdateRepoSecret({
owner: repo_owner,
Expand Down Expand Up @@ -278,6 +297,10 @@ export async function deleteSecretForRepo(
if (!dry_run) {
const action = "DELETE";
switch (target) {
case "codespaces":
return octokit.request(
`${action} /repos/${repo.full_name}/codespaces/secrets/${name}`
);
case "dependabot":
return octokit.request(
`${action} /repos/${repo.full_name}/dependabot/secrets/${name}`
Expand Down
2 changes: 1 addition & 1 deletion src/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ export async function run(): Promise<void> {
return;
}

const allowedTargets = ["dependabot", "actions"];
const allowedTargets = ["dependabot", "actions", "codespaces"];
if (!allowedTargets.some((x) => x === config.TARGET)) {
core.setFailed(
`Target: Value not in supported targets: ${allowedTargets}`
Expand Down

0 comments on commit fca2fa5

Please sign in to comment.