This post shows how to create a publishing profile for provider-hosted apps and use them as part of the build process.
This is part 4 in a series on ALM for SharePoint 2013 apps.
In the previous posts, I showed how to set up a TFS Team Build 2012 server to implement continuous integration, automatically deploying apps to SharePoint and a provider-hosted app to an IIS server using Web Deploy. We also introduced the concept of creating a custom build activity to overwrite the ~remoteAppUrl token in the appmanifest.xml file. This post will show you how app publishing works and how we can leverage it INSTEAD OF a custom workflow activity.
To recap, the appmanifest.xml file for a provider-hosted app includes the URL to the web server that contains the logic for the app. It looks like this:
When you press F5 in Visual Studio 2012, it does some work behind the scenes to create an app package. The package it creates replaces the ~remoteAppUrl token before uploading to SharePoint. It doesn’t update your code in Visual Studio, it just does this in the generated app package. You can see this after you deploy your app using F5 by using the new REST API. Go to your developer site and append the following to the site’s URL in the browser.
Notice the highlighted line shows how you can get field values as text. We rewrite our query to use the same identifier and select the AppLaunchUrl value.
Now the results show us what the actual remoteAppUrl value is.
This is what our workflow activity was mimicking, the ability to replace the remoteAppUrl just for the app package. Your code in Visual Studio didn’t change, it still shows the value as ~remoteAppUrl. The build process behind the scenes replaces the token with the URL of your development web server for testing.
The Problem With Just Replacing the remoteAppUrl
What I didn’t share in the previous post on creating a custom workflow activity is that the remoteAppUrl token is used in a whole bunch of other places besides just the appmanifest. For instance, if I add the ability for my app to call some code when the app is being installed, it creates a remote event receiver. The remote event receiver includes the ~remoteAppUrl placeholder.
Similarly, custom actions also use the ~remoteAppUrl, and that’s not in the app manifest, it’s in a file called elements.xml for the custom action.
This makes sense, because I build the app once and all those tokens should be replaced. But wait… does that mean that I have to replace the ~remoteAppUrl in ALL those places using a custom workflow activity? Oh man, doesn’t that make a brittle build process, shouldn’t TFS or Visual Studio handle this for me?
Turns out, you don’t have to do it that way.
Publishing a Provider Hosted App
In the previous post on Continuous Integration with SharePoint Apps, I showed how to publish the IIS site and create a publishing profile for it. The problem is that publishing in this manner only creates the publishsettings file for the web and doesn’t include information on the app, such as the remote app URL, client ID, certificate path, certificate password, or issuer ID. That’s why we had to customize in TFS. The RIGHT WAY to do this is to simply publish the app itself. The publishing profile will ask you for all of this information.
In Visual Studio 2012, right click the APP project (not the web site) and choose Publish.
This will bring up a dialog asking you to create a publishing profile or use an existing one. Choose New.
You are prompted for a name.
Choose Next, and Visual Studio now asks you for the information about the app.
Click next, and the app is packaged and you can see the finished product in Windows Explorer.
For sanity, let’s rename the .app to .zip and then open it to inspect the appmanifest.
Double-click on the zip file and then open the appmanifest.xml, and sure enough, the values in the package are replaced.
This is exactly what we wanted to happen. Notice it replaced not only the remoteAppUrl, for the start page, but also for the remote event receiver. Now let’s look at the elements.xml file, and it has been correctly replaced as well.
The beautiful part is that we get all of this by publishing the app, which creates the publishing profile. Since our project has the publishing profile established, we can now use it as part of the build.
Check In Your Changes
When we created the new publishing profile, it was stored in our web project.
If we crack open the pubxml file, we would see the settings we just put into the wizard.
That means the publishing settings are now part of our web project, so we need to check in the changes so that TFS will know about them.
Create a New Process Template
Remember that we created a new process template that includes a custom workflow activity. Well, we don’t need it anymore, we will get Visual Studio to do that heavy lifting for us. Rather than edit the existing process template, I will just create a new one based on the continuous integration template that I downloaded from CodePlex. In Team Explorer, go to the Builds tab and choose Edit Build Definition.
Expand the build process template and choose New.
Create a new template based on a copy of the OfficeToolsAppTemplate.xml.
Give it a name, and choose OK.
Now go to the Process tab and expand the Advanced section. Remember where we told it the publish profile before? We put in the name of our new publish profile, the one that includes the app information.
Save the process template before queuing a new build.
Queue a Build
Now go to the build definition and queue a new build. Without having to include a custom workflow activity, the build runs successfully and was deployed based on our previous configuration from the second post in this series (for reference on configuring for continuous integration, see my post ALM for SharePoint Apps: Implementing Continuous Integration).
We check the output folder, and see the app package. Rename it to .zip and open it to inspect the appmanifest, and our changes were applied WITHOUT requiring a custom workflow activity.
Note: A word of transparency here, this doesn’t work when you have a remote event receiver handling the app installed event because the PowerShell script used for continuous deployment installs the app before deploying the web site. You will need to write additional logic to use continuous integration with an app that uses a remote event receiver to handle the app installed event.
Using publishing settings for your build process makes a very clean build process. This allows you to write the code once, establish different publishing settings for each of your dev, test, QA, and prod environments, and manage the correct build and packaging for each environment as a separate build. For instance, in a dev environment you might want continuous integration, while the process template for a prod environment would not automatically deploy the app from Visual Studio.