Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

MVP for passing in custom config path #461

Merged
merged 3 commits into from
Feb 11, 2021

Conversation

toastal
Copy link
Contributor

@toastal toastal commented Feb 9, 2021

I have never used TypeScript and am not familiar with the tooling or coding styles of this project so I did the bare minimum that got my code running and your tests green (with no new tests). I believe this can address some of this issues in #457 in conjunction with process substitution in Bash, Fish, etc. to make a JSON "file" on the fly.

@toastal
Copy link
Contributor Author

toastal commented Feb 9, 2021

Considering I got here in fish

$ bubblewrap init --config .bubblewrap/config.json --manifest (dhall-to-json --file manifest.dhall | psub)                                                                                                 bosthlm 
,-----.        ,--.  ,--.  ,--.
|  |) /_,--.,--|  |-.|  |-.|  |,---.,--.   ,--,--.--.,--,--.,---.
|  .-.  |  ||  | .-. | .-. |  | .-. |  |.'.|  |  .--' ,-.  | .-. |
|  '--' '  ''  | `-' | `-' |  \   --|   .'.   |  |  \ '-'  | '-' '
`------' `----' `---' `---'`--'`----'--'   '--`--'   `--`--|  |-'
                                                           `--'    
Initializing application from Web Manifest:
	-  /run/user/1000/.psub.8n72sG4Hcf


cli ERROR Only absolute URLs are supported

I would say it's working so far for me. I'll work on how to generate my own config file shortly.

@toastal
Copy link
Contributor Author

toastal commented Feb 9, 2021

So far my shell.nix is for being able to install bubblewrap via yarn inside the shell (not globally). libuuid was the missing library I did not see in the various docs but prevented canvas from running.

{
  pkgs ? import (fetchTarball "https://github.com/NixOS/nixpkgs/archive/3f0e6e1daaa071b38121029c12de7c260286d719.tar.gz")
    { config = { android_sdk.accept_license = true; }; }
}:

with pkgs.lib;

let
  bubblewrapBuildToolsVersion = "29.0.2";

  androidComposition = pkgs.androidenv.composeAndroidPackages {
    toolsVersion = "26.1.1";
    platformToolsVersion = "30.0.5";
    buildToolsVersions = [ bubblewrapBuildToolsVersion ];
    platformVersions = [ "29" "30" ];
  };


in pkgs.mkShell {
  name = "xxxxxx";

  basePackages = with pkgs; [
    gawk
    jq
    ripgrep
  ];

  nativeBuildInputs = with pkgs.buildPackages; [
    # node
    nodejs-14_x
    yarn

    # dhall
    dhall
    dhall-bash
    dhall-json

    # android
    androidComposition.androidsdk
    cairo
    giflib
    gnome2.pango
    jdk8_headless
    libjpeg
    libuuid
    librsvg
    pkg-config
  ];

  ANDROID_SDK_ROOT = "${androidComposition.androidsdk}/libexec/android-sdk";

  GRADLE_OPTS = "-Dorg.gradle.project.android.aapt2FromMavenOverride=${ANDROID_SDK_ROOT}/build-tools/${bubblewrapBuildToolsVersion}/aapt2";

  LD_LIBRARY_PATH = "${makeLibraryPath (with pkgs; [
    giflib
    libjpeg
    librsvg
    libuuid
  ])}";
}

and wrapping bubblewrap with a shell script

#!/usr/bin/env bash
set -f

project_root_dir="$(cd "$(dirname 0)/.."; pwd -P)"
node_bin="$(cd "$project_root_dir"; yarn bin)"

# Just a wrapper around `bubblewrap` to inject Nix store directories
# into a config file.

if [ -z "$IN_NIX_SHELL" ]; then
  $node_bin/bubblewrap "$@"
else
  dhall_expr="$(cat <<EOF
    { jdkPath = "$(nix-build --no-out-link '<nixpkgs>' -A jdk8_headless)" : Text
    , androidSdkPath = "$(nix-store --query --referrers "$(which adb)")/libexec/android-sdk" : Text
    }
EOF
)"
  $node_bin/bubblewrap "$@" --config <(dhall-to-json --compact <<< $dhall_expr)
fi

prompt: Prompt = new InquirerPrompt(), path = DEFAULT_CONFIG_FILE_PATH): Promise<Config> {
await renameConfigIfNeeded(log);
const existingConfig = await Config.loadConfig(path);
export async function loadOrCreateConfig(
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure I understand this change - it seems the end result is the same as the previous version.

In the section below, path is only assigned DEFAULT_CONFIG_FILE_PATH if the value passed is different from null and different from undefined:

export async function loadOrCreateConfig(
    prompt: Prompt = new InquirerPrompt(), path = DEFAULT_CONFIG_FILE_PATH): Promise<Config> {

so, generally analog to:

  if (path === undefined) {
    await renameConfigIfNeeded(log);
    configPath = DEFAULT_CONFIG_FILE_PATH;
  } else {
    configPath = path;
  }

the only difference being the call to await renameConfigIfNeeded(log). But that call should be no-op in most cases (it's just about handling old config paths to the current one).

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Well it is calling out to filesystem which is a slow and unnecessary operation if we are already sure we don't need to do it, right?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not to mention you could be renaming a users input file which would be unexpected when rerunning a command.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hitting the filesystem shouldn't be such a large overhead in this case and renaming will only happen for a very specific filename, so I'm generally happy with the solution. Nevertheless, those are good points.

It sounds to me loadOrCreateConfig() is doing too much. Maybe a better alternative is to rename this function to loadOrCreateDefaultConfig() and when parsedArgs.config is available just call Config.loadConfig() instead of this function.

PS: It's also possible to call Config.deserialize() to parse a JSON or build a config with a new Config(jdkPath, androidSdkPath). Would passing those strings from the command line make it a better solution for your use-case?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't want to be in charge of function naming.

I think this is a very fast solution that can work for a lot of odd use case as anyone can make a config on the fly but they can also check in and use a local config file (mine is at project/workspace/.bubblewrap/config.json). This mean a user could say put the config in package.json and use jq to read and pass in through process substitution.

I plan to use Dhall everywhere and dhall-to-json for my configuration because I want types for my configuration (makes me want my twa-manifest.json to be typed too which I'm working on). Also with this solution I can to call nix-build --no-out-link '<nixpkgs>' -A jdk8_headless to get the current version of JDK (same for Android SDK) on the fly which currently is at /nix/store/q839v7q4k8s958zs2smmwm6id72xjsva-openjdk-headless-8u272-b10. I need reproducible builds ... including all building tools and libraries, so everything needs to be local to nix-shell which includes bubblewrap and all its dependencies. I may make a derivation if time allows that contains all the bits that make this work on Nix.

const parsedArgs = minimist(args);

const config = await loadOrCreateConfig(
Copy link
Member

@andreban andreban Feb 9, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If we revert loadOrCreateConfig(), we should be able to call loadOrCreateConfig(undefined, undefined, parsedArgs.config). So, the 1st and 2nd parameters get the default value and the last uses parsedArgs.config. If parsedArgs.config is null, it will use the default value.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Well, since there aren't named arguments, and they were cases where some were used and some not, I figured a dictionary would be cleaner than loadOrCreateConfig(undefined, undefined, parsedArgs.config), but I don't really care one way or another on the style.

@andreban
Copy link
Member

andreban commented Feb 9, 2021

@toastal thank you very much for this! The contribution is much appreciated! I dropped a couple of comments.

@andreban
Copy link
Member

andreban commented Feb 9, 2021

Considering I got here in fish

$ bubblewrap init --config .bubblewrap/config.json --manifest (dhall-to-json --file manifest.dhall | psub)                                                                                                 bosthlm 
,-----.        ,--.  ,--.  ,--.
|  |) /_,--.,--|  |-.|  |-.|  |,---.,--.   ,--,--.--.,--,--.,---.
|  .-.  |  ||  | .-. | .-. |  | .-. |  |.'.|  |  .--' ,-.  | .-. |
|  '--' '  ''  | `-' | `-' |  \   --|   .'.   |  |  \ '-'  | '-' '
`------' `----' `---' `---'`--'`----'--'   '--`--'   `--`--|  |-'
                                                           `--'    
