Skip to content

Commit

Permalink
Merge branch 'main' into Guccio163/45951_implementApprovalWorkflowSec…
Browse files Browse the repository at this point in the history
…tion
  • Loading branch information
blazejkustra committed Aug 2, 2024
2 parents fc835a1 + 13c0ef7 commit 27e14eb
Show file tree
Hide file tree
Showing 70 changed files with 1,505 additions and 195 deletions.
20 changes: 20 additions & 0 deletions .github/actions/composite/buildAndroidE2EAPK/action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,9 @@ inputs:
EXPENSIFY_PARTNER_PASSWORD_EMAIL:
description: The email address of the Expensify partner to use for the build
required: true
SLACK_WEBHOOK_URL:
description: 'URL of the slack webhook'
required: true

runs:
using: composite
Expand Down Expand Up @@ -75,6 +78,23 @@ runs:
env:
RUBYOPT: '-rostruct'

- name: Announce failed workflow in Slack
if: failure()
uses: 8398a7/action-slack@v3
with:
status: custom
custom_payload: |
{
channel: '#e2e-announce',
attachments: [{
color: 'danger',
text: `🚧 ${process.env.AS_REPO} E2E APK build run failed on <https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}|${{ github.workflow }}> workflow 🚧`,
}]
}
env:
GITHUB_TOKEN: ${{ github.token }}
SLACK_WEBHOOK_URL: ${{ inputs.SLACK_WEBHOOK_URL }}

- name: Upload APK
uses: actions/upload-artifact@v4
with:
Expand Down
2 changes: 1 addition & 1 deletion .github/actions/javascript/proposalPoliceComment/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -18631,7 +18631,7 @@ class OpenAIUtils {
continue;
}
response += message.content
.map((contentBlock) => this.isTextContentBlock(contentBlock))
.map((contentBlock) => this.isTextContentBlock(contentBlock) && contentBlock.text.value)
.join('\n')
.trim();
console.log('Parsed assistant response:', response);
Expand Down
2 changes: 1 addition & 1 deletion .github/libs/OpenAIUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ class OpenAIUtils {
continue;
}
response += message.content
.map((contentBlock) => this.isTextContentBlock(contentBlock))
.map((contentBlock) => this.isTextContentBlock(contentBlock) && contentBlock.text.value)
.join('\n')
.trim();
console.log('Parsed assistant response:', response);
Expand Down
4 changes: 3 additions & 1 deletion .github/workflows/e2ePerformanceTests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@ jobs:
EXPENSIFY_PARTNER_USER_ID: ${{ secrets.EXPENSIFY_PARTNER_USER_ID }}
EXPENSIFY_PARTNER_USER_SECRET: ${{ secrets.EXPENSIFY_PARTNER_USER_SECRET }}
EXPENSIFY_PARTNER_PASSWORD_EMAIL: ${{ secrets.EXPENSIFY_PARTNER_PASSWORD_EMAIL }}
SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK }}
PATH_ENV_FILE: tests/e2e/.env.e2e

buildDelta:
Expand Down Expand Up @@ -137,6 +138,7 @@ jobs:
EXPENSIFY_PARTNER_USER_ID: ${{ secrets.EXPENSIFY_PARTNER_USER_ID }}
EXPENSIFY_PARTNER_USER_SECRET: ${{ secrets.EXPENSIFY_PARTNER_USER_SECRET }}
EXPENSIFY_PARTNER_PASSWORD_EMAIL: ${{ secrets.EXPENSIFY_PARTNER_PASSWORD_EMAIL }}
SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK }}
PATH_ENV_FILE: tests/e2e/.env.e2edelta

runTestsInAWS:
Expand Down Expand Up @@ -239,7 +241,7 @@ jobs:
channel: '#e2e-announce',
attachments: [{
color: 'danger',
text: `💥 ${process.env.AS_REPO} E2E Test run failed failed on <https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}|${{ github.workflow }}> workflow 💥`,
text: `💥 ${process.env.AS_REPO} E2E Test run failed on <https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}|${{ github.workflow }}> workflow 💥`,
}]
}
env:
Expand Down
12 changes: 12 additions & 0 deletions .github/workflows/platformDeploy.yml
Original file line number Diff line number Diff line change
Expand Up @@ -179,6 +179,12 @@ jobs:
env:
GITHUB_TOKEN: ${{ github.token }}

