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
64 changes: 49 additions & 15 deletions src/config-plugin/index.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
import {
ConfigPlugin,
createRunOncePlugin,
Mod,
withAndroidManifest,
withDangerousMod,
withInfoPlist,
} from "@expo/config-plugins";
import { ExpoConfig } from "@expo/config-types";
import { generateOverrides, resolveFlagsToInvert } from "../api";
import pkg from "../../package.json";
import { withFlaggedAutolinking } from "./withFlaggedAutolinking";
Expand Down Expand Up @@ -49,25 +51,57 @@ const withAppleBuildFlags: ConfigPlugin<{ flags: string[] }> = (
});
};

const withBundleFlags: ConfigPlugin<{ flags: string[] }> = (config, props) => {
type BundlePluginProps = { flags: string[] };

const createCrossPlatformMod =
({
config,
props,
}: {
config: ExpoConfig;
props: BundlePluginProps;
}): Mod<unknown> =>
async (modConfig) => {
const { flags } = props;
let flagsToEnable = new Set(flags);
const invertable = await resolveFlagsToInvert(config);
if (invertable.flagsToEnable.size > 0) {
flagsToEnable = mergeSets(flagsToEnable, invertable.flagsToEnable);
}
await generateOverrides({
flagsToEnable,
flagsToDisable: invertable.flagsToDisable,
});
return modConfig;
};

const withAndroidBundleBuildFlags: ConfigPlugin<BundlePluginProps> = (
config,
props
) => {
return withDangerousMod(config, [
"ios", // not platform-specific, but need to specify
async (modConfig) => {
const { flags } = props;
let flagsToEnable = new Set(flags);
const invertable = await resolveFlagsToInvert(config);
if (invertable.flagsToEnable.size > 0) {
flagsToEnable = mergeSets(flagsToEnable, invertable.flagsToEnable);
}
await generateOverrides({
flagsToEnable,
flagsToDisable: invertable.flagsToDisable,
});
return modConfig;
},
"android",
createCrossPlatformMod({ config, props }),
]);
};

const withAppleBundleBuildFlags: ConfigPlugin<BundlePluginProps> = (
config,
props
) => {
return withDangerousMod(config, [
"ios",
createCrossPlatformMod({ config, props }),
]);
};

const withBundleFlags: ConfigPlugin<{ flags: string[] }> = (config, props) => {
return withAppleBundleBuildFlags(
withAndroidBundleBuildFlags(config, props),
props
);
};

const parseEnvFlags = () => {
const envFlags = process.env.EXPO_BUILD_FLAGS;
if (!envFlags) {
Expand Down
4 changes: 4 additions & 0 deletions test/overrides/default-flags.yml
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
mergePath: "constants/buildFlags.ts"
flags:
secretAndroidFeature:
value: false
meta:
team: "platform"
secretFeature:
value: false
meta:
Expand Down
1 change: 1 addition & 0 deletions test/overrides/expected-api-override.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
export const BuildFlags = {
newFeature: true,
publishedFeatured: true,
secretAndroidFeature: false,
secretFeature: false
};
1 change: 1 addition & 0 deletions test/overrides/expected-cli-override.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
export const BuildFlags = {
newFeature: false,
publishedFeatured: true,
secretAndroidFeature: false,
secretFeature: true
};
20 changes: 14 additions & 6 deletions test/run-integration.sh
Original file line number Diff line number Diff line change
@@ -1,13 +1,18 @@
#!/bin/bash

#
# WARNING - these tests build on top of each other
# adjust your initial test flag state accordingly
#

set -e

function logMark () {
echo ""
echo "###################################################################"
echo "$1"
echo "###################################################################"
echo ""
function logMark() {
echo ""
echo "###################################################################"
echo "$1"
echo "###################################################################"
echo ""
}

logMark "Setting up test environment"
Expand All @@ -24,5 +29,8 @@ node ../test/test-babel-plugin.js
logMark "Running test-config-plugin.js"
node ../test/test-config-plugin.js

logMark "Running test-config-plugin-android.js"
node ../test/test-config-plugin-android.js

logMark "Running test-autolinking.js"
node ../test/test-autolinking.js
70 changes: 70 additions & 0 deletions test/test-config-plugin-android.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
const fs = require("fs");
const cp = require("child_process");
const yaml = require("yaml");

const expectedRuntimeModule = `
export const BuildFlags = {
bundleIdScopedFeature: true,
newFeature: true,
publishedFeatured: true,
secretAndroidFeature: true,
secretFeature: false
};
`;

addBundleIdScopedFlag();
installExpoConfigPlugin();
runPrebuild();
assertFlagsAllTrue();

function addBundleIdScopedFlag() {
const flagsYmlString = fs.readFileSync("flags.yml", { encoding: "utf-8" });
const flagConfig = yaml.parse(flagsYmlString);
flagConfig.flags.bundleIdScopedFeature = {
value: false,
invertFor: {
bundleId: ["com.example.app"],
},
};
fs.writeFileSync("flags.yml", yaml.stringify(flagConfig));
}

function installExpoConfigPlugin() {
const expoConfig = JSON.parse(fs.readFileSync("app.json", "utf-8"));
expoConfig.expo.plugins.push("expo-build-flags");
expoConfig.expo.ios.bundleIdentifier = "com.example.app";
expoConfig.expo.android.package = "com.example.app";
fs.writeFileSync("app.json", JSON.stringify(expoConfig, null, 2));
}

function runPrebuild() {
cp.execSync("./node_modules/.bin/expo prebuild -p android --clean", {
env: {
...process.env,
CI: 1,
EXPO_BUILD_FLAGS: "secretAndroidFeature",
},
});
}

function assertFlagsAllTrue() {
const fileContents = fs.readFileSync("constants/buildFlags.ts", "utf8");
if (fileContents.trim() !== expectedRuntimeModule.trim()) {
console.log(
"received:\n\n",
`>${fileContents.trim()}<`,
"\n\n",
"expected:\n\n",
`>${expectedRuntimeModule.trim()}<`,
"\n\n"
);

throw new Error(
"Expected runtime buildFlags.ts module to contain all flags as true"
);
}

console.log(
"Assertion passed: Runtime build flags enabled by config plugin!"
);
}
1 change: 1 addition & 0 deletions test/test-config-plugin.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ export const BuildFlags = {
bundleIdScopedFeature: true,
newFeature: true,
publishedFeatured: true,
secretAndroidFeature: false,
secretFeature: true
};
`;
Expand Down