AQuirky
AQuirky

Reputation: 5236

Unable to deploy typescript express app to Azure

I'm trying to deploy a simply typescript express app to Azure. I found this helpful blog post...

I want to transpile the typescript code as part of the deployment.

http://Codefoster.com/tscazure

the gist of which is to install azure cli

npm install -g azure-cli

then create custom deployment script

npm site deploymentscript --node

so now I have in the root of the project a .deployment file...

[config]
command = deploy.cmd

Also in the root a deploy.cmd, which I modified to add the following sections...

:: 3. Install npm packages
IF EXIST "%DEPLOYMENT_TARGET%\package.json" (
  pushd "%DEPLOYMENT_TARGET%"
  call :ExecuteCmd !NPM_CMD! install --production
  IF !ERRORLEVEL! NEQ 0 goto error
  popd
)

:: 4. Compile Typescript

TSC="$DEPLOYMENT_TARGET/node_modules/typescript/bin/tsc"
echo "Building Typescript files."
"$TSC"
exitWithMessageOnError "Could not run 'tsc'.  Did 'npm install'"

Also in root is a package.json file that contains this...

{
  "name": "api-server",
  "version": "1.0.0",
  "description": "API server",
  "main": "index.js",
  "scripts": {
    "build": "tsc",
    "start": "node build/src | pino-colada",
    "dev": "ts-node src | pino-colada"
 },
 "author": "",
 "license": "ISC",
 "dependencies": {
    "@babel/types": "^7.8.0",
    "@types/express": "^4.17.2",
    "azure-cli": "^0.10.20",
    "bcrypt": "^3.0.7",
    "bookshelf": "^1.0.1",
    "express": "^4.17.1",
    "express-pino-logger": "^4.0.0",
    "jsonwebtoken": "^8.5.1",
    "knex": "^0.20.7",
    "mysql": "^2.17.1",
    "pino-colada": "^1.5.0",
    "typescript": "^3.7.4",
    "validator": "^12.1.0"
 },
 "proxy": "http://localhost:3201"
}

I push the code to GitHub and I create the WebApp using defaults, (Linux and Node LTS)

I deploy from Azure, the deployment fails and the log shows this...

Command: deploy.cmd
/opt/Kudu/Scripts/starter.sh: line 2: exec: deploy.cmd: not found
/opt/Kudu/Scripts/starter.sh: line 2: exec: deploy.cmd: not found\n/opt/Kudu/Scripts/starter.sh deploy.cmd

So what am I doing wrong?

Upvotes: 1

Views: 1117

Answers (1)

AQuirky
AQuirky

Reputation: 5236

Right...

After a lot of heartache I finally got this going. The fundamental issue is that my dev box is Windows and the Azure Web App is Linux. Therefore deploy.cmd is not going to fly at all. You need a deploy.sh bash script to run on Linux. There is apparently no way to generate it on Windows...you need fire up your Linux box and use

azure site deploymentscript --node

to get it. You cannot download the script from existing Web App...the docs are either wrong or obsolete. But you don't have to do that...here it is:

#!/bin/bash

# ----------------------
# KUDU Deployment Script
# Version: 1.0.17
# ----------------------

# Helpers
# -------

exitWithMessageOnError () {
  if [ ! $? -eq 0 ]; then
    echo "An error has occurred during web site deployment."
    echo $1
    exit 1
  fi
}

# Prerequisites
# -------------

# Verify node.js installed
hash node 2>/dev/null
exitWithMessageOnError "Missing node.js executable, please install node.js, if already installed make sure it can be reached from current environment."

# Setup
# -----

