Skip to content

Commit db8db34

Browse files
committed
Merge remote-tracking branch 'origin/prod-beta' into prod-stable
2 parents d19b038 + 9e82d01 commit db8db34

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

95 files changed

+251
-225
lines changed

.github/workflows/pull_request.yml

+27-7
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,13 @@
1-
# Run this workflow for PRs only. Travis is required to push via insights-frontend-builder-common scripts
2-
31
name: Pull request
42
on:
53
pull_request:
6-
branches: [ main, master, prod-beta, prod-stable, stage-beta, stage-stable ]
4+
branches:
5+
- main
6+
- master
7+
- prod-beta
8+
- prod-stable
9+
- stage-beta
10+
- stage-stable
711
env:
812
BRANCH: ${{ github.base_ref }}
913

@@ -16,14 +20,16 @@ jobs:
1620
node-version: [18]
1721
steps:
1822
- name: Checkout code
19-
uses: actions/checkout@v3
23+
uses: actions/checkout@v4
24+
2025
- name: Setup Node.js ${{ matrix.node-version }}
21-
uses: actions/setup-node@v3
26+
uses: actions/setup-node@v4
2227
with:
2328
node-version: ${{ matrix.node-version }}
29+
2430
- name: Cache node modules
2531
id: cache-npm
26-
uses: actions/cache@v3
32+
uses: actions/cache@v4
2733
env:
2834
cache-name: cache-node-modules
2935
with:
@@ -34,13 +40,27 @@ jobs:
3440
${{ runner.os }}-build-${{ env.cache-name }}-
3541
${{ runner.os }}-build-
3642
${{ runner.os }}-
43+
3744
- name: Install dependencies
3845
run: npm install
46+
3947
- name: Build
4048
run: npm run build
49+
4150
- name: Lint
4251
if: ${{ success() }}
4352
run: npm run lint
53+
4454
- name: Test
4555
if: ${{ success() }}
46-
run: npm test --coverage --maxWorkers=4
56+
run: npm test -- --collect-coverage --max-workers=4
57+
58+
- name: Upload coverage report
59+
if: ${{ success() }}
60+
uses: codecov/codecov-action@v4.2.0
61+
env:
62+
CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
63+
with:
64+
directory: coverage
65+
plugin: pycoverage # Only run one plugin so that all do not run. There is no way to disable plugins entirely.
66+

.github/workflows/stale.yml

+1-1
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ jobs:
1212
issues: write
1313
pull-requests: write
1414
steps:
15-
- uses: actions/stale@v5
15+
- uses: actions/stale@v9
1616
with:
1717
days-before-issue-close: 14
1818
days-before-issue-stale: 30

.github/workflows/tag_release.yml

+1-1
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ jobs:
77
tag_release:
88
runs-on: ubuntu-latest
99
steps:
10-
- uses: actions/checkout@v2
10+
- uses: actions/checkout@v4
1111
with:
1212
ref: prod-stable
1313
- run: |

README.md

+16-15
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,22 @@
11
# Koku UI
22

3-
[![AGPLv3][license-badge]][license]
4-
[![Build Status][build-badge]][build]
3+
[![Apache 2.0][license-badge]](https://github.com/project-koku/koku-ui/blob/main/LICENSE)
4+
[![CI Status][build-badge]](https://github.com/project-koku/koku-ui/actions/workflows/tag_release.yml)
5+
[![codecov][codecov-badge]](https://codecov.io/gh/project-koku/koku-ui)
56

67
React.js app for Cost Management.
78

8-
User interface is based on Patternfly [![Patternfly][pf-logo]][patternfly]
9+
User interface is based on [Patternfly].
910

10-
To submit an issue, please visit https://issues.redhat.com/projects/COST/
11+
Submit issues in [Jira].
1112

1213
## Requirements
1314
* [NodeJS v18.15+][nodejs]
1415
* [npm v9.5+][npm]
1516

16-
## Setup /etc/hosts entries (do this once)
17+
## Setup `hosts` entries (do this once)
1718

18-
Edit the /etc/hosts file and add the following entries
19+
Edit the `/etc/hosts` file and add the following entries
1920
```
2021
127.0.0.1 prod.foo.redhat.com
2122
127.0.0.1 stage.foo.redhat.com
@@ -28,7 +29,7 @@ sudo bash scripts/patch-etc-hosts.sh
2829

2930
## Getting Started
3031
1. Install requirements listed above.
31-
2. Setup /etc/hosts entries listed above.
32+
2. Setup `/etc/hosts` entries listed above.
3233
3. Clone the repository, and open a terminal in the base of this project.
3334
4. Run the command `npm install` to install all the dependencies.
3435

@@ -109,7 +110,7 @@ npm start:static
109110
npm start:csb:mfe
110111
```
111112

112-
## Running local instances of Koku UI & Koku API
113+
## Running local instances of Koku UI and Koku API
113114
#### Koku UI
114115

115116
1. Start development server (Answer `yes` to run against local APIs)
@@ -193,14 +194,14 @@ http://localhost:1337/beta/settings/applications/cost-management
193194

194195
This [RELEASE][release-doc] doc describes how to release Koku UI to each staging environment.
195196

196-
[build]: https://travis-ci.com/project-koku/UI'
197-
[build-badge]: https://img.shields.io/travis/project-koku/koku-ui.svg?style=for-the-badge
197+
[build-badge]: https://github.com/project-koku/koku-ui/actions/workflows/tag_release.yml/badge.svg
198+
[license-badge]: https://img.shields.io/github/license/project-koku/koku-ui.svg?longCache=true
199+
[codecov-badge]: https://codecov.io/gh/project-koku/koku-ui/graph/badge.svg?token=1hjFIy1cRe
200+
198201
[koku-readme]: https://github.com/project-koku/koku#readme
199-
[license-badge]: https://img.shields.io/github/license/project-koku/koku-ui.svg?longCache=true&style=for-the-badge
200-
[license]: https://github.com/project-koku/koku-ui/blob/main/LICENSE
201202
[nodejs]: https://nodejs.org/en/
202203
[patch-etc-hosts]: https://github.com/RedHatInsights/insights-proxy/blob/master/scripts/patch-etc-hosts.sh
203-
[pf-logo]: https://www.patternfly.org/v4/images/logo.4189e7eb1a0741ea2b3b51b80d33c4cb.svg
204-
[patternfly]: https://www.patternfly.org/
204+
[Patternfly]: https://www.patternfly.org/
205205
[release-doc]: https://github.com/project-koku/koku-ui/blob/main/RELEASE.md
206-
[npm]: https://https://www.npmjs.com/
206+
[npm]: https://www.npmjs.com/
207+
[Jira]: https://issues.redhat.com/projects/COST/

fec.config.js

-1
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,6 @@ module.exports = {
5959
* Package can be re-enabled for sharing once chrome starts providing global routing package to all applications
6060
*/
6161
// exclude: ['react-router-dom'],
62-
exclude: ['axios'], // Setting the base URL affects Cost Management APIs in OCM, when navigating between apps
6362
exposes: {
6463
'./RootApp': path.resolve(__dirname, './src/appEntry.tsx'),
6564
},

src/api/accountSettings.ts

+3-3
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import axios from 'axios';
1+
import { axiosInstance } from 'api';
22

33
import type { PagedLinks, PagedMetaData } from './api';
44

@@ -38,10 +38,10 @@ export const AccountSettingsTypePaths: Partial<Record<AccountSettingsType, strin
3838

3939
export function fetchAccountSettings(settingsType: AccountSettingsType) {
4040
const path = AccountSettingsTypePaths[settingsType];
41-
return axios.get<AccountSettings>(`${path}`);
41+
return axiosInstance.get<AccountSettings>(`${path}`);
4242
}
4343

4444
export function updateAccountSettings(settingsType: AccountSettingsType, payload: AccountSettingsPayload) {
4545
const path = AccountSettingsTypePaths[settingsType];
46-
return axios.put(`${path}`, payload);
46+
return axiosInstance.put(`${path}`, payload);
4747
}

src/api/api.ts

+17-5
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import type { AxiosRequestConfig } from 'axios';
1+
import type { AxiosInstance, AxiosRequestConfig } from 'axios';
22
import axios from 'axios';
33

44
export interface PagedMetaData {
@@ -18,10 +18,10 @@ export interface PagedResponse<D = any, M = any> {
1818
data: D[];
1919
}
2020

21-
export function initApi({ version }: { version: string }) {
22-
axios.defaults.baseURL = `/api/cost-management/${version}/`;
23-
axios.interceptors.request.use(authInterceptor);
24-
}
21+
// export function initApi({ version }: { version: string }) {
22+
// axios.defaults.baseURL = `/api/cost-management/${version}/`;
23+
// axios.interceptors.request.use(authInterceptor);
24+
// }
2525

2626
export function authInterceptor(reqConfig: AxiosRequestConfig) {
2727
return {
@@ -31,3 +31,15 @@ export function authInterceptor(reqConfig: AxiosRequestConfig) {
3131
} as any,
3232
};
3333
}
34+
35+
// Create an Axios instance
36+
//
37+
// Note: Setting global defaults may affect the base URL in Cost Management, HCS, and OCM, when navigating between apps
38+
// See https://issues.redhat.com/browse/RHCLOUD-25573
39+
const axiosInstance: AxiosInstance = axios.create({
40+
baseURL: '/api/cost-management/v1/',
41+
});
42+
43+
axiosInstance.interceptors.request.use(authInterceptor);
44+
45+
export default axiosInstance;

src/api/costModels.test.ts

+6-6
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,17 @@
1-
import axios from 'axios';
1+
import { axiosInstance } from 'api';
22

33
import type { CostModelRequest } from './costModels';
44
import { addCostModel, deleteCostModel, fetchCostModels, updateCostModel } from './costModels';
55

66
test('api get cost models calls axios to costmodels', () => {
77
fetchCostModels();
8-
expect(axios.get).toBeCalledWith('cost-models/');
8+
expect(axiosInstance.get).toBeCalledWith('cost-models/');
99
});
1010

1111
test('api get cost models calls axios to costmodels with query', () => {
1212
const query = 'limit=20&offset=10';
1313
fetchCostModels(query);
14-
expect(axios.get).toBeCalledWith(`cost-models/?${query}`);
14+
expect(axiosInstance.get).toBeCalledWith(`cost-models/?${query}`);
1515
});
1616

1717
test('add cost model calls axios post', () => {
@@ -33,7 +33,7 @@ test('add cost model calls axios post', () => {
3333
],
3434
};
3535
addCostModel(request);
36-
expect(axios.post).toBeCalledWith('cost-models/', request);
36+
expect(axiosInstance.post).toBeCalledWith('cost-models/', request);
3737
});
3838

3939
test('update cost model calls axios put', () => {
@@ -55,10 +55,10 @@ test('update cost model calls axios put', () => {
5555
],
5656
};
5757
updateCostModel('123abc456def', request);
58-
expect(axios.put).toBeCalledWith('cost-models/123abc456def/', request);
58+
expect(axiosInstance.put).toBeCalledWith('cost-models/123abc456def/', request);
5959
});
6060

6161
test('delete cost model calls axios delete', () => {
6262
deleteCostModel('123abc456def');
63-
expect(axios.delete).toBeCalledWith('cost-models/123abc456def/');
63+
expect(axiosInstance.delete).toBeCalledWith('cost-models/123abc456def/');
6464
});

src/api/costModels.ts

+6-6
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import axios from 'axios';
1+
import { axiosInstance } from 'api';
22

33
import type { PagedResponse } from './api';
44
import type { Rate, RateRequest } from './rates';
@@ -45,21 +45,21 @@ export interface CostModelRequest {
4545
export type CostModels = PagedResponse<CostModel>;
4646

4747
export function fetchCostModels(query = '') {
48-
return axios.get<CostModels>(`cost-models/${query && '?'}${query}`);
48+
return axiosInstance.get<CostModels>(`cost-models/${query && '?'}${query}`);
4949
}
5050

5151
export function fetchCostModel(uuid: string) {
52-
return axios.get<CostModels>(`cost-models/${uuid}/`);
52+
return axiosInstance.get<CostModels>(`cost-models/${uuid}/`);
5353
}
5454

5555
export function addCostModel(request: CostModelRequest) {
56-
return axios.post(`cost-models/`, request);
56+
return axiosInstance.post(`cost-models/`, request);
5757
}
5858

5959
export function updateCostModel(uuid: string, request: CostModelRequest) {
60-
return axios.put(`cost-models/${uuid}/`, request);
60+
return axiosInstance.put(`cost-models/${uuid}/`, request);
6161
}
6262

6363
export function deleteCostModel(uuid: string) {
64-
return axios.delete(`cost-models/${uuid}/`);
64+
return axiosInstance.delete(`cost-models/${uuid}/`);
6565
}

src/api/export/awsExport.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
1+
import { axiosInstance } from 'api';
12
import { ReportTypePaths } from 'api/reports/awsReports';
23
import type { ReportType } from 'api/reports/report';
3-
import axios from 'axios';
44

55
export function runExport(reportType: ReportType, query: string) {
66
const path = ReportTypePaths[reportType];
7-
return axios.get<string>(`${path}?${query}`, {
7+
return axiosInstance.get<string>(`${path}?${query}`, {
88
headers: {
99
Accept: 'text/csv',
1010
},

src/api/export/awsOcpExport.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
1+
import { axiosInstance } from 'api';
12
import { ReportTypePaths } from 'api/reports/awsOcpReports';
23
import type { ReportType } from 'api/reports/report';
3-
import axios from 'axios';
44

55
export function runExport(reportType: ReportType, query: string) {
66
const path = ReportTypePaths[reportType];
7-
return axios.get<string>(`${path}?${query}`, {
7+
return axiosInstance.get<string>(`${path}?${query}`, {
88
headers: {
99
Accept: 'text/csv',
1010
},

src/api/export/azureExport.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
1+
import { axiosInstance } from 'api';
12
import { ReportTypePaths } from 'api/reports/azureReports';
23
import type { ReportType } from 'api/reports/report';
3-
import axios from 'axios';
44

55
export function runExport(reportType: ReportType, query: string) {
66
const path = ReportTypePaths[reportType];
7-
return axios.get<string>(`${path}?${query}`, {
7+
return axiosInstance.get<string>(`${path}?${query}`, {
88
headers: {
99
Accept: 'text/csv',
1010
},

src/api/export/azureOcpExport.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
1+
import { axiosInstance } from 'api';
12
import { ReportTypePaths } from 'api/reports/azureOcpReports';
23
import type { ReportType } from 'api/reports/report';
3-
import axios from 'axios';
44

55
export function runExport(reportType: ReportType, query: string) {
66
const path = ReportTypePaths[reportType];
7-
return axios.get<string>(`${path}?${query}`, {
7+
return axiosInstance.get<string>(`${path}?${query}`, {
88
headers: {
99
Accept: 'text/csv',
1010
},

src/api/export/gcpExport.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
1+
import { axiosInstance } from 'api';
12
import { ReportTypePaths } from 'api/reports/gcpReports';
23
import type { ReportType } from 'api/reports/report';
3-
import axios from 'axios';
44

55
export function runExport(reportType: ReportType, query: string) {
66
const path = ReportTypePaths[reportType];
7-
return axios.get<string>(`${path}?${query}`, {
7+
return axiosInstance.get<string>(`${path}?${query}`, {
88
headers: {
99
Accept: 'text/csv',
1010
},

src/api/export/gcpOcpExport.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
1+
import { axiosInstance } from 'api';
12
import { ReportTypePaths } from 'api/reports/gcpOcpReports';
23
import type { ReportType } from 'api/reports/report';
3-
import axios from 'axios';
44

55
export function runExport(reportType: ReportType, query: string) {
66
const path = ReportTypePaths[reportType];
7-
return axios.get<string>(`${path}?${query}`, {
7+
return axiosInstance.get<string>(`${path}?${query}`, {
88
headers: {
99
Accept: 'text/csv',
1010
},

src/api/export/ibmExport.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
1+
import { axiosInstance } from 'api';
12
import { ReportTypePaths } from 'api/reports/ibmReports';
23
import type { ReportType } from 'api/reports/report';
3-
import axios from 'axios';
44

55
export function runExport(reportType: ReportType, query: string) {
66
const path = ReportTypePaths[reportType];
7-
return axios.get<string>(`${path}?${query}`, {
7+
return axiosInstance.get<string>(`${path}?${query}`, {
88
headers: {
99
Accept: 'text/csv',
1010
},

src/api/export/ociExport.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
1+
import { axiosInstance } from 'api';
12
import { ReportTypePaths } from 'api/reports/ociReports';
23
import type { ReportType } from 'api/reports/report';
3-
import axios from 'axios';
44

55
export function runExport(reportType: ReportType, query: string) {
66
const path = ReportTypePaths[reportType];
7-
return axios.get<string>(`${path}?${query}`, {
7+
return axiosInstance.get<string>(`${path}?${query}`, {
88
headers: {
99
Accept: 'text/csv',
1010
},

0 commit comments

Comments
 (0)