Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Always remove Angular dist folder contents with WebDeploy on Destination

We've got a single page application on Angular 5 with an ASP.NET backend, and when we compile it, the release contents for Angular are output to a folder "Project\dist".

This works great on local dev machines, but all of the dist files are randomized with different names such as:

  • polyfills.dc7175a7225af84b3c9b.bundle.js
  • styles.dc7175a7225af84b3c9b.bundle.js
  • inline.dc7175a7225af84b3c9b.bundle.js

When we use Web Publishing to deploy to staging or production, everything transfers great and our custom folder in the publish profiles is included and published.

However, on the destination server (staging or production) these old, randomly named files and old (no longer used) folders persist. This results in hundreds and hundreds of old files (from old web deploys) that have accumulated on the staging and production servers. I need a method to automatically delete these every time we push updates with webdeploy.

Ideally, the workflow is:

  • Select publish profile, click Publish
  • Enter my credentials
  • Application builds successfully
  • If app built successfully, we go delete "Project\dist" folder on the destination server. "Project" could be in c:\inetpub\www\project or d:\websites\Project, for example.
  • Updated files are copied
  • Web deploy executes and copies the custom files in dist folder (already working).

Here's a redacted version of our current publish profile:

<?xml version="1.0" encoding="utf-8"?>
<!--
This file is used by the publish/package process of your Web project. You can customize the behavior of this process
by editing this MSBuild file. In order to learn more about this please visit http://go.microsoft.com/fwlink/?LinkID=208121. 
-->
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  <PropertyGroup>
    <WebPublishMethod>MSDeploy</WebPublishMethod>
    <LastUsedBuildConfiguration>Release</LastUsedBuildConfiguration>
    <LastUsedPlatform>Any CPU</LastUsedPlatform>
    <SiteUrlToLaunchAfterPublish />
    <LaunchSiteAfterPublish>True</LaunchSiteAfterPublish>
    <ExcludeApp_Data>False</ExcludeApp_Data>
    <MSDeployServiceURL>staging.example.com</MSDeployServiceURL>
    <DeployIisAppPath>Project</DeployIisAppPath>
    <RemoteSitePhysicalPath />
    <SkipExtraFilesOnServer>True</SkipExtraFilesOnServer>
    <MSDeployPublishMethod>WMSVC</MSDeployPublishMethod>
    <EnableMSDeployBackup>False</EnableMSDeployBackup>
    <UserName>WebDeployUser</UserName>
    <PublishDatabaseSettings>
      <Objects xmlns="">
      </Objects>
    </PublishDatabaseSettings>
    <ADUsesOwinOrOpenIdConnect>False</ADUsesOwinOrOpenIdConnect>
  </PropertyGroup>
  <Target Name="CustomCollectFiles">
    <ItemGroup>
      <_CustomFiles Include="..\Project\dist\**\*" />

      <FilesForPackagingFromProject  Include="%(_CustomFiles.Identity)">
        <DestinationRelativePath>dist\%(RecursiveDir)%(Filename)%(Extension)</DestinationRelativePath>
      </FilesForPackagingFromProject>
    </ItemGroup>
  </Target>
  <PropertyGroup>
    <CopyAllFilesToSingleFolderForPackageDependsOn>
      CustomCollectFiles;
      $(CopyAllFilesToSingleFolderForPackageDependsOn);
    </CopyAllFilesToSingleFolderForPackageDependsOn>

    <CopyAllFilesToSingleFolderForMsdeployDependsOn>
      CustomCollectFiles;
      $(CopyAllFilesToSingleFolderForMsdeployDependsOn);
    </CopyAllFilesToSingleFolderForMsdeployDependsOn>
  </PropertyGroup>
</Project>

I've tried a few accepted answer solutions already and can't get this to work:

  • https://stackoverflow.com/a/45538847/559988 (I tried this in the csproj and in the publish profile pubxml file.)
  • https://stackoverflow.com/a/5080942/559988

Any ideas? I have essentially zero knowledge of web deploy aside from setting it up in IIS.

Best, Chris

EDIT I've also tried this: (Based on this: https://stackoverflow.com/a/15113445/559988)

  <Target Name="CleanFolder">

    <PropertyGroup>
      <TargetFolder>$(_MSDeployDirPath_FullPath)\dist</TargetFolder>
    </PropertyGroup>

    <ItemGroup>
      <FilesToClean Include="$(TargetFolder)\**\*"/>
      <Directories Include="$([System.IO.Directory]::GetDirectories('$(TargetFolder)', '*', System.IO.SearchOption.AllDirectories))"
                   Exclude="$(TargetFolder)"/>
    </ItemGroup>

    <Delete Files="@(FilesToClean)" ContinueOnError="true"/>
    <RemoveDir Directories="@(Directories)" />
  </Target>

Update This is specifically what we're doing: https://docs.microsoft.com/en-us/aspnet/web-forms/overview/deployment/visual-studio-web-deployment/deploying-extra-files

The first comment from there is the same problem we're experiencing: This comes very handy in deploying Angular distribution files along with ASP.Net backend, whenever both SPA and the backend share the same single virtual application. Unfortunately, due to browser cache busting techniques, the bundle files for Angular deployment will always ship with unique names and, therefore, an msbuild command/attribute or other possibility to wipe the folder clean on the IIS side before sending the updated files would be very welcomed. If anyone has found a way to do that, please share.

"Sync" functionality described here for msdeploy is exactly what we need to be doing but I don't know how to hook into this: https://docs.microsoft.com/en-us/previous-versions/windows/it-pro/windows-server-2008-R2-and-2008/dd569034(v=ws.10)#sync

In a sync operation, if the source file or folder does not exist on the destination, the provider creates the folder and any subfolders that have the corresponding files and attributes. If the destination folder already exists, the provider updates only those objects that do not match the source. This means that in some cases only one file or folder will be updated. Files on the destination that do not exist on the source will be deleted. The source and destination folders for contentPath do not have to have the same name. If the name of the destination folder differs from that of the source, the name of the destination folder will remain the same, but the contents of the folder will be updated to those of the source.

like image 477
cvocvo Avatar asked Apr 10 '18 16:04

cvocvo


Video Answer


1 Answers

If I understood you correctly, then resolve this problem is help DeleteExistingFiles property in publish profile.

<DeleteExistingFiles>True</DeleteExistingFiles>

If set to True the output directory (publishUrl) will be purged before output is written to it, it's good to start out with a clean slate.


How can I apply this to a specific folder, ex. only delete the "Project\dist" folder?

As I know result of this property is removing all files. For specify directories to remove you can try verb delete from MSDeploy, that can be wrap in <Exec> task of custom script:

<Exec Command="$(MSDeploy) -verb:delete -dest:&quot;ContentPath=D:\TestDir\Test.txt&quot"/>

/* 
 * $(MSDeploy) is path to MSDeploy binary that you passed to script.                                                                     
 */

This example show removing file on local machine. You should customize own call.


Exec Task | How to create a Web Deploy package when publishing a ClickOnce project (Some snippets for using targets)

like image 99
UserName Avatar answered Sep 19 '22 22:09

UserName