- task: GetShifting.GraphEmail.graph-email-build-task.GraphEmail@0
displayName: "Send an email with subject Test mail from $(BUILD.DEFINITIONNAME)"
inputs:
To: "sjoerd@getshifting.com"
BCC: "$(BUILD.REQUESTEDFOREMAIL)"
From: "sjoerd@getshifting.com"
Subject: "Test mail from $(BUILD.DEFINITIONNAME)"
Body: |
This is a testmail
You can use various variables within the body of the email, for example:
- Build ID: $(build.buildid)
- Build Directory: $(agent.builddirectory)
- Build Queued By: $(BUILD.QUEUEDBY)
- Agent Name: $(AGENT.NAME)
- Job Name: $(SYSTEM.JOBDISPLAYNAME)
- Task Name: $(SYSTEM.TASKDISPLAYNAME)
- Build Requested for: $(BUILD.REQUESTEDFOR)
- Commit Message: $(BUILD.SOURCEVERSIONMESSAGE)
Kind regards,
$(BUILD.REQUESTEDFOR)
ClientID: "e5e6ce84-d241-4faf-97e0-d71a171f1adf"
ClientSecret: "$(ClientSecret)"
ShowClientSecret: false
TenantDomain: getshifting.com
This is an example of a task to send a single line email:
- task: GetShifting.GraphEmail.graph-email-build-task.GraphEmail@0
displayName: "Send graph email with subject Testmail from $(BUILD.DEFINITIONNAME)"
inputs:
To: "sjoerd@getshifting.com"
From: "sjoerd@getshifting.com"
Subject: "Testmail from $(BUILD.DEFINITIONNAME)"
Body: This is a short testmail
ClientID: "$(ClientID)"
ClientSecret: "$(ClientSecret)"
TenantDomain: getshifting.com
== Classic Pipeline Example ==
Even though classic pipelines are not used that much anymore, when I originally created the extension I still mostly used classic pipelines. Below is an example I used in my pipeline to test the extension:
[{{azuredevopsextensionsendemailgraph01.png?800|An example of a task to send a multiline email}}] \\
== The Build and Release Pipeline ==
Below is the almost full build and release pipeline I use to build, test and release the extension to the marketplace. Some notes have been removed, and some of the guids are changed. The tokenized files that are used in the replacetokens task can be reviewed on the public repository of the extension: [[https://github.com/getshifting/getshifting/tree/main/adoExtensionGraphEmail]]:
name: $(Build.DefinitionName)-$(Build.BuildId)
appendCommitMessageToRunName: false
variables:
- group: ExtensionGraph
- name: ClientID
value: "42ff8d60-02e0-43dd-9b57-008cbdd86dd2"
- name: tfxcli
value: "v0.9.x"
- name: extensionid
value: "graphemail"
- name: publisherprod
value: "getshifting"
- name: publisher
value: "getshifting-private"
- name: public
value: "false"
- name: currentDate
value: $[format('{0:yyyyMMdd}', pipeline.startTime)]
parameters:
- name: action
displayName: Action
type: string
default: "Build and Release Privately only"
values:
- "Build Only"
- "Build and Release Privately only"
- "Build and Release Public"
pool:
vmImage: windows-latest
trigger: none
resources:
repositories:
- repository: self
stages:
- stage: build
displayName: "Stage: Build"
jobs:
- job: build
displayName: "Job: Build & Package"
steps:
- task: PowerShell@2
displayName: "Get System Variables"
condition: eq(variables['System.debug'], true)
inputs:
pwsh: true
targetType: "inline"
script: |
Write-Host "`n##[section]Get System Variables`n"
Get-ChildItem -path env:* | Sort-Object Name
- task: ms-devlabs.vsts-developer-tools-build-tasks.tfx-installer-build-task.TfxInstaller@5
displayName: "Use Node CLI for Azure DevOps (tfx-cli): $(tfxcli)"
inputs:
version: "$(tfxcli)"
- task: qetza.replacetokens.replacetokens-task.replacetokens@6
displayName: 'Replace tokens in vss-extension.json graphEmail\task.json'
inputs:
sources: |
vss-extension.json
graphEmail\task.json
tokenPattern: doubleunderscores
telemetryOptout: true
root: '$(System.DefaultWorkingDirectory)\public\adoExtensionGraphEmail'
verbosity: "debug"
- task: PowerShell@2
displayName: "Add VstsTaskSdk PowerShell Module to the extension package"
inputs:
pwsh: true
targetType: "inline"
workingDirectory: '$(System.DefaultWorkingDirectory)\public\adoExtensionGraphEmail'
script: |
# Set the verbose flag based on pipeline variable
if ($env:SYSTEM_DEBUG -eq "True"){
Write-Host "##[debug]Verbose logging is enabled"
$verboseFlag = $true
} else {
$verboseFlag = $false
}
Write-Host "##[section]Set Variables"
$vstsTaskSdkDir = ".\graphEmail\ps_modules\VstsTaskSdk"
$vstsTempDir = ".\vststemp"
Write-Host "VstsTaskSdk Directory : $vstsTaskSdkDir"
Write-Host "VstsTaskSdk Temp Directory: $vstsTempDir"
if ($verboseFlag) {
Write-Host "##[debug]Check current directory structure"
Get-Location
Get-ChildItem -Recurse
}
Write-Host "##[section]Save VstsTaskSdk to $vstsTempDir and copy to $vstsTaskSdkDir"
Write-Host "`nCreate required directory structure"
New-Item -Path $vstsTaskSdkDir -ItemType "Directory" -Verbose:$verboseFlag
New-Item -Path $vstsTempDir -ItemType "Directory" -Verbose:$verboseFlag
Write-Host "`nSave VstsTaskSdk Module to temporary directory"
Save-Module -Name VstsTaskSdk -Path $vstsTempDir -Verbose:$verboseFlag
Write-Host "`nCopy all required files to VstsTaskSdk directory"
Get-ChildItem -Path $vstsTempDir -Recurse -File -Depth 2 | ForEach-Object { Copy-Item -Path $_.FullName -Destination $vstsTaskSdkDir -Verbose:$verboseFlag }
if ($verboseFlag) {
Write-Host "##[debug]Check current directory structure"
Get-Location
Get-ChildItem -Recurse
}
Write-Host "##[section]Remove temporary directory"
Remove-Item -Path $vstsTempDir -Recurse -Force -Verbose:$verboseFlag
if ($verboseFlag) {
Write-Host "##[debug]Check current directory structure"
Get-Location
Get-ChildItem -Recurse
}
- task: ms-devlabs.vsts-developer-tools-build-tasks.package-extension-build-task.PackageAzureDevOpsExtension@5
displayName: "Package Extension"
inputs:
rootFolder: "$(Build.SourcesDirectory)/public/adoExtensionGraphEmail"
outputPath: "$(build.artifactstagingdirectory)"
extensionVersion: "$(currentDate).$(Build.BuildId).$(System.StageAttempt)"
- task: PublishBuildArtifacts@1
displayName: "Publish Artifact: extension"
inputs:
ArtifactName: extension
- stage: releasePrivate
displayName: "Stage: Release Private"
condition: and(succeeded(),
or(
contains('${{ parameters.action }}', 'Build and Release Privately only'),
contains('${{ parameters.action }}', 'Build and Release Public')))
jobs:
- job: releasePrivate
displayName: "Job: Release Privately"
steps:
- task: ms-devlabs.vsts-developer-tools-build-tasks.tfx-installer-build-task.TfxInstaller@5
displayName: "Use Node CLI for Azure DevOps (tfx-cli): $(tfxcli)"
inputs:
version: "$(tfxcli)"
- task: DownloadPipelineArtifact@2
inputs:
artifactName: "extension"
targetPath: "$(System.DefaultWorkingDirectory)/DevOpsExtensionGraph/extension"
- task: ms-devlabs.vsts-developer-tools-build-tasks.publish-extension-build-task.PublishAzureDevOpsExtension@5
displayName: "Publish Extension"
inputs:
connectTo: "VsTeam"
connectedServiceName: "AzureDevOpsMarketPlace"
fileType: vsix
vsixFile: "$(System.DefaultWorkingDirectory)/DevOpsExtensionGraph/extension/getshifting-private.GraphEmail-$(currentDate).$(Build.BuildId).$(System.StageAttempt).vsix"
updateTasksVersion: false
extensionVisibility: private
extensionPricing: free
- job: waitForInstall
displayName: "Job: Wait for the Private Extension to be installed"
dependsOn: releasePrivate
pool: server
timeoutInMinutes: 1440
steps:
- task: ManualValidation@0
displayName: "Wait for the private extension is installed"
timeoutInMinutes: 120
inputs:
notifyUsers: |
sjoerd@getshifting.com
instructions: 'Go to the Marketplace icon in the top right, and select "Manage Extensions". Click on "Send email through Graph by GetShifting-Private" and wait for the extension to be automatically updated to the just released version.'
onTimeout: "reject"
- job: testPublic
displayName: "Job: Test Privately"
dependsOn: waitForInstall
steps:
- task: GetShifting-Private.GraphEmail.graph-email-build-task.GraphEmail@0
displayName: "Send an email with subject Test mail from $(BUILD.DEFINITIONNAME)"
inputs:
To: "sjoerd@getshifting.com"
BCC: "$(BUILD.REQUESTEDFOREMAIL)"
From: "sjoerd@getshifting.com"
Subject: "Test mail from $(BUILD.DEFINITIONNAME)"
Body: |
This is a testmail
You can use various variables within the body of the email, for example:
- Build ID: $(build.buildid)
- Build Directory: $(agent.builddirectory)
- Build Queued By: $(BUILD.QUEUEDBY)
- Agent Name: $(AGENT.NAME)
- Job Name: $(SYSTEM.JOBDISPLAYNAME)
- Task Name: $(SYSTEM.TASKDISPLAYNAME)
- Build Requested for: $(BUILD.REQUESTEDFOR)
- Commit Message: $(BUILD.SOURCEVERSIONMESSAGE)
Kind regards,
$(BUILD.REQUESTEDFOR)
ClientID: "$(ClientID)"
ClientSecret: "$(ClientSecret)"
ShowClientSecret: true
TenantDomain: getshifting.com
- stage: releasePublic
displayName: "Stage: Release Public"
condition: and(succeeded(), eq('${{ parameters.action }}', 'Build and Release Public'))
jobs:
- job: releasePublic
displayName: "Job: Release Publicly"
steps:
- task: ms-devlabs.vsts-developer-tools-build-tasks.tfx-installer-build-task.TfxInstaller@5
displayName: "Use Node CLI for Azure DevOps (tfx-cli): $(tfxcli)"
inputs:
version: "$(tfxcli)"
- task: DownloadPipelineArtifact@2
inputs:
artifactName: "extension"
targetPath: "$(System.DefaultWorkingDirectory)/DevOpsExtensionGraph/extension"
- task: ms-devlabs.vsts-developer-tools-build-tasks.publish-extension-build-task.PublishAzureDevOpsExtension@5
displayName: "Publish Extension"
inputs:
connectTo: "VsTeam"
connectedServiceName: "AzureDevOpsMarketPlace"
fileType: vsix
vsixFile: "$(System.DefaultWorkingDirectory)/DevOpsExtensionGraph/extension/getshifting-private.GraphEmail-$(currentDate).$(Build.BuildId).$(System.StageAttempt).vsix"
publisherId: "$(publisherprod)"
updateTasksVersion: false
updateTasksId: true
extensionVisibility: public
extensionPricing: free
- job: waitForInstall
displayName: "Job: Wait for the Public Extension to be installed"
dependsOn: releasePublic
pool: server
timeoutInMinutes: 1440
steps:
- task: ManualValidation@0
displayName: "Wait for the public extension is installed"
timeoutInMinutes: 120
inputs:
notifyUsers: |
sjoerd@getshifting.com
instructions: 'Go to the Marketplace icon in the top right, and select "Manage Extensions". Click on "Send email through Graph by GetShifting" and wait for the extension to be automatically updated to the just released version.'
onTimeout: "reject"
- job: testPublic
displayName: "Job: Test Publicly"
dependsOn: waitForInstall
steps:
- task: GetShifting.GraphEmail.graph-email-build-task.GraphEmail@0
displayName: "Send graph email with subject Testmail from $(BUILD.DEFINITIONNAME)"
inputs:
To: "sjoerd@getshifting.com"
From: "sjoerd@getshifting.com"
Subject: "Testmail from $(BUILD.DEFINITIONNAME)"
Body: Test from public
ClientID: "$(ClientID)"
ClientSecret: "$(ClientSecret)"
TenantDomain: getshifting.com
== Useful Resources ==
* [[https://learn.microsoft.com/en-us/azure/devops/extend/develop/manifest?view=azure-devops |Extension Manifest]]
//This wiki has been made possible by://