Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
Merge pull request #308 from actions/aiyan/v1-release
Cherry-pick commits for v1
  • Loading branch information
Aiqiao Yan authored and GitHub committed May 14, 2020
2 parents 70655ec + 3f662ca commit d974700
Show file tree
Hide file tree
Showing 10 changed files with 790 additions and 167 deletions.
111 changes: 95 additions & 16 deletions .github/workflows/workflow.yml
Expand Up @@ -4,51 +4,130 @@ on:
pull_request:
branches:
- master
- releases/**
paths-ignore:
- '**.md'
push:
branches:
- master
- releases/**
paths-ignore:
- '**.md'

jobs:
test:
name: Test on ${{ matrix.os }}

# Build and unit test
build:
strategy:
matrix:
os: [ubuntu-latest, windows-latest, macOS-latest]
fail-fast: false

runs-on: ${{ matrix.os }}

steps:
- uses: actions/checkout@v1

- uses: actions/setup-node@v1
- name: Checkout
uses: actions/checkout@v2
- name: Setup Node.js
uses: actions/setup-node@v1
with:
node-version: '12.x'

- name: Get npm cache directory
- name: Determine npm cache directory
id: npm-cache
run: |
echo "::set-output name=dir::$(npm config get cache)"
- uses: actions/cache@v1
- name: Restore npm cache
uses: actions/cache@v1
with:
path: ${{ steps.npm-cache.outputs.dir }}
key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }}
restore-keys: |
${{ runner.os }}-node-
- run: npm ci

- name: Prettier Format Check
run: npm run format-check

- name: ESLint Check
run: npm run lint

- name: Build & Test
run: npm run test

# End to end save and restore
test-save:
strategy:
matrix:
os: [ubuntu-latest, windows-latest, macOS-latest]
fail-fast: false
runs-on: ${{ matrix.os }}
steps:
- name: Checkout
uses: actions/checkout@v2
- name: Generate files
shell: bash
run: __tests__/create-cache-files.sh ${{ runner.os }}
- name: Save cache
uses: ./
with:
key: test-${{ runner.os }}-${{ github.run_id }}
path: test-cache
test-restore:
needs: test-save
strategy:
matrix:
os: [ubuntu-latest, windows-latest, macOS-latest]
fail-fast: false
runs-on: ${{ matrix.os }}
steps:
- name: Checkout
uses: actions/checkout@v2
- name: Restore cache
uses: ./
with:
key: test-${{ runner.os }}-${{ github.run_id }}
path: test-cache
- name: Verify cache
shell: bash
run: __tests__/verify-cache-files.sh ${{ runner.os }}

# End to end with proxy
test-proxy-save:
runs-on: ubuntu-latest
container:
image: ubuntu:latest
options: --dns 127.0.0.1
services:
squid-proxy:
image: datadog/squid:latest
ports:
- 3128:3128
env:
https_proxy: http://squid-proxy:3128
steps:
- name: Checkout
uses: actions/checkout@v2
- name: Generate files
run: __tests__/create-cache-files.sh proxy
- name: Save cache
uses: ./
with:
key: test-proxy-${{ github.run_id }}
path: test-cache
test-proxy-restore:
needs: test-proxy-save
runs-on: ubuntu-latest
container:
image: ubuntu:latest
options: --dns 127.0.0.1
services:
squid-proxy:
image: datadog/squid:latest
ports:
- 3128:3128
env:
https_proxy: http://squid-proxy:3128
steps:
- name: Checkout
uses: actions/checkout@v2
- name: Restore cache
uses: ./
with:
key: test-proxy-${{ github.run_id }}
path: test-cache
- name: Verify cache
run: __tests__/verify-cache-files.sh proxy
144 changes: 144 additions & 0 deletions __tests__/cacheHttpsClient.test.ts
@@ -0,0 +1,144 @@
import { retry } from "../src/cacheHttpClient";
import * as testUtils from "../src/utils/testUtils";

afterEach(() => {
testUtils.clearInputs();
});

interface TestResponse {
statusCode: number;
result: string | null;
}

function handleResponse(
response: TestResponse | undefined
): Promise<TestResponse> {
if (!response) {
fail("Retry method called too many times");
}

if (response.statusCode === 999) {
throw Error("Test Error");
} else {
return Promise.resolve(response);
}
}

async function testRetryExpectingResult(
responses: Array<TestResponse>,
expectedResult: string | null
): Promise<void> {
responses = responses.reverse(); // Reverse responses since we pop from end

const actualResult = await retry(
"test",
() => handleResponse(responses.pop()),
(response: TestResponse) => response.statusCode
);

expect(actualResult.result).toEqual(expectedResult);
}

async function testRetryExpectingError(
responses: Array<TestResponse>
): Promise<void> {
responses = responses.reverse(); // Reverse responses since we pop from end

expect(
retry(
"test",
() => handleResponse(responses.pop()),
(response: TestResponse) => response.statusCode
)
).rejects.toBeInstanceOf(Error);
}

test("retry works on successful response", async () => {
await testRetryExpectingResult(
[
{
statusCode: 200,
result: "Ok"
}
],
"Ok"
);
});

test("retry works after retryable status code", async () => {
await testRetryExpectingResult(
[
{
statusCode: 503,
result: null
},
{
statusCode: 200,
result: "Ok"
}
],
"Ok"
);
});

test("retry fails after exhausting retries", async () => {
await testRetryExpectingError([
{
statusCode: 503,
result: null
},
{
statusCode: 503,
result: null
},
{
statusCode: 200,
result: "Ok"
}
]);
});

test("retry fails after non-retryable status code", async () => {
await testRetryExpectingError([
{
statusCode: 500,
result: null
},
{
statusCode: 200,
result: "Ok"
}
]);
});

test("retry works after error", async () => {
await testRetryExpectingResult(
[
{
statusCode: 999,
result: null
},
{
statusCode: 200,
result: "Ok"
}
],
"Ok"
);
});

test("retry returns after client error", async () => {
await testRetryExpectingResult(
[
{
statusCode: 400,
result: null
},
{
statusCode: 200,
result: "Ok"
}
],
null
);
});
11 changes: 11 additions & 0 deletions __tests__/create-cache-files.sh
@@ -0,0 +1,11 @@
#!/bin/sh

# Validate args
prefix="$1"
if [ -z "$prefix" ]; then
echo "Must supply prefix argument"
exit 1
fi

mkdir test-cache
echo "$prefix $GITHUB_RUN_ID" > test-cache/test-file.txt
44 changes: 36 additions & 8 deletions __tests__/tar.test.ts
Expand Up @@ -2,6 +2,8 @@ import * as exec from "@actions/exec";
import * as io from "@actions/io";
import * as tar from "../src/tar";

import fs = require("fs");

jest.mock("@actions/exec");
jest.mock("@actions/io");

Expand All @@ -11,31 +13,57 @@ beforeAll(() => {
});
});

test("extract tar", async () => {
test("extract BSD tar", async () => {
const mkdirMock = jest.spyOn(io, "mkdirP");
const execMock = jest.spyOn(exec, "exec");

const archivePath = "cache.tar";
const IS_WINDOWS = process.platform === "win32";
const archivePath = IS_WINDOWS
? `${process.env["windir"]}\\fakepath\\cache.tar`
: "cache.tar";
const targetDirectory = "~/.npm/cache";
await tar.extractTar(archivePath, targetDirectory);

expect(mkdirMock).toHaveBeenCalledWith(targetDirectory);

const IS_WINDOWS = process.platform === "win32";
const tarPath = IS_WINDOWS
? `${process.env["windir"]}\\System32\\tar.exe`
: "tar";
expect(execMock).toHaveBeenCalledTimes(1);
expect(execMock).toHaveBeenCalledWith(`"${tarPath}"`, [
"-xz",
"-f",
archivePath,
IS_WINDOWS ? archivePath.replace(/\\/g, "/") : archivePath,
"-C",
targetDirectory
IS_WINDOWS ? targetDirectory?.replace(/\\/g, "/") : targetDirectory
]);
});

test("create tar", async () => {
test("extract GNU tar", async () => {
const IS_WINDOWS = process.platform === "win32";
if (IS_WINDOWS) {
jest.spyOn(fs, "existsSync").mockReturnValueOnce(false);
jest.spyOn(tar, "isGnuTar").mockReturnValue(Promise.resolve(true));

const execMock = jest.spyOn(exec, "exec");
const archivePath = `${process.env["windir"]}\\fakepath\\cache.tar`;
const targetDirectory = "~/.npm/cache";

await tar.extractTar(archivePath, targetDirectory);

expect(execMock).toHaveBeenCalledTimes(1);
expect(execMock).toHaveBeenLastCalledWith(`"tar"`, [
"-xz",
"-f",
archivePath.replace(/\\/g, "/"),
"-C",
targetDirectory?.replace(/\\/g, "/"),
"--force-local"
]);
}
});

test("create BSD tar", async () => {
const execMock = jest.spyOn(exec, "exec");

const archivePath = "cache.tar";
Expand All @@ -50,9 +78,9 @@ test("create tar", async () => {
expect(execMock).toHaveBeenCalledWith(`"${tarPath}"`, [
"-cz",
"-f",
archivePath,
IS_WINDOWS ? archivePath.replace(/\\/g, "/") : archivePath,
"-C",
sourceDirectory,
IS_WINDOWS ? sourceDirectory?.replace(/\\/g, "/") : sourceDirectory,
"."
]);
});

0 comments on commit d974700

Please sign in to comment.