Skip to content

Commit f4d4948

Browse files
committed
🎉 Start LocalStack GitHub Actions login
1 parent 9ca2312 commit f4d4948

14 files changed

Lines changed: 4090 additions & 0 deletions

‎.eslintignore‎

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
dist/
2+
lib/
3+
node_modules/
4+
jest.config.js

‎.eslintrc.json‎

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
{
2+
"plugins": ["jest", "@typescript-eslint"],
3+
"extends": ["plugin:github/recommended"],
4+
"parser": "@typescript-eslint/parser",
5+
"parserOptions": {
6+
"ecmaVersion": 9,
7+
"sourceType": "module",
8+
"project": "./tsconfig.json"
9+
},
10+
"rules": {
11+
"i18n-text/no-en": "off",
12+
"eslint-comments/no-use": "off",
13+
"import/no-namespace": "off",
14+
"no-unused-vars": "off",
15+
"@typescript-eslint/no-unused-vars": "error",
16+
"@typescript-eslint/explicit-member-accessibility": ["error", {"accessibility": "no-public"}],
17+
"@typescript-eslint/no-require-imports": "error",
18+
"@typescript-eslint/array-type": "error",
19+
"@typescript-eslint/await-thenable": "error",
20+
"@typescript-eslint/ban-ts-comment": "error",
21+
"camelcase": "off",
22+
"@typescript-eslint/consistent-type-assertions": "error",
23+
"@typescript-eslint/explicit-function-return-type": ["error", {"allowExpressions": true}],
24+
"@typescript-eslint/func-call-spacing": ["error", "never"],
25+
"@typescript-eslint/no-array-constructor": "error",
26+
"@typescript-eslint/no-empty-interface": "error",
27+
"@typescript-eslint/no-explicit-any": "off",
28+
"@typescript-eslint/no-extraneous-class": "error",
29+
"@typescript-eslint/no-for-in-array": "error",
30+
"@typescript-eslint/no-inferrable-types": "error",
31+
"@typescript-eslint/no-misused-new": "error",
32+
"@typescript-eslint/no-namespace": "error",
33+
"@typescript-eslint/no-non-null-assertion": "warn",
34+
"@typescript-eslint/no-unnecessary-qualifier": "error",
35+
"@typescript-eslint/no-unnecessary-type-assertion": "error",
36+
"@typescript-eslint/no-useless-constructor": "error",
37+
"@typescript-eslint/no-var-requires": "error",
38+
"@typescript-eslint/prefer-for-of": "warn",
39+
"@typescript-eslint/prefer-function-type": "warn",
40+
"@typescript-eslint/prefer-includes": "error",
41+
"@typescript-eslint/prefer-string-starts-ends-with": "error",
42+
"@typescript-eslint/promise-function-async": "error",
43+
"@typescript-eslint/require-array-sort-compare": "error",
44+
"@typescript-eslint/restrict-plus-operands": "error",
45+
"semi": "off",
46+
"@typescript-eslint/semi": ["error", "never"],
47+
"@typescript-eslint/type-annotation-spacing": "error",
48+
"@typescript-eslint/unbound-method": "error",
49+
"no-console": ["warn", { "allow": ["info","warn","error"]}]
50+
},
51+
"env": {
52+
"node": true,
53+
"es6": true,
54+
"jest/globals": true
55+
}
56+
}