- name: Archive desktop sourcemaps
uses: actions/upload-artifact@v4
with:
name: desktop-sourcemap-${{ github.ref_name }}
path: desktop/dist/www/merged-source-map.js.map

iOS:
name: Build and deploy iOS
needs: validateActor
Expand Down Expand Up @@ -347,6 +353,12 @@ jobs:
env:
S3_URL: s3://${{ env.SHOULD_DEPLOY_PRODUCTION != 'true' && 'staging-' || '' }}expensify-cash

- name: Archive web sourcemaps
uses: actions/upload-artifact@v4
with:
name: web-sourcemap-${{ github.ref_name }}
path: dist/merged-source-map.js.map

- name: Purge Cloudflare cache
run: /home/runner/.local/bin/cli4 --verbose --delete hosts=["${{ env.SHOULD_DEPLOY_PRODUCTION != 'true' && 'staging.' || '' }}new.expensify.com"] /zones/:9ee042e6cfc7fd45e74aa7d2f78d617b/purge_cache
env:
Expand Down
16 changes: 9 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -230,19 +230,20 @@ Within Xcode head to the build phase - `Bundle React Native code and images`.
```jsx
npm i && npm run pod-install
```
7. Depending on the platform you are targeting, run your Android/iOS app in production mode.
8. Upon completion, the generated source map can be found at:
4. Depending on the platform you are targeting, run your Android/iOS app in production mode.
5. Upon completion, the generated source map can be found at:
Android: `android/app/build/generated/sourcemaps/react/productionRelease/index.android.bundle.map`
IOS: `main.jsbundle.map`
web: `dist/merged-source-map.js.map`

### Recording a Trace:
1. Ensure you have generated the source map as outlined above.
2. Launch the app in production mode.
2. Navigate to the feature you wish to profile.
3. Initiate the profiling session by tapping with four fingers to open the menu and selecting **`Use Profiling`**.
4. Close the menu and interact with the app.
5. After completing your interactions, tap with four fingers again and select to stop profiling.
6. You will be presented with a **`Share`** option to export the trace, which includes a trace file (`Profile<app version>.cpuprofile`) and build info (`AppInfo<app version>.json`).
3. Navigate to the feature you wish to profile.
4. Initiate the profiling session by tapping with four fingers (on mobile) or `cmd+d` (on web) to open the menu and selecting **`Use Profiling`**.
5. Close the menu and interact with the app.
6. After completing your interactions, tap with four fingers or `cmd+d` again and select to stop profiling.
7. You will be presented with a **`Share`** option to export the trace, which includes a trace file (`Profile<app version>.cpuprofile`) and build info (`AppInfo<app version>.json`).

