Skip to content

Commit

Permalink
fix(syncer): Fix for windows binaries in action runner syncer (philip…
Browse files Browse the repository at this point in the history
…s-labs#1716)

* Updated test data

* Added an OS case for each test.

* Added lookup for binary os label

* Remove fixed values

* Fix formatting

* Use Record<T1,T2>

* Fix references to `win` in variable descriptions.

* Updated to latest runners file list

* Fix formatting

* Update lock file for windows example
  • Loading branch information
ScottGuymer committed Feb 10, 2022
1 parent fb53335 commit 63e0e27
Show file tree
Hide file tree
Showing 7 changed files with 4,448 additions and 2,364 deletions.
2 changes: 2 additions & 0 deletions examples/windows/.terraform.lock.hcl

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,22 @@ jest.mock('aws-sdk', () => ({
}));

const bucketName = 'my-bucket';
const bucketObjectKey = 'actions-runner-linux.tar.gz';
const objectExtension: Record<string, string> = {
linux: '.tar.gz',
win: '.zip',
};
const bucketObjectNames: Record<string, string> = {
linux: `actions-runner-linux${objectExtension['linux']}`,
win: `actions-runner-windows${objectExtension['win']}`,
};

const bucketObjectKey = (os: string) => bucketObjectNames[os];

const runnerOs = [['linux'], ['win']];

const latestRelease = '2.287.0';
const latestPreRelease = '2.287.1';

beforeEach(() => {
jest.clearAllMocks();
});
Expand All @@ -51,19 +66,22 @@ jest.setTimeout(60 * 1000);
describe('Synchronize action distribution.', () => {
beforeEach(() => {
process.env.S3_BUCKET_NAME = bucketName;
process.env.S3_OBJECT_KEY = bucketObjectKey;
process.env.GITHUB_RUNNER_ALLOW_PRERELEASE_BINARIES = 'false';

mockOctokit.repos.listReleases.mockImplementation(() => ({
data: listReleases,
}));
});

it('Distribution is up-to-date with latest release.', async () => {
test.each(runnerOs)('%p Distribution is up-to-date with latest release.', async (os) => {
process.env.S3_OBJECT_KEY = bucketObjectKey(os);
process.env.GITHUB_RUNNER_OS = os;
mockS3.getObjectTagging.mockImplementation(() => {
return {
promise() {
return Promise.resolve({ TagSet: [{ Key: 'name', Value: 'actions-runner-linux-x64-2.285.1.tar.gz' }] });
return Promise.resolve({
TagSet: [{ Key: 'name', Value: `actions-runner-${os}-x64-${latestRelease}${objectExtension[os]}` }],
});
},
};
});
Expand All @@ -72,22 +90,52 @@ describe('Synchronize action distribution.', () => {
expect(mockOctokit.repos.listReleases).toBeCalledTimes(1);
expect(mockS3.getObjectTagging).toBeCalledWith({
Bucket: bucketName,
Key: bucketObjectKey,
Key: bucketObjectKey(os),
});
expect(mockS3.upload).toBeCalledTimes(0);
});

it('Distribution is up-to-date with latest release when there are no prereleases.', async () => {
test.each(runnerOs)(
'%p Distribution is up-to-date with latest release when there are no prereleases.',
async (os) => {
process.env.S3_OBJECT_KEY = bucketObjectKey(os);
process.env.GITHUB_RUNNER_OS = os;
process.env.GITHUB_RUNNER_ALLOW_PRERELEASE_BINARIES = 'true';
const releases = listReleases.slice(1);

mockOctokit.repos.listReleases.mockImplementation(() => ({
data: releases,
}));
mockS3.getObjectTagging.mockImplementation(() => {
return {
promise() {
return Promise.resolve({
TagSet: [{ Key: 'name', Value: `actions-runner-${os}-x64-${latestRelease}${objectExtension[os]}` }],
});
},
};
});

await sync();
expect(mockOctokit.repos.listReleases).toBeCalledTimes(1);
expect(mockS3.getObjectTagging).toBeCalledWith({
Bucket: bucketName,
Key: bucketObjectKey(os),
});
expect(mockS3.upload).toBeCalledTimes(0);
},
);

test.each(runnerOs)('%p Distribution is up-to-date with latest prerelease.', async (os) => {
process.env.S3_OBJECT_KEY = bucketObjectKey(os);
process.env.GITHUB_RUNNER_OS = os;
process.env.GITHUB_RUNNER_ALLOW_PRERELEASE_BINARIES = 'true';
const releases = listReleases.slice(1);

mockOctokit.repos.listReleases.mockImplementation(() => ({
data: releases,
}));
mockS3.getObjectTagging.mockImplementation(() => {
return {
promise() {
return Promise.resolve({ TagSet: [{ Key: 'name', Value: 'actions-runner-linux-x64-2.285.1.tar.gz' }] });
return Promise.resolve({
TagSet: [{ Key: 'name', Value: `actions-runner-${os}-x64-${latestPreRelease}${objectExtension[os]}` }],
});
},
};
});
Expand All @@ -96,17 +144,20 @@ describe('Synchronize action distribution.', () => {
expect(mockOctokit.repos.listReleases).toBeCalledTimes(1);
expect(mockS3.getObjectTagging).toBeCalledWith({
Bucket: bucketName,
Key: bucketObjectKey,
Key: bucketObjectKey(os),
});
expect(mockS3.upload).toBeCalledTimes(0);
});

it('Distribution is up-to-date with latest prerelease.', async () => {
process.env.GITHUB_RUNNER_ALLOW_PRERELEASE_BINARIES = 'true';
test.each(runnerOs)('%p Distribution should update to release.', async (os) => {
process.env.S3_OBJECT_KEY = bucketObjectKey(os);
process.env.GITHUB_RUNNER_OS = os;
mockS3.getObjectTagging.mockImplementation(() => {
return {
promise() {
return Promise.resolve({ TagSet: [{ Key: 'name', Value: 'actions-runner-linux-x64-2.286.0.tar.gz' }] });
return Promise.resolve({
TagSet: [{ Key: 'name', Value: `actions-runner-${os}-x64-0${objectExtension[os]}` }],
});
},
};
});
Expand All @@ -115,32 +166,16 @@ describe('Synchronize action distribution.', () => {
expect(mockOctokit.repos.listReleases).toBeCalledTimes(1);
expect(mockS3.getObjectTagging).toBeCalledWith({
Bucket: bucketName,
Key: bucketObjectKey,
});
expect(mockS3.upload).toBeCalledTimes(0);
});

it('Distribution should update to release.', async () => {
mockS3.getObjectTagging.mockImplementation(() => {
return {
promise() {
return Promise.resolve({ TagSet: [{ Key: 'name', Value: 'actions-runner-linux-x64-0.tar.gz' }] });
},
};
});

await sync();
expect(mockOctokit.repos.listReleases).toBeCalledTimes(1);
expect(mockS3.getObjectTagging).toBeCalledWith({
Bucket: bucketName,
Key: bucketObjectKey,
Key: bucketObjectKey(os),
});
expect(mockS3.upload).toBeCalledTimes(1);
const s3JsonBody = mockS3.upload.mock.calls[0][0];
expect(s3JsonBody['Tagging']).toEqual('name=actions-runner-linux-x64-2.285.1.tar.gz');
expect(s3JsonBody['Tagging']).toEqual(`name=actions-runner-${os}-x64-${latestRelease}${objectExtension[os]}`);
});

it('Distribution should update to release if there are no pre-releases.', async () => {
test.each(runnerOs)('%p Distribution should update to release if there are no pre-releases.', async (os) => {
process.env.S3_OBJECT_KEY = bucketObjectKey(os);
process.env.GITHUB_RUNNER_OS = os;
process.env.GITHUB_RUNNER_ALLOW_PRERELEASE_BINARIES = 'true';
const releases = listReleases.slice(1);

Expand All @@ -150,7 +185,9 @@ describe('Synchronize action distribution.', () => {
mockS3.getObjectTagging.mockImplementation(() => {
return {
promise() {
return Promise.resolve({ TagSet: [{ Key: 'name', Value: 'actions-runner-linux-x64-0.tar.gz' }] });
return Promise.resolve({
TagSet: [{ Key: 'name', Value: `actions-runner-${os}-x64-0${objectExtension[os]}` }],
});
},
};
});
Expand All @@ -159,19 +196,23 @@ describe('Synchronize action distribution.', () => {
expect(mockOctokit.repos.listReleases).toBeCalledTimes(1);
expect(mockS3.getObjectTagging).toBeCalledWith({
Bucket: bucketName,
Key: bucketObjectKey,
Key: bucketObjectKey(os),
});
expect(mockS3.upload).toBeCalledTimes(1);
const s3JsonBody = mockS3.upload.mock.calls[0][0];
expect(s3JsonBody['Tagging']).toEqual('name=actions-runner-linux-x64-2.285.1.tar.gz');
expect(s3JsonBody['Tagging']).toEqual(`name=actions-runner-${os}-x64-${latestRelease}${objectExtension[os]}`);
});

it('Distribution should update to prerelease.', async () => {
test.each(runnerOs)('%p Distribution should update to prerelease.', async (os) => {
process.env.S3_OBJECT_KEY = bucketObjectKey(os);
process.env.GITHUB_RUNNER_OS = os;
process.env.GITHUB_RUNNER_ALLOW_PRERELEASE_BINARIES = 'true';
mockS3.getObjectTagging.mockImplementation(() => {
return {
promise() {
return Promise.resolve({ TagSet: [{ Key: 'name', Value: 'actions-runner-linux-x64-0.tar.gz' }] });
return Promise.resolve({
TagSet: [{ Key: 'name', Value: `actions-runner-${os}-x64-0${objectExtension[os]}` }],
});
},
};
});
Expand All @@ -180,14 +221,16 @@ describe('Synchronize action distribution.', () => {
expect(mockOctokit.repos.listReleases).toBeCalledTimes(1);
expect(mockS3.getObjectTagging).toBeCalledWith({
Bucket: bucketName,
Key: bucketObjectKey,
Key: bucketObjectKey(os),
});
expect(mockS3.upload).toBeCalledTimes(1);
const s3JsonBody = mockS3.upload.mock.calls[0][0];
expect(s3JsonBody['Tagging']).toEqual('name=actions-runner-linux-x64-2.286.0.tar.gz');
expect(s3JsonBody['Tagging']).toEqual(`name=actions-runner-${os}-x64-${latestPreRelease}${objectExtension[os]}`);
});

it('Distribution should not update to prerelease if there is a newer release.', async () => {
test.each(runnerOs)('%p Distribution should not update to prerelease if there is a newer release.', async (os) => {
process.env.S3_OBJECT_KEY = bucketObjectKey(os);
process.env.GITHUB_RUNNER_OS = os;
process.env.GITHUB_RUNNER_ALLOW_PRERELEASE_BINARIES = 'true';
const releases = listReleases;
releases[0].prerelease = false;
Expand All @@ -199,7 +242,9 @@ describe('Synchronize action distribution.', () => {
mockS3.getObjectTagging.mockImplementation(() => {
return {
promise() {
return Promise.resolve({ TagSet: [{ Key: 'name', Value: 'actions-runner-linux-x64-0.tar.gz' }] });
return Promise.resolve({
TagSet: [{ Key: 'name', Value: `actions-runner-${os}-x64-0${objectExtension[os]}` }],
});
},
};
});
Expand All @@ -208,14 +253,16 @@ describe('Synchronize action distribution.', () => {
expect(mockOctokit.repos.listReleases).toBeCalledTimes(1);
expect(mockS3.getObjectTagging).toBeCalledWith({
Bucket: bucketName,
Key: bucketObjectKey,
Key: bucketObjectKey(os),
});
expect(mockS3.upload).toBeCalledTimes(1);
const s3JsonBody = mockS3.upload.mock.calls[0][0];
expect(s3JsonBody['Tagging']).toEqual('name=actions-runner-linux-x64-2.286.0.tar.gz');
expect(s3JsonBody['Tagging']).toEqual(`name=actions-runner-${os}-x64-${latestPreRelease}${objectExtension[os]}`);
});

it('No tag in S3, distribution should update.', async () => {
test.each(runnerOs)('%p No tag in S3, distribution should update.', async (os) => {
process.env.S3_OBJECT_KEY = bucketObjectKey(os);
process.env.GITHUB_RUNNER_OS = os;
mockS3.getObjectTagging.mockImplementation(() => {
return {
promise() {
Expand All @@ -228,12 +275,14 @@ describe('Synchronize action distribution.', () => {
expect(mockOctokit.repos.listReleases).toBeCalledTimes(1);
expect(mockS3.getObjectTagging).toBeCalledWith({
Bucket: bucketName,
Key: bucketObjectKey,
Key: bucketObjectKey(os),
});
expect(mockS3.upload).toBeCalledTimes(1);
});

it('Tags, but no version, distribution should update.', async () => {
test.each(runnerOs)('%p Tags, but no version, distribution should update.', async (os) => {
process.env.S3_OBJECT_KEY = bucketObjectKey(os);
process.env.GITHUB_RUNNER_OS = os;
mockS3.getObjectTagging.mockImplementation(() => {
return {
promise() {
Expand All @@ -246,7 +295,7 @@ describe('Synchronize action distribution.', () => {
expect(mockOctokit.repos.listReleases).toBeCalledTimes(1);
expect(mockS3.getObjectTagging).toBeCalledWith({
Bucket: bucketName,
Key: bucketObjectKey,
Key: bucketObjectKey(os),
});
expect(mockS3.upload).toBeCalledTimes(1);
});
Expand All @@ -256,7 +305,7 @@ describe('No release assets found.', () => {
const errorMessage = 'Cannot find GitHub release asset.';
beforeEach(() => {
process.env.S3_BUCKET_NAME = bucketName;
process.env.S3_OBJECT_KEY = bucketObjectKey;
process.env.S3_OBJECT_KEY = bucketObjectKey('linux');
});

it('Empty list of assets.', async () => {
Expand All @@ -267,7 +316,9 @@ describe('No release assets found.', () => {
await expect(sync()).rejects.toThrow(errorMessage);
});

it('No linux x64 asset.', async () => {
test.each(runnerOs)('No %p x64 asset.', async (os) => {
process.env.S3_OBJECT_KEY = bucketObjectKey(os);
process.env.GITHUB_RUNNER_OS = os;
mockOctokit.repos.listReleases.mockImplementation(() => ({
data: [listReleasesNoLinux],
}));
Expand All @@ -293,7 +344,7 @@ describe('Invalid config', () => {
});
it('No bucket.', async () => {
delete process.env.S3_BUCKET_NAME;
process.env.S3_OBJECT_KEY = bucketObjectKey;
process.env.S3_OBJECT_KEY = bucketObjectKey('linux');
await expect(sync()).rejects.toThrow(errorMessage);
});
it('No object key.', async () => {
Expand All @@ -307,35 +358,16 @@ describe('Synchronize action distribution for arm64.', () => {
const errorMessage = 'Cannot find GitHub release asset.';
beforeEach(() => {
process.env.S3_BUCKET_NAME = bucketName;
process.env.S3_OBJECT_KEY = bucketObjectKey;
process.env.GITHUB_RUNNER_ARCHITECTURE = 'arm64';
});

it('No linux arm64 asset.', async () => {
test.each(runnerOs)('No %p arm64 asset.', async (os) => {
process.env.S3_OBJECT_KEY = bucketObjectKey(os);
process.env.GITHUB_RUNNER_OS = os;
mockOctokit.repos.listReleases.mockImplementation(() => ({
data: [listReleasesNoArm64],
}));

await expect(sync()).rejects.toThrow(errorMessage);
});
});

describe('Synchronize action distribution for windows.', () => {
const errorMessage = 'Cannot find GitHub release asset.';
beforeEach(() => {
process.env.S3_BUCKET_NAME = bucketName;
process.env.S3_OBJECT_KEY = bucketObjectKey;
process.env.GITHUB_RUNNER_OS = 'win';
});

it('No win asset.', async () => {
mockOctokit.repos.listReleases.mockImplementation(() => ({
data: listReleases.map((release) => ({
...release,
assets: release.assets.filter((asset) => !asset.name.includes('win')),
})),
}));

await expect(sync()).rejects.toThrow(errorMessage);
});
});

0 comments on commit 63e0e27

Please sign in to comment.