Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
65 changes: 65 additions & 0 deletions .github/workflows/cli-ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
name: CI Pipeline

on:
push:
branches:
- main
pull_request:
branches:
- main

jobs:
test:
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v4

- name: Set up Node.js
uses: actions/setup-node@v4
with:
node-version: 20
cache: "npm"

- name: Install dependencies
run: npm install

- name: Run tests
run: npm test

lint:
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v4

- name: Set up Node.js
uses: actions/setup-node@v4
with:
node-version: 18
cache: "npm"

- name: Install dependencies
run: npm install

- name: Run ESLint
run: npm run lint

build:
runs-on: ubuntu-latest
needs: [test, lint]
steps:
- name: Checkout repository
uses: actions/checkout@v4

- name: Set up Node.js
uses: actions/setup-node@v4
with:
node-version: 20
cache: "npm"

- name: Install dependencies
run: npm install

- name: Build project
run: npm run build
21 changes: 10 additions & 11 deletions aws/EC2/createControlPanel.ts
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,7 @@ const getImageId = (region: string) => {
export const createControlPanel = async (
securityGroupId: string,
region: string
) => {
): Promise<string> => {
const client = new EC2Client({ region: region });

const encodedUserData = Buffer.from(userData).toString("base64");
Expand Down Expand Up @@ -156,19 +156,18 @@ export const createControlPanel = async (

try {
const data = await client.send(new RunInstancesCommand(params));
if (!data.Instances || data.Instances.length === 0) {
throw new Error("No instances were created");

if (!data.Instances?.length || !data.Instances[0].InstanceId) {
throw new Error("No instances were created or instance ID is missing");
}

const instanceId = data.Instances[0].InstanceId;

if (typeof instanceId === "string") {
await waitUntilInstanceRunning(
{ client: client, maxWaitTime: 240 },
{ InstanceIds: [instanceId] }
);
}
const instanceId: string = data.Instances[0].InstanceId;

await waitUntilInstanceRunning(
{ client, maxWaitTime: 240 },
{ InstanceIds: [instanceId] }
);

return instanceId;
} catch (err) {
throw new Error(
Expand Down
File renamed without changes.
1 change: 0 additions & 1 deletion aws/IAM/createBrokerRole.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ import {
CreateInstanceProfileCommand,
AddRoleToInstanceProfileCommand,
CreateRoleResponse,
IAM,
} from "@aws-sdk/client-iam";

export const ROLE_NAME = "RMQBrokerRole";
Expand Down
1 change: 0 additions & 1 deletion aws/security-groups/deleteRabbitorySG.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ import {
EC2Client,
DescribeSecurityGroupsCommand,
DeleteSecurityGroupCommand,
EC2,
} from "@aws-sdk/client-ec2";

const GROUP_NAME = "RabbitorySG";
Expand Down
54 changes: 54 additions & 0 deletions cli/_tests_/spinner.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
import { runWithSpinner } from '../spinner';
import ora from 'ora';

interface MockSpinner {
start: jest.Mock<MockSpinner, []>;
succeed: jest.Mock<void, [string]>;
fail: jest.Mock<void, [string]>;
}

jest.mock('ora', () => {
return jest.fn().mockImplementation(() => ({
start: jest.fn().mockReturnThis(),
succeed: jest.fn(),
fail: jest.fn(),
}));
});

jest.mock('chalk', () => ({
white: jest.fn().mockImplementation((msg: string) => msg),
green: jest.fn().mockImplementation((msg: string) => `green ${msg}`),
bgRed: jest.fn().mockImplementation((msg: string) => `bgRed ${msg}`),
}));

describe('runWithSpinner', () => {
beforeEach(() => {
jest.clearAllMocks();
});

it('should call the callback function and return its result', async () => {
const mockCallback = jest.fn().mockResolvedValue('Success Result');
const result = await runWithSpinner('Loading...', mockCallback, 'Completed!');

const oraMock = ora as jest.MockedFunction<typeof ora>;
const spinner = oraMock.mock.results[0].value as MockSpinner;

expect(mockCallback).toHaveBeenCalledTimes(1);
expect(spinner.succeed).toHaveBeenCalledWith('green Completed!');
expect(result).toBe('Success Result');
});

it('should handle errors and fail the spinner', async () => {
const mockError = new Error('Something went wrong');
const mockCallback = jest.fn().mockRejectedValue(mockError);

await expect(
runWithSpinner('Loading...', mockCallback, 'Completed!')
).rejects.toThrow(mockError);

const oraMock = ora as jest.MockedFunction<typeof ora>;
const spinnerInstance = oraMock.mock.results[0].value as MockSpinner;

expect(spinnerInstance.fail).toHaveBeenCalledWith('bgRed Loading... - Failed');
});
});
2 changes: 1 addition & 1 deletion cli/deploy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { createRabbitoryIAM } from "../aws/IAM/createRabbitoryRole";
import { createRMQBrokerIAM } from "../aws/IAM/createBrokerRole";
import { createRabbitorySG } from "../aws/security-groups/createRabbitorySG";
import { createControlPanel } from "../aws/EC2/createControlPanel";
import { getRabbitoryEndpoint } from "../aws/EC2/getControlPanelEndpoint";
import { getRabbitoryEndpoint } from "../aws/EC2/getRabbitoryEndpoint";
import { createTable } from "../aws/dynamoDB/createTable";
import { runWithSpinner } from "./spinner";
import { getRegion } from "./getRegion";
Expand Down
4 changes: 2 additions & 2 deletions cli/setupAws.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ const checkAwsCli = () => {
try {
execSync('aws --version', { stdio: 'ignore' })
console.log('AWS CLI is installed!');
} catch (err) {
} catch {
console.error(
'AWS CLI is not installed. Follow the instructions here and try again: https://docs.aws.amazon.com/cli/latest/userguide/getting-started-install.html'
);
Expand All @@ -16,7 +16,7 @@ const checkAwsAuth = () => {
try {
const output = execSync('aws sts get-caller-identity', { encoding: 'utf8' });
console.log('AWS authentication successful:', output);
} catch (err) {
} catch {
console.error('You are not logged in to the AWS CLI. Run `aws configure` to log in and try again.');
process.exit(1);
}
Expand Down
8 changes: 4 additions & 4 deletions cli/spinner.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import ora from 'ora';
import chalk from 'chalk';

export const runWithSpinner = async (
export const runWithSpinner = async <T>(
waitingMsg: string,
callbackFn: () => Promise<any>,
callbackFn: () => Promise<T>,
successMsg: string
) => {
): Promise<T> => {
const spinner = ora({
text: chalk.white(waitingMsg),
color: 'white',
Expand All @@ -20,4 +20,4 @@ export const runWithSpinner = async (
spinner.fail(chalk.bgRed(`${waitingMsg} - Failed`));
throw error;
}
};
};
25 changes: 25 additions & 0 deletions eslint.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import { defineConfig } from "eslint/config";
import globals from "globals";
import js from "@eslint/js";
import tseslint from "typescript-eslint";
// import jest from "eslint-plugin-jest";

export default defineConfig([
{
ignores: ["dist/"],
},
{
files: [
"cli/*.{js,mjs,cjs,ts}",
"aws/*.{js,mjs,cjs,ts}",
"*/_tests_/*.test.{js,mjs,cjs,ts}",
],
languageOptions: { globals: globals.node },
},
{
files: ["**/*.{js,mjs,cjs,ts}"],
plugins: { js },
extends: ["js/recommended"],
},
tseslint.configs.recommended,
]);
16 changes: 16 additions & 0 deletions jest.config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import type { Config } from "jest";

const config: Config = {
preset: "ts-jest",
testEnvironment: "node",
roots: ["<rootDir>/aws", "<rootDir>/cli"],
testMatch: ["**/_tests_/**/*.test.ts"],
moduleFileExtensions: ["ts", "tsx", "js", "jsx", "json", "node"],
transform: {
"^.+\\.tsx?$": "ts-jest",
},
collectCoverage: true,
coveragePathIgnorePatterns: ["/node_modules/", "/dist/"],
};

export default config;
Loading