Skip to content

Commit

Permalink
feat(client): client/src/cordova/dev action (#2111)
Browse files Browse the repository at this point in the history
  • Loading branch information
daniellacosse authored Aug 12, 2024
1 parent a4e9f77 commit c69689c
Show file tree
Hide file tree
Showing 8 changed files with 390 additions and 47 deletions.
23 changes: 23 additions & 0 deletions client/build/make_replacements.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
// Copyright 2024 The Outline Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

import replace from 'replace-in-file';

export async function makeReplacements(replacements) {
let results = [];

for (const replacement of replacements) {
results = [...results, ...(await replace(replacement))];
}
}
1 change: 1 addition & 0 deletions client/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,7 @@
"eslint-plugin-import": "^2.26.0",
"esm": "^3.2.25",
"file-loader": "^6.2.0",
"folder-hash": "^4.0.4",
"html-webpack-plugin": "^5.1.0",
"husky": "^1.3.1",
"i18n-strings-files": "^2.0.0",
Expand Down
142 changes: 142 additions & 0 deletions client/src/cordova/dev.action.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,142 @@
// Copyright 2022 The Outline Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

import os from 'os';
import path from 'path';
import url from 'url';

import {createReloadServer} from '@outline/infrastructure/build/create_reload_server.mjs';
import {getRootDir} from '@outline/infrastructure/build/get_root_dir.mjs';
import {runAction} from '@outline/infrastructure/build/run_action.mjs';
import {spawnStream} from '@outline/infrastructure/build/spawn_stream.mjs';
import {hashElement} from 'folder-hash';
import * as fs from 'fs-extra';
import minimist from 'minimist';

import {makeReplacements} from '../../build/make_replacements.mjs';

const OUTPUT_PATH = 'output/build/client/macos';
const OUTLINE_APP_PATH = 'Debug/Outline.app';
const OUTLINE_APP_WWW_PATH = 'Contents/Resources/www';
const RELOAD_SERVER_PORT = 35729;

const getUIHash = async () => {
const hashResult = await hashElement(
path.join(getRootDir(), 'client/src/www'),
{
files: {include: ['**/*.ts', '**/*.html', '**/*.css', '**/*.js']},
}
);

return hashResult.hash;
};

/**
* @description Runs the cordova app in development mode.
*
* @param {string[]} parameters
*/
export async function main(...givenParameters) {
const {
_: [platform = 'macos'],
buildMode = 'release',
sentryDsn = 'https://public@sentry.example.com/1',
versionName = '0.0.0-dev',
} = minimist(givenParameters);

if (platform !== 'macos') {
throw new Error('This action currently only works for the MacOS platform.');
}

if (buildMode !== 'release') {
throw new Error('MacOS only renders properly in the release build mode.');
}

if (os.platform() !== 'darwin') {
throw new Error('You must be on MacOS to develop for MacOS.');
}

const parameters = [
'macos',
'--buildMode=release',
`--sentryDsn=${sentryDsn}`,
`--versionName=${versionName}`,
];

await runAction('client/src/www/build', ...parameters);
await runAction('client/go/build', ...parameters);
await runAction('client/src/cordova/setup', ...parameters);

await makeReplacements([
{
files: path.join(
getRootDir(),
'client/platforms/osx/**/index_cordova.html'
),
from: '<app-root></app-root>',
to: `<app-root></app-root>
<script>
try {
const reloadSocket = new WebSocket("ws://localhost:35729");
reloadSocket.onopen = () => console.log("LiveReload connected~");
reloadSocket.onmessage = ({ data }) => data === "reload" && location.reload();
} catch (e) {
// nevermind
}
</script>`,
},
]);

await spawnStream(
'xcodebuild',
'-scheme',
'Outline',
'-workspace',
path.join(getRootDir(), 'client/src/cordova/apple/macos.xcworkspace'),
`SYMROOT=${path.join(getRootDir(), OUTPUT_PATH)}`
);

await spawnStream(
'open',
path.join(getRootDir(), OUTPUT_PATH, OUTLINE_APP_PATH)
);

let previousUIHashResult = await getUIHash();

console.log(`Starting reload server @ port ${RELOAD_SERVER_PORT}...`);
createReloadServer(async () => {
const currentUIHashResult = await getUIHash();

if (previousUIHashResult === currentUIHashResult) {
return false;
}

previousUIHashResult = currentUIHashResult;

await runAction('client/src/www/build', ...parameters);

await fs.copy(
path.join(getRootDir(), 'client/www'),
path.join(OUTPUT_PATH, OUTLINE_APP_PATH, OUTLINE_APP_WWW_PATH)
);

return true;
}).listen(RELOAD_SERVER_PORT);
}

if (import.meta.url === url.pathToFileURL(process.argv[1]).href) {
await main(...process.argv.slice(2));
}
101 changes: 74 additions & 27 deletions client/src/cordova/setup.action.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,10 @@ import {runAction} from '@outline/infrastructure/build/run_action.mjs';
import {spawnStream} from '@outline/infrastructure/build/spawn_stream.mjs';
import chalk from 'chalk';
import cordovaLib from 'cordova-lib';
import replace from 'replace-in-file';
import rmfr from 'rmfr';

import {getBuildParameters} from '../../build/get_build_parameters.mjs';
import {makeReplacements} from '../../build/make_replacements.mjs';

const {cordova} = cordovaLib;
const WORKING_CORDOVA_OSX_COMMIT = '07e62a53aa6a8a828fd988bc9e884c38c3495a67';
Expand All @@ -37,17 +37,20 @@ const WORKING_CORDOVA_OSX_COMMIT = '07e62a53aa6a8a828fd988bc9e884c38c3495a67';
* @param {string[]} parameters
*/
export async function main(...parameters) {
const {platform, buildMode, verbose, buildNumber, versionName} = getBuildParameters(parameters);
const {platform, buildMode, verbose, buildNumber, versionName} =
getBuildParameters(parameters);

await runAction('client/src/www/build', ...parameters);
await runAction('client/go/build', ...parameters);
const CORDOVA_PROJECT_DIR = path.resolve(getRootDir(), 'client');

const CORDOVA_PROJECT_DIR = path.resolve(getRootDir(), 'client');
await rmfr(path.resolve(CORDOVA_PROJECT_DIR, 'platforms'));
await rmfr(path.resolve(CORDOVA_PROJECT_DIR, 'plugins'));

if (verbose) {
cordova.on('verbose', message => console.debug(`[cordova:verbose] ${message}`));
cordova.on('verbose', message =>
console.debug(`[cordova:verbose] ${message}`)
);
}

// this is so cordova doesn't complain about not being in a cordova project
Expand All @@ -57,7 +60,9 @@ export async function main(...parameters) {
case 'android' + 'debug':
return androidDebug(verbose);
case 'android' + 'release':
console.warn('NOTE: You must open the Outline.zip file after building to upload to the Play Store.');
console.warn(
'NOTE: You must open the Outline.zip file after building to upload to the Play Store.'
);
return androidRelease(versionName, buildNumber, verbose);
case 'ios' + 'debug':
case 'maccatalyst' + 'debug':
Expand Down Expand Up @@ -86,23 +91,27 @@ async function androidDebug(verbose) {
});
}

async function makeReplacements(replacements) {
let results = [];

for (const replacement of replacements) {
results = [...results, ...(await replace(replacement))];
}
}

async function androidRelease(versionName, buildNumber, verbose) {
await cordova.prepare({
platforms: ['android'],
save: false,
verbose,
});

const manifestXmlGlob = path.join(getRootDir(), 'platforms', 'android', '**', 'AndroidManifest.xml');
const configXmlGlob = path.join(getRootDir(), 'platforms', 'android', '**', 'config.xml');
const manifestXmlGlob = path.join(
getRootDir(),
'platforms',
'android',
'**',
'AndroidManifest.xml'
);
const configXmlGlob = path.join(
getRootDir(),
'platforms',
'android',
'**',
'config.xml'
);

await makeReplacements([
{
Expand Down Expand Up @@ -130,7 +139,9 @@ async function androidRelease(versionName, buildNumber, verbose) {

async function appleIosDebug(verbose) {
if (os.platform() !== 'darwin') {
throw new Error('Building an Apple binary requires xcodebuild and can only be done on MacOS');
throw new Error(
'Building an Apple binary requires xcodebuild and can only be done on MacOS'
);
}

await cordova.prepare({
Expand All @@ -140,19 +151,32 @@ async function appleIosDebug(verbose) {
});

// TODO(daniellacosse): move this to a cordova hook
await spawnStream('rsync', '-avc', 'src/cordova/apple/xcode/ios/', 'platforms/ios/');
await spawnStream(
'rsync',
'-avc',
'src/cordova/apple/xcode/ios/',
'platforms/ios/'
);
}

async function appleMacOsDebug(verbose) {
if (os.platform() !== 'darwin') {
throw new Error('Building an Apple binary requires xcodebuild and can only be done on MacOS');
throw new Error(
'Building an Apple binary requires xcodebuild and can only be done on MacOS'
);
}

console.warn(
chalk.yellow('Debug mode on the MacOS client is currently broken. Try running with `--buildMode=release` instead.')
chalk.yellow(
'Debug mode on the MacOS client is currently broken. Try running with `--buildMode=release` instead.'
)
);

await cordova.platform('add', [`github:apache/cordova-osx#${WORKING_CORDOVA_OSX_COMMIT}`], {save: false});
await cordova.platform(
'add',
[`github:apache/cordova-osx#${WORKING_CORDOVA_OSX_COMMIT}`],
{save: false}
);

await cordova.prepare({
platforms: ['osx'],
Expand All @@ -161,7 +185,12 @@ async function appleMacOsDebug(verbose) {
});

// TODO(daniellacosse): move this to a cordova hook
await spawnStream('rsync', '-avc', 'src/cordova/apple/xcode/macos/', 'platforms/osx/');
await spawnStream(
'rsync',
'-avc',
'src/cordova/apple/xcode/macos/',
'platforms/osx/'
);
}

async function setAppleVersion(platform, versionName, buildNumber) {
Expand All @@ -181,7 +210,9 @@ async function setAppleVersion(platform, versionName, buildNumber) {

async function appleIosRelease(version, buildNumber, verbose) {
if (os.platform() !== 'darwin') {
throw new Error('Building an Apple binary requires xcodebuild and can only be done on MacOS');
throw new Error(
'Building an Apple binary requires xcodebuild and can only be done on MacOS'
);
}

await cordova.prepare({
Expand All @@ -191,17 +222,28 @@ async function appleIosRelease(version, buildNumber, verbose) {
});

// TODO(daniellacosse): move this to a cordova hook
await spawnStream('rsync', '-avc', 'src/cordova/apple/xcode/ios/', 'platforms/ios/');
await spawnStream(
'rsync',
'-avc',
'src/cordova/apple/xcode/ios/',
'platforms/ios/'
);

await setAppleVersion('ios', version, buildNumber);
}

async function appleMacOsRelease(version, buildNumber, verbose) {
if (os.platform() !== 'darwin') {
throw new Error('Building an Apple binary requires xcodebuild and can only be done on MacOS');
throw new Error(
'Building an Apple binary requires xcodebuild and can only be done on MacOS'
);
}

await cordova.platform('add', [`github:apache/cordova-osx#${WORKING_CORDOVA_OSX_COMMIT}`], {save: false});
await cordova.platform(
'add',
[`github:apache/cordova-osx#${WORKING_CORDOVA_OSX_COMMIT}`],
{save: false}
);

await cordova.prepare({
platforms: ['osx'],
Expand All @@ -210,7 +252,12 @@ async function appleMacOsRelease(version, buildNumber, verbose) {
});

// TODO(daniellacosse): move this to a cordova hook
await spawnStream('rsync', '-avc', 'src/cordova/apple/xcode/macos/', 'platforms/osx/');
await spawnStream(
'rsync',
'-avc',
'src/cordova/apple/xcode/macos/',
'platforms/osx/'
);

await setAppleVersion('osx', version, buildNumber);
}
Expand Down
1 change: 0 additions & 1 deletion client/src/www/index_cordova.html
Original file line number Diff line number Diff line change
Expand Up @@ -26,5 +26,4 @@
</head>
<body unresolved>
<app-root></app-root>
</body>
</html>
Loading

0 comments on commit c69689c

Please sign in to comment.