‎.gitattributes‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
dist/** -diff linguist-generated=true

‎.prettierignore‎

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
dist/
2+
lib/
3+
node_modules/

‎.prettierrc.json‎

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
{
2+
"printWidth": 80,
3+
"tabWidth": 2,
4+
"useTabs": false,
5+
"semi": false,
6+
"singleQuote": true,
7+
"trailingComma": "none",
8+
"bracketSpacing": false,
9+
"arrowParens": "avoid"
10+
}

‎__tests__/main.test.ts‎

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
import {expect, jest, test} from '@jest/globals'
2+
import {login, logout} from '../src/login'
3+
import * as path from 'path'
4+
import * as exec from '@actions/exec'
5+
6+
process.env['RUNNER_TEMP'] = path.join(__dirname, 'runner')
7+
8+
test('loginStandard calls exec', async () => {
9+
// @ts-ignore
10+
const execSpy = jest
11+
.spyOn(exec, 'getExecOutput')
12+
.mockImplementation(async () => {
13+
// @ts-ignore
14+
return {
15+
exitCode: expect.any(Number),
16+
stdout: expect.any(Function),
17+
stderr: expect.any(Function)
18+
} as exec.ExecOutput
19+
})
20+
21+
const email = 'hello'
22+
const password = 'world'
23+
24+
await login(email, password)
25+
26+
expect(execSpy).toHaveBeenCalledWith(
27+
`localstack`,
28+
['login', '--password-stdin', '--username', email],
29+
{
30+
input: Buffer.from(password),
31+
silent: true,
32+
ignoreReturnCode: true
33+
}
34+
)
35+
})
36+
37+
test('logout calls exec', async () => {
38+
// @ts-ignore
39+
const execSpy = jest
40+
.spyOn(exec, 'getExecOutput')
41+
.mockImplementation(async () => {
42+
// @ts-ignore
43+
return {
44+
exitCode: expect.any(Number),
45+
stdout: expect.any(Function),
46+
stderr: expect.any(Function)
47+
} as exec.ExecOutput
48+
})
49+
50+
await logout()
51+
52+
expect(execSpy).toHaveBeenCalledWith(`localstack`, ['logout'], {
53+
ignoreReturnCode: true
54+
})
55+
})

‎jest.config.js‎

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
module.exports = {
2+
clearMocks: true,
3+
moduleFileExtensions: ['js', 'ts'],
4+
testMatch: ['**/*.test.ts'],
5+
transform: {
6+
'^.+\\.ts$': 'ts-jest'
7+
},
8+
verbose: true
9+
}

‎lib/login.js‎

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
"use strict";
2+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3+
if (k2 === undefined) k2 = k;
4+
var desc = Object.getOwnPropertyDescriptor(m, k);
5+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6+
desc = { enumerable: true, get: function() { return m[k]; } };
7+
}
8+
Object.defineProperty(o, k2, desc);
9+
}) : (function(o, m, k, k2) {
10+
if (k2 === undefined) k2 = k;
11+
o[k2] = m[k];
12+
}));
13+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14+
Object.defineProperty(o, "default", { enumerable: true, value: v });
15+
}) : function(o, v) {
16+
o["default"] = v;
17+
});
18+
var __importStar = (this && this.__importStar) || function (mod) {
19+
if (mod && mod.__esModule) return mod;
20+
var result = {};
21+
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
22+
__setModuleDefault(result, mod);
23+
return result;
24+
};
25+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
26+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
27+
return new (P || (P = Promise))(function (resolve, reject) {
28+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
29+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
30+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
31+
step((generator = generator.apply(thisArg, _arguments || [])).next());
32+
});
33+
};
34+
Object.defineProperty(exports, "__esModule", { value: true });
35+
exports.logout = exports.login = void 0;
36+
const core = __importStar(require("@actions/core"));
37+
const exec = __importStar(require("@actions/exec"));
38+
function login(email, password) {
39+
return __awaiter(this, void 0, void 0, function* () {
40+
if (!email || !password) {
41+
throw new Error('Email and password required');
42+
}
43+
const args = ['login', '--password-stdin', '--username', email];
44+
core.info(`Logging in`);
45+
const res = yield exec.getExecOutput('localstack', args, {
46+
ignoreReturnCode: true,
47+
silent: true,
48+
input: Buffer.from(password)
49+
});
50+
if (res.stderr.length > 0 && res.exitCode !== 0) {
51+
throw new Error(res.stderr.trim());
52+
}
53+
core.info(`Login Succeeded!`);
54+
});
55+
}
56+
exports.login = login;
57+
function logout() {
58+
return __awaiter(this, void 0, void 0, function* () {
59+
const res = yield exec.getExecOutput('localstack', ['logout'], {
60+
ignoreReturnCode: true
61+
});
62+
if (res.stderr.length > 0 && res.exitCode !== 0) {
63+
core.warning(res.stderr.trim());
64+
}
65+
});
66+
}
67+
exports.logout = logout;

