def build_push(self, force=False, dev=False, push=False, no_cache=False):
        """
        Builds a user service, if changed, and pushes  to repo if requested
        """
        builder = DockerBuild(push, no_cache)
        self.dev = dev
        dockerfile = '.Dockerfile'

        if force or not self.image_exists or self.image_stale():
            log.debug("Image not found or stale - building...")
            # run barrister and copy shim
            rpc.generate_contract()
            self.stack.copy_shim()

            try:
                builder.gen_dockerfile('Dockerfile-service.txt', dict(service=self), dockerfile)
                builder.build_dockerfile(self.full_name, dockerfile)
            finally:
                self.stack.del_shim()

            log.info("{} build complete".format(self.short_name))
        else:
            log.info("Build not necessary, run with '--force' to override")

        builder.push_image(self.full_name)
    def run(self):
        toolkit_stack = stacks[self.hutcfg.stack]
        toolkit_stack.copy_shim()
        rpc.generate_contract()

        try:
            backend = LocalBackend(self.hutcfg, self.usercfg.username, port=self.port)
            with ServiceRunner(backend, self.hutcfg) as runner:
                log.info("Running service '{}' on http://127.0.0.1:{}".format(backend.service_short_name, self.port))
                runner.run()
        finally:
            toolkit_stack.del_shim()
            os.remove(rpc.REQ_FIFO)
            os.remove(rpc.RESP_FIFO)
    def run(self):
        super().run()

        # validation checks
        self.usercfg.assert_logged_in()

        service = Service(self.hutcfg, self.usercfg.username)

        # run the contract regardless
        rpc.generate_contract()

        if self.local:
            # call build+push first using Docker builder
            if not self.no_build:
                service.build_push(force=self.force, push=True, dev=self.dev)
        else:
            import tempfile
            import requests
            import os.path
            from stackhut_common import utils
            from stackhut_client import client

            log.info("Starting Remote build, this may take a while (especially the first time), please wait...")

            # compress and upload the service
            with tempfile.NamedTemporaryFile(suffix=".tar.gz", delete=False) as f:
                f.close()

            # get the upload url
            r_file = stackhut_api_user_call("file", dict(filename=os.path.basename(f.name)), self.usercfg)

            sh.tar(
                "-czvf",
                f.name,
                "--exclude",
                ".git",
                "--exclude",
                "__pycache__",
                "--exclude",
                "run_result",
                "--exclude",
                ".stackhut",
                ".",
            )
            log.debug("Uploading package {} ({:.2f} Kb)...".format(f.name, os.path.getsize(f.name) / 1024))
            with open(f.name, "rb") as f1:
                with Spinner():
                    r = requests.put(r_file["url"], data=f1)
                r.raise_for_status()
            # remove temp file
            os.unlink(f.name)

            # call the remote build service
            auth = client.SHAuth(self.usercfg.username, hash=self.usercfg["hash"])
            sh_client = client.SHService("stackhut", "stackhut", auth=auth, host=utils.SERVER_URL)
            log.debug("Uploaded package, calling remote build...")
            try:
                with Spinner():
                    r = sh_client.Default.remoteBuild(r_file["key"], self.dev)

            except client.SHRPCError as e:
                log.error("Build error, remote build output below...")
                log.error(e.data["output"])
                return 1
            else:

                log.debug("Remote build output...\n" + r["cmdOutput"])
                if not r["success"]:
                    raise RuntimeError("Build failed")
                log.info("...completed Remote build")

        # Inform the SH server re the new/updated service
        # build up the deploy message body
        test_request = json.loads(self._read_file("test_request.json"))
        readme = self._read_file("README.md")

        data = {
            "service": service.short_name,  # StackHut Service,
            "github_url": self.hutcfg.github_url,
            "example_request": test_request,
            "description": self.hutcfg.description,
            "private_service": self.hutcfg.private,
            "readme": readme,
            "schema": self.create_methods(),
        }

        log.info("Deploying image '{}' to StackHut".format(service.short_name))
        r = stackhut_api_user_call("add", data, self.usercfg)
        log.info("Service {} has been {} and is live".format(service.short_name, r["message"]))
        log.info("You can now call this service with our client-libs or directly over JSON+HTTP")
        return 0