Repository: serverless/serverless-azure-functions
Pull request #257 (2019-08-19 21:29:35)

feat: Specify Node.js runtime version in serverless.yml
Specify Node.js runtime version in serverless.yml under provider. Throws an error for invalid Node.js version. 

AB#704

coveralls: 
[![Coverage Status](https://coveralls.io/builds/25225074/badge)](https://coveralls.io/builds/25225074)

Coverage decreased (-0.05%) to 84.569% when pulling **05f4eed612b1ab4533a1bd09edc98d140c7dca95 on nemand/nodeRuntime** into **44185c5db4f80c88c4e32b30a0012fb30fe5ee21 on dev**.

njm3754: Made some more changes. Now if the user does not specify runtime version the plugin throws an errors and just does not use the default value (10.14.1), Also added a new test case.

Patch:
diff --git a/package-lock.json b/package-lock.json
index a438c76..d012bd9 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -157,6 +157,12 @@
             "minimist": "^1.2.0"
           }
         },
+        "semver": {
+          "version": "5.7.1",
+          "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz",
+          "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==",
+          "dev": true
+        },
         "source-map": {
           "version": "0.5.7",
           "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz",
@@ -901,6 +907,14 @@
         "@babel/helper-plugin-utils": "^7.0.0",
         "resolve": "^1.8.1",
         "semver": "^5.5.1"
+      },
+      "dependencies": {
+        "semver": {
+          "version": "5.7.1",
+          "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz",
+          "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==",
+          "dev": true
+        }
       }
     },
     "@babel/plugin-transform-shorthand-properties": {
@@ -1025,6 +1039,14 @@
         "invariant": "^2.2.2",
         "js-levenshtein": "^1.1.3",
         "semver": "^5.5.0"
+      },
+      "dependencies": {
+        "semver": {
+          "version": "5.7.1",
+          "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz",
+          "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==",
+          "dev": true
+        }
       }
     },
     "@babel/preset-react": {
@@ -1365,6 +1387,12 @@
           "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.0.tgz",
           "integrity": "sha512-8dG4H5ujfvFiqDmVu9fQ5bOHUC15JMjMY/Zumv26oOvvVJjM67KF8koCWIabKQ1GJIa9r2mMZscBq/TbdOcmNA==",
           "dev": true
+        },
+        "semver": {
+          "version": "5.7.1",
+          "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz",
+          "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==",
+          "dev": true
         }
       }
     },
@@ -1794,6 +1822,7 @@
       "version": "0.1.4",
       "resolved": "https://registry.npmjs.org/align-text/-/align-text-0.1.4.tgz",
       "integrity": "sha1-DNkKVhCT810KmSVsIrcGlDP60Rc=",