‎lib/main.js‎

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
"use strict";
2+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3+
if (k2 === undefined) k2 = k;
4+
var desc = Object.getOwnPropertyDescriptor(m, k);
5+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6+
desc = { enumerable: true, get: function() { return m[k]; } };
7+
}
8+
Object.defineProperty(o, k2, desc);
9+
}) : (function(o, m, k, k2) {
10+
if (k2 === undefined) k2 = k;
11+
o[k2] = m[k];
12+
}));
13+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14+
Object.defineProperty(o, "default", { enumerable: true, value: v });
15+
}) : function(o, v) {
16+
o["default"] = v;
17+
});
18+
var __importStar = (this && this.__importStar) || function (mod) {
19+
if (mod && mod.__esModule) return mod;
20+
var result = {};
21+
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
22+
__setModuleDefault(result, mod);
23+
return result;
24+
};
25+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
26+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
27+
return new (P || (P = Promise))(function (resolve, reject) {
28+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
29+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
30+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
31+
step((generator = generator.apply(thisArg, _arguments || [])).next());
32+
});
33+
};
34+
Object.defineProperty(exports, "__esModule", { value: true });
35+
const core = __importStar(require("@actions/core"));
36+
const login_1 = require("./login");
37+
function setup() {
38+
return __awaiter(this, void 0, void 0, function* () {
39+
const email = core.getInput('email');
40+
const password = core.getInput('password');
41+
core.saveState('email', email);
42+
yield (0, login_1.login)(email, password);
43+
});
44+
}
45+
function teardown() {
46+
return __awaiter(this, void 0, void 0, function* () {
47+
yield (0, login_1.logout)();
48+
});
49+
}
50+
function run() {
51+
return __awaiter(this, void 0, void 0, function* () {
52+
try {
53+
if (core.getState('isPost')) {
54+
yield teardown();
55+
}
56+
else {
57+
core.saveState('isPost', 'true');
58+
yield setup();
59+
}
60+
}
61+
catch (error) {
62+
if (error instanceof Error) {
63+
core.setFailed(error.message);
64+
}
65+
}
66+
});
67+
}
68+
run();

‎package.json‎

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
{
2+
"name": "localstack-github-actions-login",
3+
"version": "0.1.0",
4+
"private": true,
5+
"main": "lib/main.js",
6+
"scripts": {
7+
"build": "tsc",
8+
"format": "prettier --write '**/*.ts'",
9+
"format-check": "prettier --check '**/*.ts'",
10+
"lint": "eslint src/**/*.ts",
11+
"package": "ncc build --source-map --license licenses.txt",
12+
"test": "jest",
13+
"all": "yarn run build && yarn run format && yarn run lint && yarn run package && yarn test"
14+
},
15+
"repository": {
16+
"type": "git",
17+
"url": "git+https://github.com/HarshCasper/localstack-github-actions-login.git"
18+
},
19+
"keywords": [
20+
"localstack",
21+
"github-actions",
22+
"github",
23+
"aws"
24+
],
25+
"author": "Harsh Mishra",
26+
"license": "Apache-2.0",
27+
"dependencies": {
28+
"yarn": "^1.22.19"
29+
},
30+
"devDependencies": {
31+
"@actions/core": "^1.10.0",
32+
"@actions/exec": "^1.1.1",
33+
"@types/node": "^18.11.4",
34+
"@typescript-eslint/parser": "^5.41.0",
35+
"@vercel/ncc": "^0.34.0",
36+
"eslint": "^8.26.0",
37+
"eslint-plugin-github": "^4.4.0",
38+
"eslint-plugin-jest": "^27.1.3",
39+
"jest": "^29.2.2",
40+
"js-yaml": "^4.1.0",
41+
"prettier": "2.7.1",
42+
"ts-jest": "^29.0.3",
43+
"typescript": "^4.8.4"
44+
}
45+
}

0 commit comments

Comments
 (0)