Initializing application from Web Manifest:
	-  /run/user/1000/.psub.8n72sG4Hcf


cli ERROR Only absolute URLs are supported

I would say it's working so far for me. I'll work on how to generate my own config file shortly.

It seems to me you are bumping into #401 - we require an URL as the --manifest parameter.

@toastal
Copy link
Contributor Author

toastal commented Feb 10, 2021

I was going to make a separate twa-manifest.dhall file deriving from the manifest.dhall file I already have where I could include some of these new attributes. I REALLY wish the differences in these manifests were documented somewhere else other than in the config TS code. I tried searching for documentation about the twa-manifest.json and its additional properties, but got nothing.

Found it in the code though.

@andreban
Copy link
Member

The best place to check for the twa-manifest.json values is this bit of code.

Copy link
Member

@andreban andreban left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM, Thank you! Shall I merge this then?

@toastal
Copy link
Contributor Author

toastal commented Feb 11, 2021

Yeah, that be great.

@andreban andreban merged commit d628122 into GoogleChromeLabs:master Feb 11, 2021
@toastal
Copy link
Contributor Author

toastal commented Feb 11, 2021

How often do you cut releases?

@andreban
Copy link
Member

We don't have a fixed schedule, due to development not moving at a constant rate. I want to get #463 merged and update the docs with the --config option for the next release.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants