|
| 1 | +# Umbraco CMS Build |
| 2 | + |
| 3 | +## Are you sure? |
| 4 | + |
| 5 | +In order to use Umbraco as a CMS and build your website with it, you should not build it yourself. If you're reading this then you're trying to contribute to Umbraco or you're debugging a complex issue. |
| 6 | + |
| 7 | +- Are you about to create a pull request for Umbraco? |
| 8 | +- Are you trying to get to the bottom of a problem in your existing Umbraco installation? |
| 9 | + |
| 10 | +If the answer is yes, please read on. Otherwise, make sure to head on over [to the download page](https://our.umbraco.com/download) and start using Umbraco CMS as intended. |
| 11 | + |
| 12 | +**Table of contents** |
| 13 | + |
| 14 | +[Building from source](#building-from-source) |
| 15 | + * [The quick build](#quick) |
| 16 | + * [Build infrastructure](#build-infrastructure) |
| 17 | + * [Properties](#properties) |
| 18 | + * [GetUmbracoVersion](#getumbracoversion) |
| 19 | + * [SetUmbracoVersion](#setumbracoversion) |
| 20 | + * [Build](#build) |
| 21 | + * [Build-UmbracoDocs](#build-umbracodocs) |
| 22 | + * [Verify-NuGet](#verify-nuget) |
| 23 | + * [Cleaning up](#cleaning-up) |
| 24 | + |
| 25 | +[Azure DevOps](#azure-devops) |
| 26 | + |
| 27 | +[Quirks](#quirks) |
| 28 | + * [Powershell quirks](#powershell-quirks) |
| 29 | + * [Git quirks](#git-quirks) |
| 30 | + |
| 31 | + |
| 32 | +## Building from source |
| 33 | + |
| 34 | +Did you read ["Are you sure"](#are-you-sure)? |
| 35 | + |
| 36 | +### Quick! |
| 37 | + |
| 38 | +To build Umbraco, fire up PowerShell and move to Umbraco's repository root (the directory that contains `src`, `build`, `LICENSE.md`...). There, trigger the build with the following command: |
| 39 | + |
| 40 | + build/build.ps1 |
| 41 | + |
| 42 | +If you only see a build.bat-file, you're probably on the wrong branch. If you switch to the correct branch (v8/contrib) the file will appear and you can build it. |
| 43 | + |
| 44 | +You might run into [Powershell quirks](#powershell-quirks). |
| 45 | + |
| 46 | +If it runs without errors; Hooray! Now you can continue with [the next step](CONTRIBUTING.md#how-do-i-begin) and open the solution and build it. |
| 47 | + |
| 48 | +### Build Infrastructure |
| 49 | + |
| 50 | +The Umbraco Build infrastructure relies on a PowerShell object. The object can be retrieved with: |
| 51 | + |
| 52 | + $ubuild = build/build.ps1 -get |
| 53 | + |
| 54 | +The object exposes various properties and methods that can be used to fine-grain build Umbraco. Some, but not all, of them are detailed below. |
| 55 | + |
| 56 | +#### Properties |
| 57 | + |
| 58 | +The object exposes the following properties: |
| 59 | + |
| 60 | +* `SolutionRoot`: the absolute path to the solution root |
| 61 | +* `VisualStudio`: a Visual Studio object (see below) |
| 62 | +* `NuGet`: the absolute path to the NuGet executable |
| 63 | +* `Zip`: the absolute path to the 7Zip executable |
| 64 | +* `VsWhere`: the absolute path to the VsWhere executable |
| 65 | +* `NodePath`: the absolute path to the Node install |
| 66 | +* `NpmPath`: the absolute path to the Npm install |
| 67 | + |
| 68 | +The Visual Studio object is `null` when Visual Studio has not been detected (eg on VSTS). When not null, the object exposes the following properties: |
| 69 | + |
| 70 | +* `Path`: Visual Studio installation path (eg some place under `Program Files`) |
| 71 | +* `Major`: Visual Studio major version (eg `15` for VS 2017) |
| 72 | +* `Minor`: Visual Studio minor version |
| 73 | +* `MsBuild`: the absolute path to the MsBuild executable |
| 74 | + |
| 75 | +#### GetUmbracoVersion |
| 76 | + |
| 77 | +Gets an object representing the current Umbraco version. Example: |
| 78 | + |
| 79 | + $v = $ubuild.GetUmbracoVersion() |
| 80 | + Write-Host $v.Semver |
| 81 | + |
| 82 | +The object exposes the following properties: |
| 83 | + |
| 84 | +* `Semver`: the semver object representing the version |
| 85 | +* `Release`: the main part of the version (eg `7.6.33`) |
| 86 | +* `Comment`: the pre release part of the version (eg `alpha02`) |
| 87 | +* `Build`: the build number part of the version (eg `1234`) |
| 88 | + |
| 89 | +#### SetUmbracoVersion |
| 90 | + |
| 91 | +Modifies Umbraco files with the new version. |
| 92 | + |
| 93 | +>This entirely replaces the legacy `UmbracoVersion.txt` file. Do *not* edit version infos in files. |
| 94 | +
|
| 95 | +The version must be a valid semver version. It can include a *pre release* part (eg `alpha02`) and/or a *build number* (eg `1234`). Examples: |
| 96 | + |
| 97 | + $ubuild.SetUmbracoVersion("7.6.33") |
| 98 | + $ubuild.SetUmbracoVersion("7.6.33-alpha.2") |
| 99 | + $ubuild.SetUmbracoVersion("7.6.33+1234") |
| 100 | + $ubuild.SetUmbracoVersion("7.6.33-beta.5+5678") |
| 101 | + |
| 102 | +#### Build |
| 103 | + |
| 104 | +Builds Umbraco. Temporary files are generated in `build.tmp` while the actual artifacts (zip files, NuGet packages...) are produced in `build.out`. Example: |
| 105 | + |
| 106 | + $ubuild.Build() |
| 107 | + |
| 108 | +Some log files, such as MsBuild logs, are produced in `build.tmp` too. The `build` directory should remain clean during a build. |
| 109 | + |
| 110 | +**Note: web.config** |
| 111 | + |
| 112 | +Building Umbraco requires a clean `web.config` file in the `Umbraco.Web.UI` project. If a `web.config` file already exists, the `pre-build` task (see below) will save it as `web.config.temp-build` and replace it with a clean copy of `web.Template.config`. The original file is replaced once it is safe to do so, by the `pre-packages` task. |
| 113 | + |
| 114 | +#### Build-UmbracoDocs |
| 115 | + |
| 116 | +Builds umbraco documentation. Temporary files are generated in `build.tmp` while the actual artifacts (docs...) are produced in `build.out`. Example: |
| 117 | + |
| 118 | + Build-UmbracoDocs |
| 119 | + |
| 120 | +Some log files, such as MsBuild logs, are produced in `build.tmp` too. The `build` directory should remain clean during a build. |
| 121 | + |
| 122 | +#### Verify-NuGet |
| 123 | + |
| 124 | +Verifies that projects all require the same version of their dependencies, and that NuSpec files require versions that are consistent with projects. Example: |
| 125 | + |
| 126 | + Verify-NuGet |
| 127 | + |
| 128 | +### Cleaning up |
| 129 | + |
| 130 | +Once the solution has been used to run a site, one may want to "reset" the solution in order to run a fresh new site again. |
| 131 | + |
| 132 | +At the very minimum, you want |
| 133 | + |
| 134 | + git clean -Xdf src/Umbraco.Web.UI/App_Data |
| 135 | + rm src/Umbraco.Web.UI/web.config |
| 136 | + |
| 137 | +Then, a simple 'Rebuild All' in Visual Studio will recreate a fresh `web.config` but should be quite fast (since it does not really need to rebuild anything). |
| 138 | + |
| 139 | +The `clean` Git command force (`-f`) removes (`-X`, note the capital X) all files and directories (`-d`) that are ignored by Git. |
| 140 | + |
| 141 | +This will leave media files and views around, but in most cases, it will be enough. |
| 142 | + |
| 143 | +To perform a more complete clear, you will want to also delete the content of the media, views, scripts... directories. |
| 144 | + |
| 145 | +The following command will force remove all untracked files and directories, whether they are ignored by Git or not. Combined with `git reset` it can recreate a pristine working directory. |
| 146 | + |
| 147 | + git clean -xdf . |
| 148 | + |
| 149 | +For git documentation see: |
| 150 | +* git [clean](<https://git-scm.com/docs/git-clean>) |
| 151 | +* git [reset](<https://git-scm.com/docs/git-reset>) |
| 152 | + |
| 153 | +## Azure DevOps |
| 154 | + |
| 155 | +Umbraco uses Azure DevOps for continuous integration, nightly builds and release builds. The Umbraco CMS project on DevOps [is available for anonymous users](https://umbraco.visualstudio.com/Umbraco%20Cms). |
| 156 | + |
| 157 | +DevOps uses the `Build-Umbraco` command several times, each time passing a different *target* parameter. The supported targets are: |
| 158 | + |
| 159 | +* `pre-build`: prepares the build |
| 160 | +* `compile-belle`: compiles Belle |
| 161 | +* `compile-umbraco`: compiles Umbraco |
| 162 | +* `pre-tests`: prepares the tests |
| 163 | +* `compile-tests`: compiles the tests |
| 164 | +* `pre-packages`: prepares the packages |
| 165 | +* `pkg-zip`: creates the zip files |
| 166 | +* `pre-nuget`: prepares NuGet packages |
| 167 | +* `pkg-nuget`: creates NuGet packages |
| 168 | + |
| 169 | +All these targets are executed when `Build-Umbraco` is invoked without a parameter (or with the `all` parameter). On VSTS, compilations (of Umbraco and tests) are performed by dedicated DevOps tasks. Similarly, creating the NuGet packages is also performed by dedicated DevOps tasks. |
| 170 | + |
| 171 | +Finally, the produced artifacts are published in two containers that can be downloaded from DevOps: `zips` contains the zip files while `nuget` contains the NuGet packages. |
| 172 | + |
| 173 | +>During a DevOps build, some environment `UMBRACO_*` variables are exported by the `pre-build` target and can be reused in other targets *and* in DevOps tasks. The `UMBRACO_TMP` environment variable is used in `Umbraco.Tests` to disable some tests that have issues with DevOps at the moment. |
| 174 | +
|
| 175 | +## Quirks |
| 176 | + |
| 177 | +### PowerShell Quirks |
| 178 | + |
| 179 | +There is a good chance that running `build.ps1` ends up in error, with messages such as |
| 180 | + |
| 181 | +>The file ...\build.ps1 is not digitally signed. You cannot run this script on the current system. For more information about running scripts and setting execution policy, see about_Execution_Policies. |
| 182 | +
|
| 183 | +PowerShell has *Execution Policies* that may prevent the script from running. You can check the current policies with: |
| 184 | + |
| 185 | + PS> Get-ExecutionPolicy -List |
| 186 | + |
| 187 | + Scope ExecutionPolicy |
| 188 | + ----- --------------- |
| 189 | + MachinePolicy Undefined |
| 190 | + UserPolicy Undefined |
| 191 | + Process Undefined |
| 192 | + CurrentUser Undefined |
| 193 | + LocalMachine RemoteSigned |
| 194 | + |
| 195 | +Policies can be `Restricted`, `AllSigned`, `RemoteSigned`, `Unrestricted` and `Bypass`. Scopes can be `MachinePolicy`, `UserPolicy`, `Process`, `CurrentUser`, `LocalMachine`. You need the current policy to be `RemoteSigned`—as long as it is `Undefined`, the script cannot run. You can change the current user policy with: |
| 196 | + |
| 197 | + PS> Set-ExecutionPolicy -Scope CurrentUser -ExecutionPolicy RemoteSigned |
| 198 | + |
| 199 | +Alternatively, you can do it at machine level, from within an elevated PowerShell session: |
| 200 | + |
| 201 | + PS> Set-ExecutionPolicy -Scope LocalMachine -ExecutionPolicy RemoteSigned |
| 202 | + |
| 203 | +And *then* the script should run. It *might* however still complain about executing scripts, with messages such as: |
| 204 | + |
| 205 | +>Security warning - Run only scripts that you trust. While scripts from the internet can be useful, this script can potentially harm your computer. If you trust this script, use the Unblock-File cmdlet to allow the script to run without this warning message. Do you want to run ...\build.ps1? |
| 206 | +[D] Do not run [R] Run once [S] Suspend [?] Help (default is "D"): |
| 207 | + |
| 208 | +This is usually caused by the scripts being *blocked*. And that usually happens when the source code has been downloaded as a Zip file. When Windows downloads Zip files, they are marked as *blocked* (technically, they have a Zone.Identifier alternate data stream, with a value of "3" to indicate that they were downloaded from the Internet). And when such a Zip file is un-zipped, each and every single file is also marked as blocked. |
| 209 | + |
| 210 | +The best solution is to unblock the Zip file before un-zipping: right-click the files, open *Properties*, and there should be a *Unblock* checkbox at the bottom of the dialog. If, however, the Zip file has already been un-zipped, it is possible to recursively unblock all files from PowerShell with: |
| 211 | + |
| 212 | + PS> Get-ChildItem -Recurse *.* | Unblock-File |
| 213 | + |
| 214 | +### Git Quirks |
| 215 | + |
| 216 | +Git might have issues dealing with long file paths during build. You may want/need to enable `core.longpaths` support (see [this page](https://github.com/msysgit/msysgit/wiki/Git-cannot-create-a-file-or-directory-with-a-long-path) for details). |
0 commit comments