- Getting Started
Development flow integration
- No small error pages
- AMP HTML validator
- No vulnerable libraries
- Avoid HTTP redirects
- Avoid CSS limits
- Optimal compression
- Correct manifest extension
- Babel configuration hint set
- Correct `Content-Type` header
- Performance budget
- HTTP cache
- Correct viewport
- Disallowed HTTP headers
- External links disown opener
- TypeScript configuration hints set
- Modern DOCTYPE
- Has web app manifest
- Highest document mode
- Manifest has name
- Use HTTPS
- No protocol-relative URLs
- No byte-order mark
- No `P3P` headers
- No broken links
- Use charset `utf-8`
- SSL server test
- Optimize images
- Nu HTML test
- Unneeded HTTP headers
- Use Apple touch icon
- Use `Strict-Transport-Security` header
- Use `X-Content-Type-Options` header
- Use subresource integrity
- Valid `Set-Cookie` header
- Valid `theme-color`
- Valid manifest
- aXe accessibility check
- webpack configuration hints set
- Configuring webhint
- Development flow integration
- Server configurations
Azure Web Apps allows developers to have different environments or slots for the same website (learn more here). Slots are useful if you want to test things right before going into production in an environment similar to it (they could be virtually identical).
In the case of webhint.io we have 2 slots or environments and the process of changing the code from one place to another is done via a custom Travis CI script.
The TL;DR; version is:
- Staging: Every time there is a change into the documentation of the CLI’s repo, or the site’s one, the code is downloaded, built and deployed into staging automatically.
- Production: Once staging is updated, it gets tested and if no problems are found, the code gets promoted to production. Same as before, this is done automatically.
This guide documents how to deploy your website into an Azure Web App
slot, test it using
webhint, and put it into production. All of this
using Travis CI.
It assumes the user has a Travis CI and an Azure account, this last one
with an Azure Web App already created.
To create a slot in your website you have to:
Select “Deployment slots” in the blade of your Azure Web App:
Select “Add Slot” in the blade that appears:
Choose a name (e.g.: “staging”) and select a source to clone if applicable (e.g.: “production”). This will copy all the environment variables in the source such as
Select the new slot in the menu and then “Deployment options”
In the new menu, select “Local Git Repository”
At this moment you might have to create some "deployment credentials". You can do so via the “Deployment credentials” option:
This is an optional step, but recommended. You should create a service principal with only access to the bare minimum. That way you do not have to put your credentials anywhere (even if they are encrypted), and if something happens you can easily revoke access to it.
To achieve this, you first need to install the Azure CLI. Then log in into your account using:
A browser should open and give you access in the command line.
Note: If your account has access to multiple Azure subscriptions, make sure to choose the right one via
az account set --subscription "My Subscription".
Then create a service principal:
az ad sp create-for-rbac --name NAME --password PASSWORD --subscription "My Subscription"
You should get an output like:
You should write down this information, but the fields we will use later are:
By default, service principals are created with the
Contributorrole. Unless you want this account to have access to anything, you should remove it and scope it down. For this case, the
Website Contributorshould be enough and you should give this role only for the Azure WebApp you are using.
- Go to the Azure Portal, select your Azure WebApp and click on "Access control (IAM)".
- Click on "+ Add".
- Search and select the service principal you created before.
- Add the “Website Contributor” role and click Save.
First thing you have to do is add
webhint to your project:
npm install --save-dev webhint
Then you need a valid
.hintrc file. For a starter file, use the
following command and answer the questions:
npm create hintrc
You can use the generated file as a starter point for your needs, ignoring URLs you do not have control over, tweaking the configuration of some of the hints, etc.
Finally, add a task to your
package.json that will test the staging
The last remaining piece is Travis CI. As stated earlier, Travis CI is in
charge of deploying, running the tests, and changing the code from staging
to production. And all of this from the
.travis.yml of your project!
Travis has several steps and you can configure what scripts or actions
execute in each one. E.g.:
etc. To know more about the different steps, visit
Travis CI’s Build Lifecycle.
One thing to consider is that not all the scripts can break the build on
Travis. If you want to stop the process if
webhint fails, you will have
to combine a few steps into one. There are more details further on, but you
can learn more in Travis CI’s Breaking the Build.
The staging slot should have a local Git repository. Every time there is
push event in this repository, Azure will trigger the installation process
(basically download the code and then execute
There are 2 ways to get the code into staging in Travis CI:
Travis CI has built-in support to deploy to Azure. To enable it you have to configure the following environment variables:
AZURE_WA_USERNAME: User name to use for the deployment
AZURE_WA_PASSWORD: Password to use for the deployment
AZURE_WA_SITE: Site to deploy to. E.g.:
AZURE_WA_SLOT: Slot to deploy to. E.g.:
With the values above, Travis CI will deploy the code to
It is recommended to encrypt these environment variables for security reasons.
How to encrypt environment variables:
apt-get ruby ruby-dev(Windows users can use WSL; macOS users do not need to do this).
Install the Travis CI gem:
gem install travis
Log into Travis CI:
Encrypt the variables:
travis encrypt -r "<username>/<repository>" \
This should output something in the form of:
Add it to your
.travis.ymlnear the top under:
- secure: "Bx6tfqQJYjlSofs3wEr2iqWx75HuR+Qtybomc97ueGxlkHjCXKF2A7one9ykwm+EVdJGVPLKM4bvS2ebqeNSPFSNyZbajXLV24lXgXsA3UVsXI3kBDkKG/bouyuQWvCeYAKF1XSbQM3513XbYSDWCdO72IkB5E961nvKCkLcsvJ+WGeE+3YtigK8ThHlzcM9Twt22y7ZQa4Y429uR6I1tAYzYkp4XHG/SO0tb9SAdGDg"
Now that you have added the credentials to deploy to Azure you can deploy to it:
One thing to keep in mind, is that
.gitignore will be respected at this
moment. If you have artifacts from a build step that need to be published
.gitignore ignores them, you will have to update it before this
An easy way to do this is to have a “production”
.gitignore and replace
one with the other in the
Another thing to consider is that Travis CI resets the working directory before deploying. If your deployment relies on a build step, you probably want to change that:
The next step is to test using
webhint. You should have
package.json. Use it in the
NOTE: As mentioned previously, non-zero exit codes for stages after
script do not change the status of the build.
There are a few limitations when running the
- The build will not fail even if they exit with a non-zero value.
- Modifying the
.gitignorefile during the build can be cumbersome and errors here can be difficult to catch.
To solve these issues, you should collapse the different stage scripts into the
script stage. In the case of webhint.io, it looks as follows:
The steps are:
npm test: Lint and build the site.
npm run travis-update: Copy all the files we need for the deployment (minus
node_modules) into a temporary folder and push them into the Azure WebApp Git repository. Example.
npm run test-staging: Test the staging environment with
webhint. This is the script created previously.
npm run swap: Change the code in
productionafter installing the Azure CLI. Example.
You will still have to add some encrypted environment variables to make everything work.
Congratulations, you can now deploy to your Azure WebApp from Travis!
If you have followed the instructions, you should have a
task in your
package.json. Now it is time to use it:
.travis.yml to run it after the deploy:
after_deploy: npm run test:staging
You also want to swap if everything goes right. To do this, the first
step is to install the Azure CLI in Travis CI. The
following snippet of
.travis.yml assumes the machine runs Linux:
# Install Azure CLI
Then you need to log into Azure using the Service Principal credentials
from before and do the swap. It’s probably easier to have a script file
that does everything and call it from the
after_script stage or any
other you might be using:
NOTE: You have to replace the values
SLOTENAME with yours. Also, you will have to create the encrypted
environment variables for them similarly to what was described before:
travis encrypt -r "<username>/<repository>" \
Please refer to the Azure CLI documentation for other authentication methods.
If the above is under
.travis/swap.sh, then your
have something similar to:
NOTE: Remember that all stages after
script will not change the
build status, nor will they interrupt the execution, so you might want to
move the actions to another stage depending on your needs.
The following is a functional
.travis.yml that does the following:
|Install Azure CLI|
|Build and test|
|Deploy into Azure without cleaning the workspace|
|Test staging with |
NOTE: This will not change the status of your build if
fails in staging. To achieve that you will have to combine all the
.travis.yml does that).
# For more information about the configurations used