+      "optional": true,
       "requires": {
         "kind-of": "^3.0.2",
         "longest": "^1.0.1",
@@ -1966,6 +1995,7 @@
       "version": "4.10.1",
       "resolved": "https://registry.npmjs.org/asn1.js/-/asn1.js-4.10.1.tgz",
       "integrity": "sha512-p32cOF5q0Zqs9uBiONKYLm6BClCoBCM5O9JfeUSlnQLBTxYdTK+pW+nXflm8UkKd2UYlEbYz5qEi0JuZR9ckSw==",
+      "optional": true,
       "requires": {
         "bn.js": "^4.0.0",
         "inherits": "^2.0.1",
@@ -2296,6 +2326,14 @@
             "resolve": "^1.3.2",
             "semver": "^5.4.1",
             "source-map": "^0.5.0"
+          },
+          "dependencies": {
+            "semver": {
+              "version": "5.7.1",
+              "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz",
+              "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==",
+              "dev": true
+            }
           }
         },
         "@babel/runtime": {
@@ -2435,7 +2473,8 @@
     "bn.js": {
       "version": "4.11.8",
       "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.8.tgz",
-      "integrity": "sha512-ItfYfPLkWHUjckQCk8xC+LwxgK8NYcXywGigJgSwOP8Y2iyWT4f2vsZnoOXTTbo+o5yXmIUJ4gn5538SO5S3gA=="
+      "integrity": "sha512-ItfYfPLkWHUjckQCk8xC+LwxgK8NYcXywGigJgSwOP8Y2iyWT4f2vsZnoOXTTbo+o5yXmIUJ4gn5538SO5S3gA==",
+      "optional": true
     },
     "body-parser": {
       "version": "1.19.0",
@@ -2540,7 +2579,8 @@
     "brorand": {
       "version": "1.1.0",
       "resolved": "https://registry.npmjs.org/brorand/-/brorand-1.1.0.tgz",
-      "integrity": "sha1-EsJe/kCkXjwyPrhnWgoM5XsiNx8="
+      "integrity": "sha1-EsJe/kCkXjwyPrhnWgoM5XsiNx8=",
+      "optional": true
     },
     "browser-process-hrtime": {
       "version": "0.1.3",
@@ -2569,6 +2609,7 @@
       "version": "1.2.0",
       "resolved": "https://registry.npmjs.org/browserify-aes/-/browserify-aes-1.2.0.tgz",
       "integrity": "sha512-+7CHXqGuspUn/Sl5aO7Ea0xWGAtETPXNSAjHo48JfLdPWcMng33Xe4znFvQweqc/uzk5zSOI3H52CYnjCfb5hA==",
+      "optional": true,
       "requires": {
         "buffer-xor": "^1.0.3",
         "cipher-base": "^1.0.0",
@@ -2605,6 +2646,7 @@
       "version": "4.0.1",
       "resolved": "https://registry.npmjs.org/browserify-rsa/-/browserify-rsa-4.0.1.tgz",
       "integrity": "sha1-IeCr+vbyApzy+vsTNWenAdQTVSQ=",
+      "optional": true,
       "requires": {
         "bn.js": "^4.1.0",
         "randombytes": "^2.0.1"
@@ -2701,7 +2743,8 @@
     "buffer-xor": {
       "version": "1.0.3",
       "resolved": "https://registry.npmjs.org/buffer-xor/-/buffer-xor-1.0.3.tgz",
-      "integrity": "sha1-JuYe0UIvtw3ULm42cp7VHYVf6Nk="
+      "integrity": "sha1-JuYe0UIvtw3ULm42cp7VHYVf6Nk=",
+      "optional": true
     },
     "builtin-modules": {
       "version": "1.1.1",
@@ -2888,6 +2931,7 @@
       "version": "1.0.4",
       "resolved": "https://registry.npmjs.org/cipher-base/-/cipher-base-1.0.4.tgz",
       "integrity": "sha512-Kkht5ye6ZGmwv40uUDZztayT2ThLQGfnj/T71N/XzeZeo3nf8foyW7zGTsPYkEya3m5f3cAypH+qe7YOrM1U2Q==",
+      "optional": true,
       "requires": {
         "inherits": "^2.0.1",
         "safe-buffer": "^5.0.1"
@@ -3265,6 +3309,7 @@
       "version": "1.2.0",
       "resolved": "https://registry.npmjs.org/create-hash/-/create-hash-1.2.0.tgz",
       "integrity": "sha512-z00bCGNHDG8mHAkP7CtT1qVu+bFQUPjYq/4Iv3C3kWjTFV10zIjfSoeqXo9Asws8gwSHDGj/hl2u4OGIjapeCg==",
+      "optional": true,
       "requires": {
         "cipher-base": "^1.0.1",
         "inherits": "^2.0.1",
@@ -3277,6 +3322,7 @@
       "version": "1.1.7",
       "resolved": "https://registry.npmjs.org/create-hmac/-/create-hmac-1.1.7.tgz",
       "integrity": "sha512-MJG9liiZ+ogc4TzUwuvbER1JRdgvUFSB5+VR/g5h82fGaIRWMWddtKBHi7/sVhfjQZ6SehlyhvQYrcYkaUIpLg==",
+      "optional": true,
       "requires": {
         "cipher-base": "^1.0.3",
         "create-hash": "^1.1.0",
@@ -3739,6 +3785,7 @@
       "version": "6.4.1",
       "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.4.1.tgz",
       "integrity": "sha512-BsXLz5sqX8OHcsh7CqBMztyXARmGQ3LWPtGjJi6DiJHq5C/qvi9P3OqgswKSDftbu8+IoI/QDTAm2fFnQ9SZSQ==",
+      "optional": true,
       "requires": {
         "bn.js": "^4.4.0",
         "brorand": "^1.0.1",
@@ -3800,6 +3847,7 @@
       "version": "0.1.7",
       "resolved": "https://registry.npmjs.org/errno/-/errno-0.1.7.tgz",
       "integrity": "sha512-MfrRBDWzIWifgq6tJj60gkAwtLNb6sQPlcFrSOflcP1aFmmruKQ2wRnze/8V6kgyz7H3FF8Npzv78mZ7XLLflg==",
+      "optional": true,
       "requires": {
         "prr": "~1.0.1"
       }
@@ -4062,6 +4110,12 @@
           "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==",
           "dev": true
         },
+        "semver": {
+          "version": "5.7.1",
+          "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz",
+          "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==",
+          "dev": true
+        },
         "strip-ansi": {
           "version": "4.0.0",
           "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz",
@@ -4179,6 +4233,7 @@
       "version": "0.3.5",
       "resolved": "https://registry.npmjs.org/event-emitter/-/event-emitter-0.3.5.tgz",
       "integrity": "sha1-34xp7vFkeSPHFXuc6DhAYQsCzDk=",
+      "optional": true,
       "requires": {
         "d": "1",
         "es5-ext": "~0.10.14"
@@ -4193,6 +4248,7 @@
       "version": "1.0.3",
       "resolved": "https://registry.npmjs.org/evp_bytestokey/-/evp_bytestokey-1.0.3.tgz",
       "integrity": "sha512-/f2Go4TognH/KvCISP7OUsHn85hT9nUkxxA9BEWxFn+Oj9o8ZNLm/40hdlgSLyuOimsrTKLUMEorQexp/aPQeA==",
+      "optional": true,
       "requires": {
         "md5.js": "^1.3.4",
         "safe-buffer": "^5.1.1"
@@ -4722,7 +4778,8 @@
         },
         "ansi-regex": {
           "version": "2.1.1",
-          "bundled": true
+          "bundled": true,
+          "optional": true
         },
         "aproba": {
           "version": "1.2.0",
@@ -5087,7 +5144,8 @@
         },
         "safe-buffer": {
           "version": "5.1.2",
-          "bundled": true
+          "bundled": true,
+          "optional": true
         },
         "safer-buffer": {
           "version": "2.1.2",
@@ -5135,6 +5193,7 @@
         "strip-ansi": {
           "version": "3.0.1",
           "bundled": true,
+          "optional": true,
           "requires": {
             "ansi-regex": "^2.0.0"
           }
@@ -5173,11 +5232,13 @@
         },
         "wrappy": {
           "version": "1.0.2",
-          "bundled": true
+          "bundled": true,
+          "optional": true
         },
         "yallist": {
           "version": "3.0.3",
-          "bundled": true
+          "bundled": true,
+          "optional": true
         }
       }
     },
@@ -5485,6 +5546,7 @@
       "version": "3.0.4",
       "resolved": "https://registry.npmjs.org/hash-base/-/hash-base-3.0.4.tgz",
       "integrity": "sha1-X8hoaEfs1zSZQDMZprCj8/auSRg=",
+      "optional": true,
       "requires": {
         "inherits": "^2.0.1",
         "safe-buffer": "^5.0.1"
@@ -5494,6 +5556,7 @@
       "version": "1.1.7",
       "resolved": "https://registry.npmjs.org/hash.js/-/hash.js-1.1.7.tgz",
       "integrity": "sha512-taOaskGt4z4SOANNseOviYDvjEJinIkRgmp7LbKP2YTTmVxWBl87s/uzK9r+44BclBSp2X7K1hqeNfz9JbBeXA==",
+      "optional": true,
       "requires": {
         "inherits": "^2.0.3",
         "minimalistic-assert": "^1.0.1"
@@ -5503,6 +5566,7 @@
       "version": "1.0.1",
       "resolved": "https://registry.npmjs.org/hmac-drbg/-/hmac-drbg-1.0.1.tgz",
       "integrity": "sha1-0nRXAQJabHdabFRXk+1QL8DGSaE=",
+      "optional": true,
       "requires": {
         "hash.js": "^1.0.3",
         "minimalistic-assert": "^1.0.0",
@@ -5821,7 +5885,8 @@
     "is-extglob": {
       "version": "2.1.1",
       "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz",
-      "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI="
+      "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=",
+      "optional": true
     },
     "is-fullwidth-code-point": {
       "version": "1.0.0",
@@ -6129,6 +6194,14 @@
             "semver": "^5.5.0",
             "shebang-command": "^1.2.0",
             "which": "^1.2.9"
+          },
+          "dependencies": {
+            "semver": {
+              "version": "5.7.1",
+              "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz",
+              "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==",
+              "dev": true
+            }
           }
         },
         "execa": {
@@ -6212,6 +6285,14 @@
             "semver": "^5.5.0",
             "shebang-command": "^1.2.0",
             "which": "^1.2.9"
+          },
+          "dependencies": {
+            "semver": {
+              "version": "5.7.1",
+              "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz",
+              "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==",
+              "dev": true
+            }
           }
         },
         "execa": {
@@ -6693,6 +6774,14 @@
             "semver": "^5.5.0",
             "shebang-command": "^1.2.0",
             "which": "^1.2.9"
+          },
+          "dependencies": {
+            "semver": {
+              "version": "5.7.1",
+              "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz",
+              "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==",
+              "dev": true
+            }
           }
         },
         "execa": {
@@ -6870,6 +6959,14 @@
         "natural-compare": "^1.4.0",
         "pretty-format": "^24.8.0",
         "semver": "^5.5.0"
+      },
+      "dependencies": {
+        "semver": {
+          "version": "5.7.1",
+          "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz",
+          "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==",
+          "dev": true
+        }
       }
     },
     "jest-util": {
@@ -7461,7 +7558,8 @@
     "longest": {
       "version": "1.0.1",
       "resolved": "https://registry.npmjs.org/longest/-/longest-1.0.1.tgz",
-      "integrity": "sha1-MKCy2jj3N3DoKUoNIuZiXtd9AJc="
+      "integrity": "sha1-MKCy2jj3N3DoKUoNIuZiXtd9AJc=",
+      "optional": true
     },
     "loose-envify": {
       "version": "1.4.0",
@@ -7508,6 +7606,12 @@
           "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz",
           "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==",
           "dev": true
+        },
+        "semver": {
+          "version": "5.7.1",
+          "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz",
+          "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==",
+          "dev": true
         }
       }
     },
@@ -7562,6 +7666,7 @@
       "version": "1.3.5",
       "resolved": "https://registry.npmjs.org/md5.js/-/md5.js-1.3.5.tgz",
       "integrity": "sha512-xitP+WxNPcTTOgnTJcrhM0xvdPepipPSf3I8EIpGKeFLjt3PlJLIDG3u8EX53ZIubkb+5U2+3rELYpEhHhzdkg==",
+      "optional": true,
       "requires": {
         "hash-base": "^3.0.0",
         "inherits": "^2.0.1",
@@ -7587,6 +7692,7 @@
       "version": "0.4.1",
       "resolved": "https://registry.npmjs.org/memory-fs/-/memory-fs-0.4.1.tgz",
       "integrity": "sha1-OpoguEYlI+RHz7x+i7gO1me/xVI=",
+      "optional": true,
       "requires": {
         "errno": "^0.1.3",
         "readable-stream": "^2.0.1"
@@ -7677,12 +7783,14 @@
     "minimalistic-assert": {
       "version": "1.0.1",
       "resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz",
-      "integrity": "sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A=="
+      "integrity": "sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==",
+      "optional": true
     },
     "minimalistic-crypto-utils": {
       "version": "1.0.1",
       "resolved": "https://registry.npmjs.org/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz",
-      "integrity": "sha1-9sAMHAsIIkblxNmd+4x8CDsrWCo="
+      "integrity": "sha1-9sAMHAsIIkblxNmd+4x8CDsrWCo=",
+      "optional": true
     },
     "minimatch": {
       "version": "3.0.4",
@@ -7920,6 +8028,14 @@
         "semver": "^5.5.0",
         "shellwords": "^0.1.1",
         "which": "^1.3.0"
+      },
+      "dependencies": {
+        "semver": {
+          "version": "5.7.1",
+          "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz",
+          "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==",
+          "dev": true
+        }
       }
     },
     "node-releases": {
@@ -7929,6 +8045,14 @@
       "dev": true,
       "requires": {
         "semver": "^5.3.0"
+      },
+      "dependencies": {
+        "semver": {
+          "version": "5.7.1",
+          "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz",
+          "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==",
+          "dev": true
+        }
       }
     },
     "nomnom": {
@@ -7956,6 +8080,13 @@
         "resolve": "^1.10.0",
         "semver": "2 || 3 || 4 || 5",
         "validate-npm-package-license": "^3.0.1"
+      },
+      "dependencies": {
+        "semver": {
+          "version": "5.7.1",
+          "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz",
+          "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ=="
+        }
       }
     },
     "normalize-path": {
@@ -8269,6 +8400,14 @@
         "registry-auth-token": "^3.0.1",
         "registry-url": "^3.0.3",
         "semver": "^5.1.0"
+      },
+      "dependencies": {
+        "semver": {
+          "version": "5.7.1",
+          "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz",
+          "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==",
+          "dev": true
+        }
       }
     },
     "pako": {
@@ -8289,6 +8428,7 @@
       "version": "5.1.4",
       "resolved": "https://registry.npmjs.org/parse-asn1/-/parse-asn1-5.1.4.tgz",
       "integrity": "sha512-Qs5duJcuvNExRfFZ99HDD3z4mAi3r9Wl/FOjEOijlxwCZs7E7mW2vjTpgQ4J8LpTF8x5v+1Vn5UQFejmWT11aw==",
+      "optional": true,
       "requires": {
         "asn1.js": "^4.0.0",
         "browserify-aes": "^1.0.0",
@@ -8397,6 +8537,7 @@
       "version": "3.0.17",
       "resolved": "https://registry.npmjs.org/pbkdf2/-/pbkdf2-3.0.17.tgz",
       "integrity": "sha512-U/il5MsrZp7mGg3mSQfn742na2T+1/vHDCG5/iTI3X9MKUuYUZVLQhyRsg06mCgDBTd57TxzgZt7P+fYfjRLtA==",
+      "optional": true,
       "requires": {
         "create-hash": "^1.1.2",
         "create-hmac": "^1.1.4",
@@ -8599,7 +8740,8 @@
     "prr": {
       "version": "1.0.1",
       "resolved": "https://registry.npmjs.org/prr/-/prr-1.0.1.tgz",
-      "integrity": "sha1-0/wRS6BplaRexok/SEzrHXj19HY="
+      "integrity": "sha1-0/wRS6BplaRexok/SEzrHXj19HY=",
+      "optional": true
     },
     "pseudomap": {
       "version": "1.0.2",
@@ -8666,6 +8808,7 @@
       "version": "2.1.0",
       "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz",
       "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==",
+      "optional": true,
       "requires": {
         "safe-buffer": "^5.1.0"
       }
@@ -9078,6 +9221,7 @@
       "version": "2.0.2",
       "resolved": "https://registry.npmjs.org/ripemd160/-/ripemd160-2.0.2.tgz",
       "integrity": "sha512-ii4iagi25WusVoiC4B4lq7pbXfAp3D9v5CwfkY33vffw2+pkDjY1D8GaN7spsxvCSx8dkPqOZCEZyfxcmJG2IA==",
+      "optional": true,
       "requires": {
         "hash-base": "^3.0.0",
         "inherits": "^2.0.1"
@@ -9159,6 +9303,14 @@
             "semver": "^5.5.0",
             "shebang-command": "^1.2.0",
             "which": "^1.2.9"
+          },
+          "dependencies": {
+            "semver": {
+              "version": "5.7.1",
+              "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz",
+              "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==",
+              "dev": true
+            }
           }
         },
         "execa": {
@@ -9213,9 +9365,9 @@
       }
     },
     "semver": {
-      "version": "5.7.0",
-      "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.0.tgz",
-      "integrity": "sha512-Ya52jSX2u7QKghxeoFGpLwCtGlt7j0oY9DYb5apt9nPlJ42ID+ulTXESnt/qAQcoSERyZ5sl3LDIOw0nAn/5DA=="
+      "version": "6.3.0",
+      "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
+      "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw=="
     },
     "semver-diff": {
       "version": "2.1.0",
@@ -9224,6 +9376,14 @@
       "dev": true,
       "requires": {
         "semver": "^5.0.3"
+      },
+      "dependencies": {
+        "semver": {
+          "version": "5.7.1",
+          "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz",
+          "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==",
+          "dev": true
+        }
       }
     },
     "semver-regex": {
@@ -9395,6 +9555,12 @@
             "graceful-fs": "^4.1.6"
           }
         },
+        "semver": {
+          "version": "5.7.1",
+          "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz",
+          "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==",
+          "dev": true
+        },
         "uuid": {
           "version": "2.0.3",
           "resolved": "https://registry.npmjs.org/uuid/-/uuid-2.0.3.tgz",
@@ -9417,6 +9583,14 @@
         "lodash": "^4.17.4",
         "semver": "^5.4.1",
         "ts-node": "^3.2.0"
+      },
+      "dependencies": {
+        "semver": {
+          "version": "5.7.1",
+          "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz",
+          "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==",
+          "optional": true
+        }
       }
     },
     "set-blocking": {
@@ -9467,6 +9641,7 @@
       "version": "2.4.11",
       "resolved": "https://registry.npmjs.org/sha.js/-/sha.js-2.4.11.tgz",
       "integrity": "sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ==",
+      "optional": true,
       "requires": {
         "inherits": "^2.0.1",
         "safe-buffer": "^5.0.1"
@@ -9662,7 +9837,8 @@
     "source-list-map": {
       "version": "2.0.1",
       "resolved": "https://registry.npmjs.org/source-list-map/-/source-list-map-2.0.1.tgz",
-      "integrity": "sha512-qnQ7gVMxGNxsiL4lEuJwe/To8UnK7fAnmbGEEH8RpLouuKbeEm0lhbQVFIrNSuB+G7tVrAlVsZgETT5nljf+Iw=="
+      "integrity": "sha512-qnQ7gVMxGNxsiL4lEuJwe/To8UnK7fAnmbGEEH8RpLouuKbeEm0lhbQVFIrNSuB+G7tVrAlVsZgETT5nljf+Iw==",
+      "optional": true
     },
     "source-map": {
       "version": "0.7.3",
@@ -10219,7 +10395,8 @@
     "tapable": {
       "version": "0.2.9",
       "resolved": "https://registry.npmjs.org/tapable/-/tapable-0.2.9.tgz",
-      "integrity": "sha512-2wsvQ+4GwBvLPLWsNfLCDYGsW6xb7aeC6utq2Qh0PFwgEy7K7dsma9Jsmb2zSQj7GvYAyUGSntLtsv++GmgL1A=="
+      "integrity": "sha512-2wsvQ+4GwBvLPLWsNfLCDYGsW6xb7aeC6utq2Qh0PFwgEy7K7dsma9Jsmb2zSQj7GvYAyUGSntLtsv++GmgL1A==",
+      "optional": true
     },
     "tar-stream": {
       "version": "1.6.2",
@@ -11069,6 +11246,7 @@
       "version": "1.3.0",
       "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-1.3.0.tgz",
       "integrity": "sha512-OiVgSrbGu7NEnEvQJJgdSFPl2qWKkWq5lHMhgiToIiN9w34EBnjYzSYs+VbL5KoYiLNtFFa7BZIKxRED3I32pA==",
+      "optional": true,
       "requires": {
         "source-list-map": "^2.0.0",
         "source-map": "~0.6.1"
@@ -11077,7 +11255,8 @@
         "source-map": {
           "version": "0.6.1",
           "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
-          "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g=="
+          "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
+          "optional": true
         }
       }
     },
diff --git a/package.json b/package.json
index a9999cd..872db5a 100644
--- a/package.json
+++ b/package.json
@@ -55,6 +55,7 @@
     "open": "^6.3.0",
     "request": "^2.81.0",
     "rimraf": "^2.6.3",
+    "semver": "^6.3.0",
     "xml": "^1.0.1"
   },
   "devDependencies": {
diff --git a/src/armTemplates/resources/functionApp.ts b/src/armTemplates/resources/functionApp.ts
index 0263490..eab4a9e 100644
--- a/src/armTemplates/resources/functionApp.ts
+++ b/src/armTemplates/resources/functionApp.ts
@@ -2,6 +2,10 @@ import { ArmResourceTemplate, ArmResourceTemplateGenerator } from "../../models/
 import { FunctionAppConfig, ServerlessAzureConfig } from "../../models/serverless";
 import { AzureNamingService } from "../../services/namingService";
 
+//Runtime versions found at " https://<sitename>.scm.azurewebsites.net/api/diagnostics/runtime".
+import runtimeVersionsJson from "../../services/runtimeVersions.json";
+import semver from "semver";
+
 export class FunctionAppResource implements ArmResourceTemplateGenerator {
   public static getResourceName(config: ServerlessAzureConfig) {
     const safeServiceName = config.service.replace(/\s/g, "-");
@@ -23,7 +27,7 @@ export class FunctionAppResource implements ArmResourceTemplateGenerator {
           "type": "String"
         },
         "functionAppNodeVersion": {
-          "defaultValue": "10.14.1",
+          "defaultValue": "",
           "type": "String"
         },
         "functionAppWorkerRuntime": {
@@ -108,6 +112,7 @@ export class FunctionAppResource implements ArmResourceTemplateGenerator {
   public getParameters(config: ServerlessAzureConfig): any {
     const resourceConfig: FunctionAppConfig = {
       ...config.provider.functionApp,
+      nodeVersion: this.getRuntimeVersion(config.provider.runtime)
     };
 
     return {
@@ -117,4 +122,37 @@ export class FunctionAppResource implements ArmResourceTemplateGenerator {
       functionAppExtensionVersion: resourceConfig.extensionVersion,
     };
   }
+
+  private getRuntimeVersion(runtime: string): string{ 
+    if(!runtime) {
+      throw new Error("Runtime version not specified in serverless.yml");
+    }
+    const extractedVersion = runtime.split("nodejs")[1];
+    const runtimeVersionsList = runtimeVersionsJson["nodejs"];
+
+    //Searches for a specific version. For example nodejs10.6.0.
+    if(!extractedVersion.endsWith(".x")) {
+      let retrivedVersion: string;
+      for(const version of runtimeVersionsList){
+        retrivedVersion = version["version"]; 
+        if(extractedVersion === retrivedVersion && semver.valid(retrivedVersion)){
+          return retrivedVersion; 
+        }
+      }
+    }
+    else {
+      // User specified something like nodejs10.14.x
+      const extractedVersionNumber = extractedVersion.replace(/[^0-9\.]/g,"");
+
+      const selectedVersions = runtimeVersionsList.filter(({ version }) => {
+        return version.startsWith(extractedVersionNumber) && semver.valid(version)
+      }).map((item) => item.version);
+
+      if (!selectedVersions.length) {
+        throw new Error(`Could not find runtime version matching ${runtime}`)
+      }
+      return selectedVersions.sort(semver.rcompare)[0]
+    }
+    throw new Error(`Could not find runtime version matching ${runtime}`)
+  }  
 }
diff --git a/src/models/armTemplates.ts b/src/models/armTemplates.ts
index a35d050..97ef914 100644
--- a/src/models/armTemplates.ts
+++ b/src/models/armTemplates.ts
@@ -8,6 +8,11 @@ export interface ArmResourceTemplateGenerator {
   getParameters(config: ServerlessAzureConfig): any;
 }
 
+export enum ArmTemplateProvisioningState {
+  FAILED = "Failed",
+  SUCCEEDED = "Succeeded",
+}
+
 /**
  * The well-known serverless Azure template types
  */
diff --git a/src/models/serverless.ts b/src/models/serverless.ts
index c1e43e7..db09448 100644
--- a/src/models/serverless.ts
+++ b/src/models/serverless.ts
@@ -50,6 +50,7 @@ export interface ServerlessAzureProvider {
   hostingEnvironment?: ResourceConfig;
   virtualNetwork?: ResourceConfig;
   armTemplate?: ArmTemplateConfig;
+  runtime: string; 
 }
 
 export interface ServerlessAzureConfig {
diff --git a/src/services/armService.ts b/src/services/armService.ts
index 3abb531..d2dfd75 100644
--- a/src/services/armService.ts
+++ b/src/services/armService.ts
@@ -39,7 +39,6 @@ export class ArmService extends BaseService {
     }
 
     const azureConfig: ServerlessAzureConfig = this.serverless.service as any;
-
     const mergedTemplate = template.getTemplate();
     let parameters = template.getParameters(azureConfig);
 
diff --git a/src/services/resourceService.ts b/src/services/resourceService.ts
index 51885e6..dac7acf 100644
--- a/src/services/resourceService.ts
+++ b/src/services/resourceService.ts
@@ -3,7 +3,7 @@ import { ResourceManagementClient } from "@azure/arm-resources";
 import { BaseService } from "./baseService";
 import { Utils } from "../shared/utils";
 import { AzureNamingService } from "./namingService";
-import { ArmDeployment } from "../models/armTemplates";
+import { ArmDeployment, ArmTemplateProvisioningState } from "../models/armTemplates";
 import { DeploymentExtended } from "@azure/arm-resources/esm/models";
 
 export class ResourceService extends BaseService {
@@ -41,7 +41,7 @@ export class ResourceService extends BaseService {
    */
   public async getLastDeploymentTemplate(): Promise<ArmDeployment> {
     const deployment = await this.getLastDeployment();
-    if (!deployment) {
+    if (!deployment || deployment.properties.provisioningState !== ArmTemplateProvisioningState.SUCCEEDED) {
       return;
     }
     const { parameters } = deployment.properties;
diff --git a/src/services/runtimeVersions.json b/src/services/runtimeVersions.json
new file mode 100644
index 0000000..7e81b70
--- /dev/null
+++ b/src/services/runtimeVersions.json
@@ -0,0 +1,63 @@
+{
+    "nodejs": [{
+        "version": "0.10.40",
+        "npm": "1.4.28"
+    }, {
+        "version": "0.10.5",
+        "npm": "1.2.18"
+    }, {
+        "version": "0.12.6",
+        "npm": "2.11.2"
+    }, {
+        "version": "0.6.20",
+        "npm": "1.1.37"
+    }, {
+        "version": "0.8.28",
+        "npm": "1.2.30"
+    }, {
+        "version": "10.14.1",
+        "npm": "6.4.1"
+    }, {
+        "version": "10.15.2",
+        "npm": "6.4.1"
+    }, {
+        "version": "10.6.0",
+        "npm": "6.1.0"
+    }, {
+        "version": "4.8.4",
+        "npm": "2.15.11"
+    }, {
+        "version": "6.12.3",
+        "npm": "3.10.10"
+    }, {
+        "version": "6.5.0",
+        "npm": "3.10.3"
+    }, {
+        "version": "6.9.1",
+        "npm": "3.10.8"
+    }, {
+        "version": "6.9.5",
+        "npm": "3.10.10"
+    }, {
+        "version": "7.10.1",
+        "npm": "4.2.0"
+    }, {
+        "version": "8.1.4",
+        "npm": "5.0.3"
+    }, {
+        "version": "8.10.0",
+        "npm": "5.6.0"
+    }, {
+        "version": "8.11.1",
+        "npm": "5.6.0"
+    }, {
+        "version": "8.4.0",
+        "npm": "5.3.0"
+    }, {
+        "version": "8.5.0",
+        "npm": "5.3.0"
+    }, {
+        "version": "8.9.4",
+        "npm": "5.6.0"
+    }]
+}
\ No newline at end of file


Test patch:
diff --git a/src/services/armService.test.ts b/src/services/armService.test.ts
index 71dedfe..f09a2bd 100644
--- a/src/services/armService.test.ts
+++ b/src/services/armService.test.ts
@@ -1,12 +1,12 @@
 import Serverless from "serverless";
 import { MockFactory } from "../test/mockFactory";
 import { ArmService } from "./armService";
-import { ArmResourceTemplate, ArmTemplateType, ArmDeployment } from "../models/armTemplates";
+import { ArmResourceTemplate, ArmTemplateType, ArmDeployment, ArmTemplateProvisioningState } from "../models/armTemplates";
 import { ArmTemplateConfig, ServerlessAzureOptions } from "../models/serverless";
 import mockFs from "mock-fs";
 import jsonpath from "jsonpath";
 import { Deployments } from "@azure/arm-resources";
-import { Deployment } from "@azure/arm-resources/esm/models";
+import { Deployment, DeploymentExtended } from "@azure/arm-resources/esm/models";
 import { ResourceService } from "./resourceService";
 
 describe("Arm Service", () => {
@@ -30,13 +30,12 @@ describe("Arm Service", () => {
     };
 
     service = createService();
-    ResourceService.prototype.getDeployments = jest.fn(() => MockFactory.createTestDeployments()) as any;
+    ResourceService.prototype.getDeployments = jest.fn(() => Promise.resolve(MockFactory.createTestDeployments())) as any;
     ResourceService.prototype.getDeploymentTemplate = jest.fn(() => {
       return {
         template: MockFactory.createTestArmTemplate()
       }
     }) as any;
-
   })
 
   afterEach(() => {
@@ -71,6 +70,7 @@ describe("Arm Service", () => {
     });
 
     it("Creates a custom ARM template from well-known type", async () => {
+      sls.service.provider.runtime = "nodejs6.9.x";      
       const deployment = await service.createDeploymentFromType("premium");
 
       expect(deployment).not.toBeNull();
@@ -80,6 +80,7 @@ describe("Arm Service", () => {
 
     it("Creates a custom ARM template (with APIM support) from well-known type", async () => {
       sls.service.provider["apim"] = MockFactory.createTestApimConfig();
+      sls.service.provider.runtime = "nodejs10.6.x";
       const deployment = await service.createDeploymentFromType(ArmTemplateType.Premium);
 
       expect(deployment).not.toBeNull();
@@ -93,7 +94,42 @@ describe("Arm Service", () => {
       await expect(service.createDeploymentFromType("not-found")).rejects.not.toBeNull();
     });
 
+    it("throws error when invalid nodejs version in defined", async () => {
+      sls.service.provider.runtime = "nodejs10.6.1"; 
+      await expect(service.createDeploymentFromType("premium")).rejects.toThrowError("Could not find runtime version matching nodejs10.6.1");
+    });
+
+    it("throws error when incomplete nodejs version in defined", async () => {
+      sls.service.provider.runtime = "nodejs8"; 
+      await expect(service.createDeploymentFromType("premium")).rejects.toThrowError("Could not find runtime version matching nodejs8");
+    });
+
+    it("throws error when unsupported nodejs version in defined", async () => {
+      sls.service.provider.runtime = "nodejs5.x"; 
+      await expect(service.createDeploymentFromType("premium")).rejects.toThrowError("Could not find runtime version matching nodejs5.x");
+    });
+
+    it("Does not throw an error when valid nodejs version is defined", async () => {
+      sls.service.provider.runtime = "nodejs10.x"; 
+      await expect(service.createDeploymentFromType("premium")).resolves.not.toThrow();
+    });
+
+    it("Does not throw an error when nodejs version with major and minor is defined", async () => {
+      sls.service.provider.runtime = "nodejs6.9.x"; 
+      await expect(service.createDeploymentFromType("premium")).resolves.not.toThrow();
+    });
+
+    it("Does not throw an error when specific nodejs version is defined", async () => {
+      sls.service.provider.runtime = "nodejs10.6.0"; 
+      await expect(service.createDeploymentFromType("premium")).resolves.not.toThrow();
+    });
+
+    it("throws an error when no nodejs version in defined", async () => {
+      await expect(service.createDeploymentFromType("premium")).rejects.toThrowError("Runtime version not specified in serverless.yml");
+    });
+
     it("Premium template includes correct resources", async () => {
+      sls.service.provider.runtime = "nodejs10.14.1";
       const deployment = await service.createDeploymentFromType(ArmTemplateType.Premium);
 
       expect(deployment.template.parameters.appServicePlanSkuTier.defaultValue).toEqual("ElasticPremium");
@@ -116,6 +152,7 @@ describe("Arm Service", () => {
     });
 
     it("ASE template includes correct resources", async () => {
+      sls.service.provider.runtime = "nodejs10.14.1";
       const deployment = await service.createDeploymentFromType(ArmTemplateType.AppServiceEnvironment);
 
       expect(deployment.template.parameters.appServicePlanSkuTier.defaultValue).toEqual("Isolated");
@@ -141,6 +178,7 @@ describe("Arm Service", () => {
     });
 
     it("Consumption template includes correct resources", async () => {
+      sls.service.provider.runtime = "nodejs10.x";      
       const deployment = await service.createDeploymentFromType(ArmTemplateType.Consumption);
 
       expect(deployment.template.resources.find((resource) => resource.type === "Microsoft.Web/hostingEnvironments")).toBeUndefined();
@@ -168,6 +206,26 @@ describe("Arm Service", () => {
       expect(Deployments.prototype.createOrUpdate).not.toBeCalled()
     });
 
+    it("Calls deploy if previous template is the same but failed", async () => {
+      const deployments = MockFactory.createTestDeployments();
+      const failedDeployment: DeploymentExtended = {
+        ...deployments[0],
+        properties: {
+          ...deployments[0].properties,
+          provisioningState: ArmTemplateProvisioningState.FAILED
+        }
+      }
+      deployments[0] = failedDeployment;
+      ResourceService.prototype.getDeployments = jest.fn(() => Promise.resolve(deployments))
+
+      const deployment: ArmDeployment = {
+        parameters: MockFactory.createTestParameters(false),
+        template: MockFactory.createTestArmTemplate()
+      };
+      await service.deployTemplate(deployment);
+      expect(Deployments.prototype.createOrUpdate).toBeCalled();
+    });
+
     it("Calls deploy if parameters have changed from deployed template", async () => {
       const deployment: ArmDeployment = {
         parameters: MockFactory.createTestParameters(false),
@@ -212,6 +270,7 @@ describe("Arm Service", () => {
       };
 
       sls.service.provider["environment"] = environmentConfig
+      sls.service.provider.runtime = "nodejs10.x";
 
       const deployment = await service.createDeploymentFromType(ArmTemplateType.Consumption);
       await service.deployTemplate(deployment);
@@ -223,6 +282,7 @@ describe("Arm Service", () => {
     });
 
     it("Deploys ARM template via resources REST API", async () => {
+      sls.service.provider.runtime = "nodejs10.x";
       const deployment = await service.createDeploymentFromType(ArmTemplateType.Consumption);
       const deploymentParameters = {};
       Object.keys(deployment.parameters).forEach((key) => {
diff --git a/src/test/mockFactory.ts b/src/test/mockFactory.ts
index 9789940..64242c9 100644
--- a/src/test/mockFactory.ts
+++ b/src/test/mockFactory.ts
@@ -12,7 +12,7 @@ import Service from "serverless/classes/Service";
 import Utils from "serverless/classes/Utils";
 import PluginManager from "serverless/lib/classes/PluginManager";
 import { ApiCorsPolicy, ApiManagementConfig } from "../models/apiManagement";
-import { ArmDeployment, ArmResourceTemplate } from "../models/armTemplates";
+import { ArmDeployment, ArmResourceTemplate, ArmTemplateProvisioningState } from "../models/armTemplates";
 import { ServicePrincipalEnvVariables } from "../models/azureProvider";
 import { Logger } from "../models/generic";
 import { ServerlessAzureConfig, ServerlessAzureProvider, ServerlessAzureFunctionConfig } from "../models/serverless";
@@ -193,6 +193,7 @@ export class MockFactory {
       properties: {
         timestamp: new Date(2019, 1, 1, 0, 0, second),
         parameters: MockFactory.createTestParameters(),
+        provisioningState: ArmTemplateProvisioningState.SUCCEEDED
       }
     }
   }