Update readme, add new CI pipeline samples

This commit is contained in:
Joris de Gruyter 2020-04-22 16:08:53 -07:00
Родитель 1a319af914
Коммит f49ad48b01
5 изменённых файлов: 490 добавлений и 45 удалений

Просмотреть файл

@ -0,0 +1,56 @@
---
page_type: sample
languages:
- powershell
- yaml
- json
products:
- azure-devops
- dynamics-finance
- dynamics-finance-operations
- dynamics-retail
- dynamics-commerce
- dynamics-scm
description: "Sample Azure DevOps Build Pipeline for X++ solutions (Dynamics 365)"
urlFragment: "update-this-to-unique-url-stub"
---
# Azure DevOps Pipeline Samples for X++
To run X++ build automation on any system outside of X++ development machines (including Azure DevOps hosted agents), [review the documentation on build automation](https://docs.microsoft.com/en-us/dynamics365/fin-ops-core/dev-itpro/dev-tools/hosted-build-automation). This sample contains an Azure DevOps YML and Classic Pipeline JSON to illustrate a basic X++ build pipeline.
## Contents
| File/folder | Description |
|--- |--- |
| `xpp-ci.yml` | A sample YML file for an X++ Git repo. |
| `xpp-classic-ci.json` | Classic pipeline definition to import manually. |
| `xpp-classic-ci.ps1` | PowerShell script to automatically create a classic pipeline definition in your project. |
## Prerequisites
Basic knowledge of the X++ developer workflow and related files such as models, source code XMLs and descriptors, and their relation to X++ binaries and deployable packages.
The samples, although broadly illustrating the build process, are specifically geared towards Azure DevOps and some knowledge of Azure DevOps pipelines is assumed. An Azure DevOps project is required to use these samples.
Finally, these samples depend on tasks from the [Dynamics 365 Finance and Operations Tools](https://marketplace.visualstudio.com/items?itemName=Dyn365FinOps.dynamics365-finops-tools) extension for Azure DevOps. Review the [Azure DevOps documentation](https://docs.microsoft.com/en-us/azure/devops/marketplace/install-extension?view=azure-devops&tabs=browser) on how to install an extension for an organization.
## Setup
- The **xpp-ci.yml** file can be placed inside a Git repository containing X++ source code to setup a build pipeline.
- To setup the classic definition which can work with TFVC (Team Foundation Version Control) as well as Git repositories, import the **xpp-classic-ci.json** file from the pipelines landing page. (See: [Export and Import a Pipeline](https://docs.microsoft.com/en-us/azure/devops/pipelines/create-first-pipeline?view=azure-devops&tabs=java%2Cclassic%2Cbrowser%2Ctfs-2018-2#export-and-import-a-pipeline)).
- Alternatively you can run the **xpp-classic-ci.ps1** PowerShell script, provide [connection credentials including a PAT token](https://docs.microsoft.com/en-us/azure/devops/organizations/accounts/use-personal-access-tokens-to-authenticate?view=azure-devops&tabs=preview-page#create-personal-access-tokens-to-authenticate-access), and follow the script's prompts to create a new pipeline definition in your project. The token requires at least **Build: Read & execute** permissions, as well as **Agent Pools: Read**.
## Contributing
This project welcomes contributions and suggestions. Most contributions require you to agree to a
Contributor License Agreement (CLA) declaring that you have the right to, and actually do, grant us
the rights to use your contribution. For details, visit https://cla.opensource.microsoft.com.
When you submit a pull request, a CLA bot will automatically determine whether you need to provide
a CLA and decorate the PR appropriately (e.g., status check, comment). Simply follow the instructions
provided by the bot. You will only need to do this once across all repos using our CLA.
This project has adopted the [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/).
For more information see the [Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/) or
contact [opencode@microsoft.com](mailto:opencode@microsoft.com) with any additional questions or comments.

Просмотреть файл

@ -0,0 +1,98 @@
# Sample YML pipeline for X++ builds
# For more information on build pipelines, see
# https://docs.microsoft.com/en-us/dynamics365/fin-ops-core/dev-itpro/dev-tools/hosted-build-automation
# Change the name of the build to a 4-digit version number to be used for model versioning
name: $(Date:yy.MM.dd)$(Rev:.r)
trigger:
- master
pool:
# Use the VS2017 image
vmImage: 'vs2017-win2016'
demands:
- msbuild
- visualstudio
# Declare some shorthand for NuGet package names
# Make editing the path for metadata and NuGet extraction folder easier
variables:
AppPackage: 'Microsoft.Dynamics.AX.Application.DevALM.BuildXpp'
PlatPackage: 'Microsoft.Dynamics.AX.Platform.DevALM.BuildXpp'
ToolsPackage: 'Microsoft.Dynamics.AX.Platform.CompilerPackage'
MetadataPath: '$(Build.SourcesDirectory)\Metadata'
NugetConfigsPath: '$(Build.SourcesDirectory)\Metadata'
NugetsPath: '$(Pipeline.Workspace)\NuGets'
steps:
# Install NuGet and use -ExcludeVersion option to avoid paths containing version numbers
- task: NuGetInstaller@0
displayName: 'NuGet install Packages'
inputs:
solution: '$(NugetConfigsPath)\packages.config'
nugetConfigPath: '$(NugetConfigsPath)\nuget.config'
restoreMode: install
nuGetRestoreArgs: '-ExcludeVersion -OutputDirectory "$(NugetsPath)"'
# Use the custom build number y.m.d.rev as the model version
# Default updates only VAR layer and above
- task: XppUpdateModelVersion@0
displayName: 'Update Model Version'
inputs:
XppSourcePath: '$(MetadataPath)'
VersionNumber: '$(Build.BuildNumber)'
# In case the X++ code has check-in binary dependencies, copy them to the output folder
# This is needed for packaging but also for the X++ compiler
- task: CopyFiles@2
displayName: 'Copy Binary Dependencies to: $(Build.BinariesDirectory)'
inputs:
SourceFolder: '$(MetadataPath)'
Contents: '**/bin/**'
TargetFolder: '$(Build.BinariesDirectory)'
# Build using MSBuild 15 (VS 2017)
# Provide the needed paths, including semi-colon separated list of reference folders
# /p:ReferenceFolder are metadata folders containing other (compiled) X++ packages that are referenced
# /p:ReferencePath are folders containing non-X++ assemblies referenced (aside from one already in the output folder for the package)
- task: VSBuild@1
displayName: 'Build solution **\*.sln'
inputs:
solution: '**/*.sln'
vsVersion: '15.0'
msbuildArgs: '/p:BuildTasksDirectory="$(NugetsPath)\$(ToolsPackage)\DevAlm" /p:MetadataDirectory="$(MetadataPath)" /p:FrameworkDirectory="$(NuGetsPath)\$(ToolsPackage)" /p:ReferenceFolder="$(NuGetsPath)\$(PlatPackage)\ref\net40;$(NuGetsPath)\$(AppPackage)\ref\net40;$(MetadataPath);$(Build.BinariesDirectory)" /p:ReferencePath="$(NuGetsPath)\$(ToolsPackage)" /p:OutputDirectory="$(Build.BinariesDirectory)"'
# Copy the compiler log files to the drop artifacts
- task: CopyFiles@2
displayName: 'Copy X++ Compile Log Files to: $(Build.ArtifactStagingDirectory)\Logs'
inputs:
SourceFolder: '$(Build.SourcesDirectory)'
Contents: |
**\Dynamics.AX.*.xppc.*
**\Dynamics.AX.*.labelc.*
**\Dynamics.AX.*.reportsc.*
TargetFolder: '$(build.ArtifactStagingDirectory)\Logs'
condition: succeededOrFailed()
# For packaging we need NuGet installed, with a version <3.4.0
- task: NuGetToolInstaller@0
displayName: 'Use NuGet 3.3.0'
inputs:
versionSpec: 3.3.0
- task: XppCreatePackage@0
displayName: 'Create Deployable Package'
inputs:
XppToolsPath: '$(NuGetsPath)\$(ToolsPackage)'
# Enable this task to add a license file to the package
- task: XppAddLicenseToPackage@0
displayName: 'Add Licenses to Deployable Package'
enabled: false
- task: PublishBuildArtifacts@1
displayName: 'Publish Artifact: drop'
inputs:
PathtoPublish: '$(build.artifactstagingdirectory)'
condition: succeededOrFailed()

Просмотреть файл

@ -0,0 +1,48 @@
$Organization = Read-Host "Organization name (X in X.visualstudio.com or dev.azure.com/X)"
$Project = Read-Host "Project name"
$PATToken = Read-Host "PAT Token"
$Branch = Read-Host "Branch name (hit ENTER for default 'Main')"
if (!$Branch)
{
$Branch = "Main"
}
$PipelineName = Read-Host "Pipeline name (hit ENTER for default 'X++ ($Branch)'"
if (!$PipelineName)
{
$PipelineName = "X++ ($Branch)"
}
$URI = "https://dev.azure.com/$($Organization)/$($Project)/_apis/build/definitions?api-version=5.1"
[int]$ExitCode = 0
try
{
$TokenBytes = [Text.Encoding]::UTF8.GetBytes(":$($PATToken)")
$TokenBase64 = [Convert]::ToBase64String($TokenBytes)
$AuthHeader = @{ Authorization = "Basic " + $TokenBase64 }
[string]$Pipeline = Get-Content -Raw (Join-Path -Path $PSScriptRoot -ChildPath "classic-ci.json")
$Pipeline = $Pipeline.Replace('{\"mappings\":[]}', '{\"mappings\":[{\"serverPath\":\"$/' + $ProjectName + '/Trunk/' + $Branch + '\",\"mappingType\":\"map\",\"localPath\":\"\\\\\"}]}')
$Pipeline = $Pipeline.Replace('"name": "X++ Classic Pipeline",','"name": "' + $PipelineName + '",')
Write-Host "Calling API at $URI"
Invoke-RestMethod -Uri $URI -Method POST -Headers $AuthHeader -Body $Pipeline -ContentType "application/json"
Write-Host
Write-Host
Write-Host "New pipeline definition successfully created."
}
catch [System.Exception]
{
$_.ErrorDetails.Message
Write-Host
Write-Host
Write-Host "Please ensure that the PAT token is not expired and valid for project '$Project'"
Write-Host "Please ensure the PAT token has access to `"Build 'read&execute'`" and `"Agent Pool 'read'`""
Write-Host "Please ensure you have the marketplace extension installed from https://marketplace.visualstudio.com/items?itemName=Dyn365FinOps.dynamics365-finops-tools"
$ExitCode = -1
}
Exit $ExitCode

Просмотреть файл

@ -0,0 +1,282 @@
{
"options": [
],
"demands": [
],
"variables": {
"AppPackage": {
"value": "Microsoft.Dynamics.AX.Application.DevALM.BuildXpp"
},
"MetadataPath": {
"value": "$(Build.SourcesDirectory)\\Metadata"
},
"NugetConfigsPath": {
"value": "$(Build.SourcesDirectory)\\Metadata"
},
"NugetsPath": {
"value": "$(Pipeline.Workspace)\\NuGets"
},
"PlatPackage": {
"value": "Microsoft.Dynamics.AX.Platform.DevALM.BuildXpp"
},
"system.debug": {
"value": "false",
"allowOverride": true
},
"ToolsPackage": {
"value": "Microsoft.Dynamics.AX.Platform.CompilerPackage"
}
},
"properties": {},
"tags": [],
"buildNumberFormat": "$(Date:yy.MM.dd)$(Rev:.r)",
"jobAuthorizationScope": "project",
"jobTimeoutInMinutes": 60,
"jobCancelTimeoutInMinutes": 5,
"process": {
"phases": [
{
"steps": [
{
"environment": {},
"enabled": true,
"continueOnError": false,
"alwaysRun": false,
"displayName": "NuGet install Packages",
"timeoutInMinutes": 0,
"condition": "succeeded()",
"task": {
"id": "333b11bd-d341-40d9-afcf-b32d5ce6f23b",
"versionSpec": "0.*",
"definitionType": "task"
},
"inputs": {
"solution": "$(NugetConfigsPath)\\packages.config",
"nugetConfigPath": "$(NugetConfigsPath)\\nuget.config",
"restoreMode": "install",
"noCache": "false",
"nuGetRestoreArgs": "-ExcludeVersion -OutputDirectory \"$(NugetsPath)\"",
"verbosity": "Detailed",
"nuGetVersion": "4.0.0.2283",
"nuGetPath": ""
}
},
{
"environment": {},
"enabled": true,
"continueOnError": false,
"alwaysRun": false,
"displayName": "Update Model Version",
"timeoutInMinutes": 0,
"condition": "succeeded()",
"task": {
"id": "2f934f7a-6f72-5a07-be8d-a8dd8c7e8ab9",
"versionSpec": "0.*",
"definitionType": "task"
},
"inputs": {
"XppSourcePath": "$(MetadataPath)",
"XppDescriptorSearch": "**\\Descriptor\\*.xml",
"XppLayer": "10",
"VersionNumber": "$(Build.BuildNumber)"
}
},
{
"environment": {},
"enabled": true,
"continueOnError": false,
"alwaysRun": false,
"displayName": "Copy Binary Dependencies to: $(Build.BinariesDirectory)",
"timeoutInMinutes": 0,
"condition": "succeeded()",
"task": {
"id": "5bfb729a-a7c8-4a78-a7c3-8d717bb7c13c",
"versionSpec": "2.*",
"definitionType": "task"
},
"inputs": {
"SourceFolder": "$(MetadataPath)",
"Contents": "**/bin/**",
"TargetFolder": "$(Build.BinariesDirectory)",
"CleanTargetFolder": "false",
"OverWrite": "false",
"flattenFolders": "false",
"preserveTimestamp": "false"
}
},
{
"environment": {},
"enabled": true,
"continueOnError": false,
"alwaysRun": false,
"displayName": "Build solution **\\*.sln",
"timeoutInMinutes": 0,
"condition": "succeeded()",
"task": {
"id": "71a9a2d3-a98a-4caa-96ab-affca411ecda",
"versionSpec": "1.*",
"definitionType": "task"
},
"inputs": {
"solution": "**\\*.sln",
"vsVersion": "15.0",
"msbuildArgs": "/p:BuildTasksDirectory=\"$(NugetsPath)\\$(ToolsPackage)\\DevAlm\" /p:MetadataDirectory=\"$(MetadataPath)\" /p:FrameworkDirectory=\"$(NuGetsPath)\\$(ToolsPackage)\" /p:ReferenceFolder=\"$(NuGetsPath)\\$(PlatPackage)\\ref\\net40;$(NuGetsPath)\\$(AppPackage)\\ref\\net40;$(MetadataPath);$(Build.BinariesDirectory)\" /p:ReferencePath=\"$(NuGetsPath)\\$(ToolsPackage)\" /p:OutputDirectory=\"$(Build.BinariesDirectory)\"",
"platform": "",
"configuration": "",
"clean": "false",
"maximumCpuCount": "false",
"restoreNugetPackages": "false",
"msbuildArchitecture": "x86",
"logProjectEvents": "true",
"createLogFile": "false",
"logFileVerbosity": "normal"
}
},
{
"environment": {},
"enabled": true,
"continueOnError": false,
"alwaysRun": true,
"displayName": "Copy X++ Compile Log Files to: $(Build.ArtifactStagingDirectory)\\Logs",
"timeoutInMinutes": 0,
"condition": "succeededOrFailed()",
"task": {
"id": "5bfb729a-a7c8-4a78-a7c3-8d717bb7c13c",
"versionSpec": "2.*",
"definitionType": "task"
},
"inputs": {
"SourceFolder": "$(Build.SourcesDirectory)",
"Contents": "**\\Dynamics.AX.*.xppc.*\n**\\Dynamics.AX.*.labelc.*\n**\\Dynamics.AX.*.reportsc.*",
"TargetFolder": "$(Build.ArtifactStagingDirectory)\\Logs",
"CleanTargetFolder": "false",
"OverWrite": "false",
"flattenFolders": "false",
"preserveTimestamp": "false"
}
},
{
"environment": {},
"enabled": true,
"continueOnError": false,
"alwaysRun": false,
"displayName": "Use NuGet 3.3.0",
"timeoutInMinutes": 0,
"condition": "succeeded()",
"task": {
"id": "2c65196a-54fd-4a02-9be8-d9d1837b7c5d",
"versionSpec": "0.*",
"definitionType": "task"
},
"inputs": {
"versionSpec": "3.3.0",
"checkLatest": "false"
}
},
{
"environment": {},
"enabled": true,
"continueOnError": false,
"alwaysRun": false,
"displayName": "Create Deployable Package",
"timeoutInMinutes": 0,
"condition": "succeeded()",
"task": {
"id": "7fb16795-60b5-5435-9c70-10ff3740b4f3",
"versionSpec": "0.*",
"definitionType": "task"
},
"inputs": {
"XppToolsPath": "$(NuGetsPath)\\$(ToolsPackage)",
"XppBinariesPath": "$(Build.BinariesDirectory)",
"XppBinariesSearch": "*",
"DeployablePackagePath": "$(Build.ArtifactStagingDirectory)\\AXDeployableRuntime_$(Build.BuildNumber).zip",
"DeploymentFolder": ""
}
},
{
"environment": {},
"enabled": false,
"continueOnError": false,
"alwaysRun": false,
"displayName": "Add Licenses to Deployable Package",
"timeoutInMinutes": 0,
"condition": "succeeded()",
"task": {
"id": "d5d98cc7-805d-5533-b5c3-9aaaf3910be9",
"versionSpec": "0.*",
"definitionType": "task"
},
"inputs": {
"LicenseFilePaths": "*.txt",
"DeployablePackagePath": "$(Build.ArtifactStagingDirectory)\\AXDeployableRuntime_$(Build.BuildNumber).zip"
}
},
{
"environment": {},
"enabled": true,
"continueOnError": false,
"alwaysRun": true,
"displayName": "Publish Artifact: drop",
"timeoutInMinutes": 0,
"condition": "succeededOrFailed()",
"task": {
"id": "2ff763a7-ce83-4e1f-bc89-0ae63477cebe",
"versionSpec": "1.*",
"definitionType": "task"
},
"inputs": {
"PathtoPublish": "$(build.artifactstagingdirectory)",
"ArtifactName": "drop",
"ArtifactType": "Container",
"TargetPath": "\\\\my\\share\\$(Build.DefinitionName)\\$(Build.BuildNumber)",
"Parallel": "false",
"ParallelCount": "8",
"FileCopyOptions": ""
}
}
],
"name": "Compile X++",
"refName": "XppCompileJob",
"condition": "succeeded()",
"target": {
"executionOptions": {
"type": 0
},
"allowScriptsAuthAccessOption": false,
"type": 1
},
"jobAuthorizationScope": 1
}
],
"target": {
"agentSpecification": {
"identifier": "vs2017-win2016"
}
},
"type": 1
},
"processParameters": {
},
"repository": {
"properties": {
"labelSourcesFormat": "$(Build.BuildNumber)",
"tfvcMapping": "{\"mappings\":[]}",
"cleanOptions": "1"
},
"id": "$/",
"type": "TfsVersionControl",
"clean": "true",
"checkoutSubmodules": false
},
"quality": "definition",
"name": "X++ Classic Pipeline",
"type": "build",
"queue": {
"name": "Azure Pipelines",
"pool": {
"name": "Azure Pipelines",
"isHosted": true
}
}
}

Просмотреть файл

@ -1,53 +1,14 @@
---
page_type: sample
languages:
- csharp
products:
- dotnet
description: "Add 150 character max description"
urlFragment: "update-this-to-unique-url-stub"
---
# X++ (Dynamics 365) Samples and Tools
# Official Microsoft Sample
<!--
Guidelines on README format: https://review.docs.microsoft.com/help/onboard/admin/samples/concepts/readme-template?branch=master
Guidance on onboarding samples to docs.microsoft.com/samples: https://review.docs.microsoft.com/help/onboard/admin/samples/process/onboarding?branch=master
Taxonomies for products and languages: https://review.docs.microsoft.com/new-hope/information-architecture/metadata/taxonomies?branch=master
-->
Give a short description for your sample here. What does it do and why is it important?
This repository contains samples of code, scripts and tools related to X++ or X++ tools.
## Contents
Outline the file contents of the repository. It helps users navigate the codebase, build configuration and any related assets.
We've organized the repository into folders sorting the different samples.
| File/folder | Description |
|-------------------|--------------------------------------------|
| `src` | Sample source code. |
| `.gitignore` | Define what to ignore at commit time. |
| `CHANGELOG.md` | List of changes to the sample. |
| `CONTRIBUTING.md` | Guidelines for contributing to the sample. |
| `README.md` | This README file. |
| `LICENSE` | The license for the sample. |
## Prerequisites
Outline the required components and tools that a user might need to have on their machine in order to run the sample. This can be anything from frameworks, SDKs, OS versions or IDE releases.
## Setup
Explain how to prepare the sample once the user clones or downloads the repository. The section should outline every step necessary to install dependencies and set up any settings (for example, API keys and output folders).
## Running the sample
Outline step-by-step instructions to execute the sample and see its output. Include steps for executing the sample from the IDE, starting specific services in the Azure portal or anything related to the overall launch of the code.
## Key concepts
Provide users with more context on the tools and services used in the sample. Explain some of the code that is being used and how services interact with each other.
| File/folder | Description |
|--- |--- |
| `CI-CD` | Sample scripts and definitions for X++ CI/CD |
## Contributing