Skip to content

Commit

Permalink
DEVPROD-5141: Fix commit check for prod deploy (#228)
Browse files Browse the repository at this point in the history
  • Loading branch information
sophstad authored Jul 3, 2024
1 parent 3500fcb commit 2114d44
Show file tree
Hide file tree
Showing 6 changed files with 101 additions and 23 deletions.
17 changes: 17 additions & 0 deletions apps/parsley/src/gql/generated/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -622,6 +622,17 @@ export type GeneralSubscription = {
triggerData?: Maybe<Scalars["StringMap"]["output"]>;
};

export type GitHubDynamicTokenPermissionGroup = {
__typename?: "GitHubDynamicTokenPermissionGroup";
name: Scalars["String"]["output"];
permissions: Scalars["StringMap"]["output"];
};

export type GitHubDynamicTokenPermissionGroupInput = {
name: Scalars["String"]["input"];
permissions: Scalars["StringMap"]["input"];
};

export type GitTag = {
__typename?: "GitTag";
pusher: Scalars["String"]["output"];
Expand Down Expand Up @@ -1690,6 +1701,7 @@ export type Project = {
gitTagAuthorizedUsers?: Maybe<Array<Scalars["String"]["output"]>>;
gitTagVersionsEnabled?: Maybe<Scalars["Boolean"]["output"]>;
githubChecksEnabled?: Maybe<Scalars["Boolean"]["output"]>;
githubDynamicTokenPermissionGroups: Array<GitHubDynamicTokenPermissionGroup>;
githubTriggerAliases?: Maybe<Array<Scalars["String"]["output"]>>;
hidden?: Maybe<Scalars["Boolean"]["output"]>;
id: Scalars["String"]["output"];
Expand Down Expand Up @@ -1827,6 +1839,9 @@ export type ProjectInput = {
gitTagAuthorizedUsers?: InputMaybe<Array<Scalars["String"]["input"]>>;
gitTagVersionsEnabled?: InputMaybe<Scalars["Boolean"]["input"]>;
githubChecksEnabled?: InputMaybe<Scalars["Boolean"]["input"]>;
githubDynamicTokenPermissionGroups?: InputMaybe<
Array<GitHubDynamicTokenPermissionGroupInput>
>;
githubTriggerAliases?: InputMaybe<Array<Scalars["String"]["input"]>>;
id: Scalars["String"]["input"];
identifier?: InputMaybe<Scalars["String"]["input"]>;
Expand Down Expand Up @@ -1904,6 +1919,8 @@ export enum ProjectSettingsSection {
Containers = "CONTAINERS",
General = "GENERAL",
GithubAndCommitQueue = "GITHUB_AND_COMMIT_QUEUE",
GithubAppSettings = "GITHUB_APP_SETTINGS",
GithubPermissions = "GITHUB_PERMISSIONS",
Notifications = "NOTIFICATIONS",
PatchAliases = "PATCH_ALIASES",
PeriodicBuilds = "PERIODIC_BUILDS",
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
import Stream from "stream";
import { tagIsValid } from ".";

describe("getCurrentDeployedCommit without mocking https requests", () => {
it("fetches the commit from spruce", async () => {
const { getCurrentlyDeployedCommit } = await import(
"./get-current-deployed-commit"
);
expect(await getCurrentlyDeployedCommit("spruce")).toHaveLength(40);
});

it("fetches the commit from parsley", async () => {
const { getCurrentlyDeployedCommit } = await import(
"./get-current-deployed-commit"
);
expect(await getCurrentlyDeployedCommit("parsley")).toHaveLength(40);
});
});

describe("when get request fails", () => {
beforeEach(() => {
vi.resetModules();
vi.doMock("https", () => ({
default: vi.fn(),
get: vi.fn().mockImplementation((_, cb) => {
const s = new Stream();
cb(s);
s.emit("error", new Error("invalid"));
}),
}));
});

afterEach(() => {
vi.restoreAllMocks();
vi.doUnmock("https");
});

it("gets a local spruce tag", async () => {
const { getCurrentlyDeployedCommit } = await import(
"./get-current-deployed-commit"
);
const app = "spruce";
const commit = await getCurrentlyDeployedCommit(app);
expect(commit).not.toHaveLength(40);
expect(tagIsValid(app, commit)).toBe(true);
});

it("gets a local parsley tag", async () => {
const { getCurrentlyDeployedCommit } = await import(
"./get-current-deployed-commit"
);
const app = "parsley";
const commit = await getCurrentlyDeployedCommit(app);
expect(commit).not.toHaveLength(40);
expect(tagIsValid(app, commit)).toBe(true);
});
});
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { get } from "https";
import { getLatestTag } from ".";
import { getLatestTag, tagIsValid } from ".";
import { DeployableApp } from "../types";

/**
Expand Down Expand Up @@ -47,9 +47,11 @@ export const getCurrentlyDeployedCommit = async (app: DeployableApp) => {
}
}

const commitIsCorrectLength = commit?.length === 40;
commit = commit?.trim();

if (commitIsCorrectLength) {
const commitIsValid = commit?.length === 40 || tagIsValid(app, commit);

if (commitIsValid) {
return commit;
}
throw new Error("No valid commit found");
Expand Down
6 changes: 2 additions & 4 deletions packages/deploy-utils/src/utils/git/git.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -71,10 +71,8 @@ describe("getCurrentlyDeployedCommit", () => {

it("returns a valid local commit", async () => {
vi.mocked(get).mockImplementation(errorMock);
vi.mocked(execSync).mockReturnValue(validCommitString);
expect(await getCurrentlyDeployedCommit("spruce")).toEqual(
validCommitString,
);
vi.mocked(execSync).mockReturnValue("spruce/v1.0.0");
expect(await getCurrentlyDeployedCommit("spruce")).toEqual("spruce/v1.0.0");
expect(vi.mocked(execSync)).toHaveBeenCalledOnce();
});

Expand Down
26 changes: 10 additions & 16 deletions packages/deploy-utils/src/utils/git/tag.test.ts
Original file line number Diff line number Diff line change
@@ -1,31 +1,25 @@
import { getLatestTag } from ".";
import { DeployableApp } from "../types";
import { getLatestTag, tagIsValid } from ".";

describe("getLatestTag", () => {
const currentlyDeployedTagRegex = (app: DeployableApp) =>
new RegExp(`${app}/v\\d+.\\d+.\\d+`);

it("currentlyDeployedTagRegex should match on a known valid tag", () => {
const tag = currentlyDeployedTagRegex("parsley").test("parsley/v1.2.3");
expect(tag).toBeTruthy();
describe("tagIsValid", () => {
it("should match on a known valid tag", () => {
expect(tagIsValid("parsley", "parsley/v1.2.3")).toEqual(true);
});

it("currentlyDeployedTagRegex should not match on the wrong app's tag tag", () => {
const tag = currentlyDeployedTagRegex("parsley").test("spruce/v1.2.3");
expect(tag).toBeFalsy();
it("should not match on the wrong app's tag", () => {
expect(tagIsValid("parsley", "spruce/v1.2.3")).toEqual(false);
});
});

describe("getLatestTag", () => {
it("should return the latest spruce tag", () => {
const app = "spruce";
const latestTag = getLatestTag(app);
const latestTagIsTag = currentlyDeployedTagRegex(app).test(latestTag);
expect(latestTagIsTag).toBeTruthy();
expect(tagIsValid(app, latestTag)).toEqual(true);
});

it("should return the latest parsley tag", () => {
const app = "parsley";
const latestTag = getLatestTag(app);
const latestTagIsTag = currentlyDeployedTagRegex(app).test(latestTag);
expect(latestTagIsTag).toBeTruthy();
expect(tagIsValid(app, latestTag)).toEqual(true);
});
});
10 changes: 10 additions & 0 deletions packages/deploy-utils/src/utils/git/tag.ts
Original file line number Diff line number Diff line change
Expand Up @@ -87,10 +87,20 @@ const pushTags = () => {
}
};

/**
* tagIsValid asserts whether a given string matches a tag for a specified app
* @param app - app with which tag is associated
* @param matchString - string to test against
* @returns - boolean indicating whether matchString is a valid tag
*/
const tagIsValid = (app: DeployableApp, matchString: string) =>
new RegExp(`${app}/v\\d+.\\d+.\\d+`).test(matchString);

export {
createTagAndPush,
deleteTag,
getLatestTag,
getTagFromCommit,
pushTags,
tagIsValid,
};

0 comments on commit 2114d44

Please sign in to comment.