SCRIPT_DIR="${BASH_SOURCE[0]%\\*}"
SCRIPT_DIR="${SCRIPT_DIR%/*}"
ARTIFACTS=$SCRIPT_DIR/../artifacts
KUDU_SYNC_CMD=${KUDU_SYNC_CMD//\"}

if [[ ! -n "$DEPLOYMENT_SOURCE" ]]; then
  DEPLOYMENT_SOURCE=$SCRIPT_DIR
fi

if [[ ! -n "$NEXT_MANIFEST_PATH" ]]; then
  NEXT_MANIFEST_PATH=$ARTIFACTS/manifest

  if [[ ! -n "$PREVIOUS_MANIFEST_PATH" ]]; then
    PREVIOUS_MANIFEST_PATH=$NEXT_MANIFEST_PATH
  fi
fi

if [[ ! -n "$DEPLOYMENT_TARGET" ]]; then
  DEPLOYMENT_TARGET=$ARTIFACTS/wwwroot
else
  KUDU_SERVICE=true
fi

if [[ ! -n "$KUDU_SYNC_CMD" ]]; then
  # Install kudu sync
  echo Installing Kudu Sync
  npm install kudusync -g --silent
  exitWithMessageOnError "npm failed"

  if [[ ! -n "$KUDU_SERVICE" ]]; then
    # In case we are running locally this is the correct location of kuduSync
    KUDU_SYNC_CMD=kuduSync
  else
    # In case we are running on kudu service this is the correct location of kuduSync
    KUDU_SYNC_CMD=$APPDATA/npm/node_modules/kuduSync/bin/kuduSync
  fi
fi

# Node Helpers
# ------------

selectNodeVersion () {
  if [[ -n "$KUDU_SELECT_NODE_VERSION_CMD" ]]; then
    SELECT_NODE_VERSION="$KUDU_SELECT_NODE_VERSION_CMD \"$DEPLOYMENT_SOURCE\" \"$DEPLOYMENT_TARGET\" \"$DEPLOYMENT_TEMP\""
    eval $SELECT_NODE_VERSION
    exitWithMessageOnError "select node version failed"

    if [[ -e "$DEPLOYMENT_TEMP/__nodeVersion.tmp" ]]; then
      NODE_EXE=`cat "$DEPLOYMENT_TEMP/__nodeVersion.tmp"`
      exitWithMessageOnError "getting node version failed"
    fi

    if [[ -e "$DEPLOYMENT_TEMP/__npmVersion.tmp" ]]; then
      NPM_JS_PATH=`cat "$DEPLOYMENT_TEMP/__npmVersion.tmp"`
      exitWithMessageOnError "getting npm version failed"
    fi

    if [[ ! -n "$NODE_EXE" ]]; then
      NODE_EXE=node
    fi

    NPM_CMD="\"$NODE_EXE\" \"$NPM_JS_PATH\""
  else
    NPM_CMD=npm
    NODE_EXE=node
  fi
}

##################################################################################################################################
# Deployment
# ----------

echo Handling node.js deployment.

# 1. KuduSync
if [[ "$IN_PLACE_DEPLOYMENT" -ne "1" ]]; then
  "$KUDU_SYNC_CMD" -v 50 -f "$DEPLOYMENT_SOURCE" -t "$DEPLOYMENT_TARGET" -n "$NEXT_MANIFEST_PATH" -p "$PREVIOUS_MANIFEST_PATH" -i ".git;.hg;.deployment;deploy.sh"
  exitWithMessageOnError "Kudu Sync failed"
fi

# 2. Select node version
# selectNodeVersion
NPM_CMD=npm
NODE_EXE=node

# 3. Install npm packages
if [ -e "$DEPLOYMENT_TARGET/package.json" ]; then
  cd "$DEPLOYMENT_TARGET"
  echo "Running $NPM_CMD install --production"
  eval $NPM_CMD install --production
  exitWithMessageOnError "npm failed"
  cd - > /dev/null
fi

# 4. Compile Typescript

TSC="$DEPLOYMENT_TARGET/node_modules/typescript/bin/tsc"
echo "Building Typescript files."
cd "$DEPLOYMENT_TARGET"
"$TSC"
exitWithMessageOnError "Could not run 'tsc'.  Did 'npm install'"
cd - > /dev/null

echo "Finished Typescript build."



##################################################################################################################################
echo "Finished successfully."

Now the .deployment file looks like this...

[config]
command = bash deploy.sh

Note the following:

  • In deploy.sh step 2, I commented out the node selection function and simply set the node and npm commands directly. The node selection function simply does not work.
  • I added deploy.sh step 4 to compile the typescript.

Here are a few other things you should know that don't seem to be documented anywhere:

  • The PORT and the SSH_PORT environment variables contain the only 2 port that are open. These were 8080 and 2222 on my web app.

Upvotes: 1

Related Questions