def run_test() -> None: env = os.environ.copy() env["TANKER_SDK_DEBUG"] = "1" src_path = Path.cwd() # fmt: off tankerci.run( "poetry", "run", "pytest", "--verbose", "--capture=no", "--cov=tankersdk", "--cov-report", "html", "--numprocesses", "auto", env=env, cwd=src_path, ) # fmt: on coverage_dir = src_path / "htmlcov" dest_dir = Path.cwd() / "coverage" if dest_dir.exists(): shutil.rmtree(dest_dir) shutil.copytree(coverage_dir, dest_dir)
def build(profile: str, release_version: Optional[str], tanker_ref: str, test: bool) -> None: tankerci.run("poetry", "install", cwd=Path.cwd()) if release_version: build_wheel(profile, release_version, tanker_ref) if test: run_test()
def run_end_to_end_tests(app): ensure_default_browser_not_started(app) config_path = write_server_config() src_path = get_src_path() tests_path = src_path / "tests" with tankerci.run_in_background("yarn", "start", "--config", config_path, cwd=src_path): with tankerci.run_in_background("yarn", "start:web:%s" % app, cwd=src_path): # We let the server and the app time to fully start, # otherwise, browser might be stuck in a no man's land time.sleep(1) snake_case_name = app.replace("-", "_") pytest_file = f"test_{snake_case_name}.py" env = os.environ.copy() # On Ubuntu chromedriver is in /usr/lib/chromium-browser because reasons, # so add that to PATH. # This is required for Selenium to work. env["PATH"] = "/usr/lib/chromium-browser:" + env["PATH"] # fmt: off tankerci.run( "poetry", "run", "pytest", "--verbose", "--capture=no", "--headless", tests_path / pytest_file, check=True, env=env, )
def handle_ios_deps(self) -> None: ui.info_2("Installing Tanker pod dependencies") tankerci.run("pod", "install", "--repo-update", "--clean-install", cwd=self.example_path)
def get_android_bin_path() -> Path: # We need to specify an android profile or conan can't find the binary # package. The specific profile is not important since there is only one # binary NDK, the recipe ignores the arch, api_level, etc. tankerci.run( "conan", "install", "android_ndk_installer/r22b@", "--profile", "android-armv7-release", ) _, out = tankerci.run_captured( "conan", "info", "android_ndk_installer/r22b@", "--profile", "android-armv7-release", "--json", "--paths", ) try: info = json.loads(out) package_path = Path(info[0]["package_folder"]) bin_path = package_path / "toolchains/llvm/prebuilt/linux-x86_64/bin" return bin_path except (json.JSONDecodeError, KeyError, IndexError): if out: ui.error(f"Failed to parse output: {out}") raise
def test(self) -> None: self.build() if not self._is_host_target: ui.info(self.profile, "is a cross-compiled target, skipping tests") return tankerci.run("cargo", "fmt", "--", "--check", cwd=self.src_path) tankerci.run( "cargo", "clippy", "--all-targets", "--", "--deny", "warnings", "--allow", "unknown-lints", cwd=self.src_path, ) if self._is_windows_target: shutil.copy( Path("native") / self.target_triplet / "ctanker.dll", Path("target") / "debug/deps", ) self._cargo("test")
def build_and_test(profile: str, tanker_source: TankerSource, tanker_ref: Optional[str] = None) -> None: prepare(profile, tanker_source, False, tanker_ref) # -v shows the logs as they appear, even if tests wlll succeed # -ginkgo.v shows the name of each test as it starts # -count=1 forces the tests to run instead of showing a cached result tankerci.run("go", "test", "./...", "-v", "-ginkgo.v", "-count=1")
def deploy(*, version: str, tanker_ref: str) -> None: tankerci.bump_files(version) prepare(TankerSource.DEPLOYED, False, tanker_ref) build() ui.info_1("Deploying SDK to https://storage.googleapis.com/maven.tanker.io") tankerci.gcp.GcpProject("tanker-prod").auth() tankerci.run("./gradlew", "tanker-bindings:publish")
def deploy(*, git_tag: str) -> None: version = tankerci.version_from_git_tag(git_tag) tankerci.bump_files(version) build_and_test() ui.info_1("Deploying Identity SDK to maven.tanker.io") tankerci.gcp.GcpProject("tanker-prod").auth() tankerci.run("./gradlew", "publish")
def build_and_test() -> None: ui.info_1("Building everything") tankerci.run("./gradlew", "assemble") ui.info_1("Running tests") # In case you're wondering: # https://stackoverflow.com/questions/50104666/gradle-difference-between-test-and-check tankerci.run("./gradlew", "test")
def build_and_test_pod(self) -> None: ui.info_2("building pod and launching tests") tankerci.run( "pod", "lib", "lint", "--verbose", "--allow-warnings", str(self.pod_path / "Tanker.podspec"), )
def generate_archive(self) -> Path: version = self.get_version_from_spec() ui.info_1("Generating archive, version:", version) archive_name = "tanker-ios-sdk-%s.tar.gz" % version with tankerci.working_directory(self.dest_path): tankerci.run("tar cfvz %s *" % archive_name, shell=True) shutil.copy(archive_name, self.src_path) res = self.src_path / archive_name ui.info_2("Generated", res) return res
def test_deploy(*, version: str) -> None: test_dir = Path("test") index_file = test_dir / "index.js" test_dir.mkdir() tankerci.js.run_yarn("init", "--yes", cwd=test_dir) tankerci.js.run_yarn("add", f"@tanker/client-browser@{version}", cwd=test_dir) index_file.write_text('require("@tanker/client-browser");') tankerci.run("node", "index.js", cwd=test_dir)
def publish_npm_package(package_name: str, version: str) -> None: package_path = get_package_path(package_name) npm_tag = version_to_npm_tag(version) tankerci.run("npm", "publish", "--access", "public", "--tag", npm_tag, cwd=package_path)
def build() -> None: tankerci.run("./gradlew", "tanker-bindings:buildNativeRelease") tankerci.run("./gradlew", "tanker-bindings:assembleRelease") dest_path = Path.cwd() / "artifacts" shutil.rmtree(dest_path, ignore_errors=True) dest_path.mkdir(parents=True) shutil.copy( Path.cwd() / "tanker-bindings/build/outputs/aar/tanker-bindings-release.aar", dest_path / "tanker-bindings.aar", )
def build_pod(self) -> None: # fmt: off tankerci.run( "pod", "spec", "lint", "Tanker/Tanker.podspec", "--verbose", "--allow-warnings", "--skip-tests", cwd=self.src_path, )
def check(): shutil.copy("src/config.dev.js", "src/config.js") tankerci.run("yarn") with tankerci.run_in_background("yarn", "start"): # fmt: off tankerci.run( "poetry", "run", "pytest", "--verbose", "--capture=no", "--headless", )
def publish_pod(self) -> None: # fmt: off tankerci.run( "pod", "repo", "push", "tanker", "Tanker/Tanker.podspec", "--skip-tests", "--verbose", "--allow-warnings", cwd=self.src_path, )
def _cargo(self, subcommand: str) -> None: tankerci.run("cargo", subcommand, "--target", self.target_triplet, cwd=self.src_path) if self._is_windows_target: tankerci.run( "cargo", subcommand, "--target", "x86_64-pc-windows-gnu", cwd=self.src_path, )
def deploy(args: argparse.Namespace) -> None: compiled_targets = [p.name for p in Path("native").iterdir() if p.is_dir()] missing_targets = [ target for target in TARGET_LIST if target not in compiled_targets ] if missing_targets: ui.fatal("Aborting deploy because of missing targets:", *missing_targets) version = args.version registry = args.registry tankerci.bump_files(version) tankerci.run("cargo", "publish", "--allow-dirty", f"--registry={registry}")
def build(self) -> None: if not self._is_host_target: if self.target_triplet == "aarch64-apple-ios-sim": tankerci.run( "cargo", "+nightly", "build", "-Z", "build-std", "--target", self.target_triplet, cwd=self.src_path, ) return self._cargo("build")
def run_mypy(): src_path = get_src_path() tests_path = src_path / "tests" env = os.environ.copy() env["MYPYPATH"] = tests_path / "stubs" # fmt: off tankerci.run( "poetry", "run", "mypy", "--strict", "--ignore-missing-imports", tests_path, check=True, env=env, )
def prepare( tanker_source: TankerSource, host_profile: Profile, update: bool, tanker_ref: Optional[str], ) -> None: tanker_deployed_ref = tanker_ref if tanker_source == TankerSource.DEPLOYED and not tanker_deployed_ref: tanker_deployed_ref = "tanker/latest-stable@" tankerci.conan.install_tanker_source( tanker_source, output_path=Path.cwd() / "conan", host_profiles=[host_profile], build_profile=tankerci.conan.get_build_profile(), tanker_deployed_ref=tanker_deployed_ref, ) tankerci.run("bundle", "install") tankerci.run("bundle", "exec", "rake", "tanker_libs")
def test() -> None: ui.info_1("Building tests") tankerci.run("./gradlew", "packageReleaseAndroidTest", "-PandroidTestRelease") ui.info_1("Running tests") try: with tankerci.android.emulator(): try: tankerci.run( "./gradlew", "connectedAndroidTest", "-PandroidTestRelease" ) except Exception: dump_logcat_for_failed_tests() tankerci.android.take_screenshot(Path.cwd() / "screenshot.png") raise finally: shutil.copytree( "tanker-bindings/build/reports", Path.cwd() / "artifacts/reports" )
def deploy() -> None: env = os.environ.copy() env["TWINE_PASSWORD"] = env["GITLAB_TOKEN"] env["TWINE_USERNAME"] = env["GITLAB_USERNAME"] wheels_path = Path.cwd() / "dist" for wheel in wheels_path.glob("tankersdk-*.whl"): # fmt: off tankerci.run( "poetry", "run", "twine", "upload", str(wheel), "--repository-url", PUBLIC_REPOSITORY_URL, env=env, )
def build_wheel(profile: str, version: str, tanker_ref: str) -> None: src_path = Path.cwd() tankerci.bump.bump_files(version) dist_path = src_path / "dist" if dist_path.exists(): shutil.rmtree(dist_path) env = os.environ.copy() env["TANKER_PYTHON_SDK_SRC"] = str(src_path) # Note: poetry generates a temporary directory, # change the working directory there, creates a `setup.py` # from scratch (calling `build.py`) and runs it. # In the process, all the conan files generated in the # sources gets lost. We set this environment variable # so that they can be found even when the working directory # changes, and we make sure *all* paths used in build_tanker.py # are absolute tankerci.run("poetry", "build", env=env) wheels = list(dist_path.glob("tankersdk-*.whl")) if len(wheels) != 1: raise Exception("multiple wheels found: {}".format(wheels))
def run_android_tests(src_path): config_path = write_server_config() tankerci.run("./gradlew", "assembleLocalhost", cwd=src_path) tankerci.run("./gradlew", "assembleAndroidTest", cwd=src_path) apk_folder = src_path / "app/build/outputs/apk" app_url = send_app(apk_folder) test_url = send_tests(apk_folder) tankerci.run("yarn") devices = [ "Google Pixel 3-9.0", "Samsung Galaxy S9-8.0", "Samsung Galaxy S6-5.0" ] config = { "devices": devices, "app": app_url, "deviceLogs": "true", "testSuite": test_url, "local": "true", } with tankerci.run_in_background("BrowserStackLocal", "--key", get_browserstack_key()): # Wait for the tunnel to BrowserStack to be established time.sleep(5) with tankerci.run_in_background("yarn", "start", "--config", config_path): build_id = start_build(config) success = poll_build_status(build_id, devices) if not success: raise Exception("Timeout: BrowserStack tests are still running")
def bind_gen(*, header_source: Path, output_file: Path, include_path: Path, dynamic_loading: bool) -> None: # bindgen will call clang, which needs vcvarsall to be set # otherwise, it will fail to find stdbool.h tankerci.cpp.set_build_env() args = [] if dynamic_loading: args += [ "--dynamic-loading", "ctanker_api", ] tankerci.run( "bindgen", *args, "--no-layout-tests", str(header_source), "-o", str(output_file), "--", "-I", str(include_path), )
def deploy(): shutil.copy("src/config.prod.js", "src/config.js") tankerci.run("yarn") tankerci.run("yarn", "build") commit_sha = os.environ["CI_COMMIT_SHA"] message = f"Deploy {commit_sha}" # Ensure 'github' remote exists tankerci.run("git", "remote", "remove", "github", check=False) tankerci.run("git", "remote", "add", "github", GITHUB_URL) # fmt: off tankerci.run( "ghp-import", "--message", message, "--remote", "github", "--push", "--force", "--no-jekyll", "build/", )
def _merge_all_libs(self, depsConfig: DepsConfig, package_path: Path, native_path: Path) -> None: with tankerci.working_directory(package_path): env = os.environ.copy() if self._is_android_target: android_bin_path = get_android_bin_path() env["LD"] = str(android_bin_path / "ld.lld") env["OBJCOPY"] = str(android_bin_path / "llvm-objcopy") ui.info(f'Using {env["LD"]}') ui.info(f'Using {env["OBJCOPY"]}') if self._is_ios_target: env["ARMERGE_LDFLAGS"] = "-bitcode_bundle" libctanker_a = Path("libctanker.a") if libctanker_a.exists(): libctanker_a.unlink() package_libs = package_path / "deplibs" package_libs.mkdir(parents=True, exist_ok=True) for lib_path in depsConfig.all_lib_paths(): ui.info_1("copying", lib_path, "to", package_libs) shutil.copy(lib_path, package_libs) # Apple prefixes symbols with '_' tankerci.run( "armerge --keep-symbols '^_?tanker_.*' --output libctanker.a" " deplibs/*.a", shell=True, env=env, ) if self._is_android_target: llvm_strip = android_bin_path / "llvm-strip" # HACK: Android forces debug symbols, we need to patch the # toolchain to remove them. Until then, strip them here. tankerci.run(str(llvm_strip), "--strip-debug", "--strip-unneeded", "libctanker.a") shutil.copy("libctanker.a", native_path)