Build info:
```jsx
Expand All @@ -265,6 +266,7 @@ Build info:
4. Use the following commands to symbolicate the trace for Android and iOS, respectively:
Android: `npm run symbolicate-release:android`
IOS: `npm run symbolicate-release:ios`
web: `npm run symbolicate-release:web`
5. A new file named `Profile_trace_for_<app version>-converted.json` will appear in your project's root folder.
6. Open this file in your tool of choice:
- SpeedScope ([https://www.speedscope.app](https://www.speedscope.app/))
Expand Down
11 changes: 11 additions & 0 deletions assets/images/filter.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
4 changes: 4 additions & 0 deletions config/webpack/webpack.dev.ts
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,10 @@ const getConfiguration = (environment: Environment): Promise<Configuration> =>
cert: path.join(__dirname, 'certificate.pem'),
},
},
headers: {
// eslint-disable-next-line @typescript-eslint/naming-convention
'Document-Policy': 'js-profiling',
},
},
plugins: [
new DefinePlugin({
Expand Down
108 changes: 108 additions & 0 deletions desktop/electron-serve.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
/* eslint-disable @typescript-eslint/no-misused-promises */

/* eslint-disable rulesdir/no-negated-variables */

/* eslint-disable @lwc/lwc/no-async-await */

/**
* This file is a modified version of the electron-serve package.
* We keep the same interface, but instead of file protocol we use buffer protocol (with support of JS self profiling).
*/
import type {BrowserWindow, Protocol} from 'electron';
import {app, protocol, session} from 'electron';
import fs from 'fs';
import mime from 'mime-types';
import path from 'path';

type RegisterBufferProtocol = Protocol['registerBufferProtocol'];
type HandlerType = Parameters<RegisterBufferProtocol>[1];
type Optional<T> = T | null | undefined;

const FILE_NOT_FOUND = -6;

const getPath = async (filePath: string): Promise<Optional<string>> => {
try {
const result = await fs.promises.stat(filePath);

if (result.isFile()) {
return filePath;
}

if (result.isDirectory()) {
// eslint-disable-next-line @typescript-eslint/return-await
return getPath(path.join(filePath, 'index.html'));
}
} catch {
return null;
}
};

type ServeOptions = {
directory: string;
isCorsEnabled?: boolean;
scheme?: string;
hostname?: string;
file?: string;
partition?: string;
};

export default function electronServe(options: ServeOptions) {
const mandatoryOptions = {
isCorsEnabled: true,
scheme: 'app',
hostname: '-',
file: 'index',
...options,
};

if (!mandatoryOptions.directory) {
throw new Error('The `directory` option is required');
}

mandatoryOptions.directory = path.resolve(app.getAppPath(), mandatoryOptions.directory);

const handler: HandlerType = async (request, callback) => {
const filePath = path.join(mandatoryOptions.directory, decodeURIComponent(new URL(request.url).pathname));
const resolvedPath = (await getPath(filePath)) ?? path.join(mandatoryOptions.directory, `${mandatoryOptions.file}.html`);
const mimeType = mime.lookup(resolvedPath) || 'application/octet-stream';

try {
const data = await fs.promises.readFile(resolvedPath);
callback({
mimeType,
data: Buffer.from(data),
headers: {
// eslint-disable-next-line @typescript-eslint/naming-convention
'Document-Policy': 'js-profiling',
},
});
} catch (error) {
callback({error: FILE_NOT_FOUND});
}
};

protocol.registerSchemesAsPrivileged([
{
scheme: mandatoryOptions.scheme,
privileges: {
standard: true,
secure: true,
allowServiceWorkers: true,
supportFetchAPI: true,
corsEnabled: mandatoryOptions.isCorsEnabled,
},
},
]);

app.on('ready', () => {
const partitionSession = mandatoryOptions.partition ? session.fromPartition(mandatoryOptions.partition) : session.defaultSession;

partitionSession.protocol.registerBufferProtocol(mandatoryOptions.scheme, handler);
});

// eslint-disable-next-line @typescript-eslint/naming-convention
return async (window_: BrowserWindow, searchParameters?: URLSearchParams) => {
const queryString = searchParameters ? `?${new URLSearchParams(searchParameters).toString()}` : '';
await window_.loadURL(`${mandatoryOptions.scheme}://${mandatoryOptions.hostname}${queryString}`);
};
}
2 changes: 1 addition & 1 deletion desktop/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ import type {BrowserView, MenuItem, MenuItemConstructorOptions, WebContents, Web
import contextMenu from 'electron-context-menu';
import log from 'electron-log';
import type {ElectronLog} from 'electron-log';
import serve from 'electron-serve';
import {autoUpdater} from 'electron-updater';
import {machineId} from 'node-machine-id';
import checkForUpdates from '@libs/checkForUpdates';
Expand All @@ -14,6 +13,7 @@ import type {TranslationPaths} from '@src/languages/types';
import type PlatformSpecificUpdater from '@src/setup/platformSetup/types';
import type {Locale} from '@src/types/onyx';
import type {CreateDownloadQueueModule, DownloadItem} from './createDownloadQueue';
import serve from './electron-serve';
import ELECTRON_EVENTS from './ELECTRON_EVENTS';

const createDownloadQueue = require<CreateDownloadQueueModule>('./createDownloadQueue').default;
Expand Down
64 changes: 41 additions & 23 deletions desktop/package-lock.json

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

Loading

0 comments on commit 27e14eb

Please sign in to comment.