Code Monkey home page Code Monkey logo

azurepipelinestogithubactionsconverter's Introduction

Convert Azure Pipelines YAML to GitHub Actions YAML

A project to create a conversion tool to make migrations between Azure Pipelines YAML and GitHub Actions YAML easier. As GitHub Actions becomes more popular, it's clear that a migration tool will be useful to move workloads to GitHub.

Current build Coverage Status Latest NuGet package Current Release

How to use

We built a website that uses this module at: https://pipelinestoactions.azurewebsites.net/.
You can also use the NuGet package

Example:

The Azure Pipelines YAML to build a dotnet application on ubuntu:

trigger:
- main
variables:
  buildConfiguration: Release
jobs:
- job: Build
  displayName: Build job
  pool: 
    vmImage: ubuntu-latest
  steps: 
  - script: dotnet build WebApplication1/WebApplication1.Service/WebApplication1.Service.csproj --configuration $(buildConfiguration) 
    displayName: dotnet build webapp

In GitHub Actions:

on: 
  push:
    branches:
    - main
env:
  buildConfiguration: Release
jobs:
  Build:
    name: Build job
    runs-on: ubuntu-latest
    steps:
    - uses: actions/checkout@v1
    - name: dotnet build webapp
      run: dotnet build WebApplication1/WebApplication1.Service/WebApplication1.Service.csproj --configuration ${{ env.buildConfiguration }}";

Current builds running

The table below shows current, functioning YML files that run on a regular schedule to regression test the YAML produced

Language Azure Pipelines GitHub Actions
.NET Core WebAPI .NET Core WebAPI .NET Core WebAPI
.NET Framework Desktop .NET Framework Desktop .NET Framework Desktop
Ant Ant Ant
Maven Maven Maven
NodeJS NodeJS Node.js
Python Python Python
Ruby Ruby Ruby

How this works

Currently this only supports one-way migrations from Azure Pipelines to GitHub Actions. There are functions to deserialize Azure Pipelines, and serialize and deserialize GitHub Actions. While this is translating many steps, there are nearly infinite combinations, therefore most of the focus has been supporting the basic .NET pipelines. Even if steps can't convert, the pipeline should. Check the issues for incomplete items, or the TODO's in the source code.

Yaml can be challenging. The yaml wikipedia page does a very good job of laying out the rules, but when we are talking about converting yaml to C#, there are a few things to know:

  1. Use a good editor - Visual Studio Code has a decent YAML extension (https://marketplace.visualstudio.com/items?itemName=docsmsft.docs-yaml), or if using Visual Studio, enable spaces with CTRL+R,CTRL+W. The GitHub and Azure DevOps in-browser editors are decent too.
  2. String arrays (string[]) are useful for lists (e.g -job). Note both of the following pieces of code for triggers are effectively the same (although the YamlDotNet serializer does not currently support the single line 'sequence flow' format)
trigger: [main,develop]

trigger:
- main
- develop
  1. The dictonary object (dictonary<string,string>) is useful for dynamic key value pairs, for example, variables
variables:
  MY_VAR: 'my value'
  ANOTHER_VAR: 'another value'

The C# definition for a dictonary looks like:

Dictionary<string, string> variables = new Dictionary<string, string>
{
    { "MY_VAR", "my value" },
    { "ANOTHER_VAR", "another value" }
};
  1. Just about everything else can be a string or object. Here is an example of a simple job:
- job: Build
  displayName: 'Build job'
  pool:
    vmImage: ubuntu-latest
public string job { get; set; }
public string displayName { get; set; }
public Pool pool { get; set; }
  1. Yaml is wack. The white spaces can destroy you, as the errors returned are often not helpful at all. Take lots of breaks. In the end YAML is worth it - I promise!

Current limitations

There are a number of Azure Pipeline features that don't currently match up well with a GitHub feature, and hence, these migrate with a change in functionality (e.g. parameters become variables and stages become jobs), or not at all (e.g. deployment strategies/environments). As/if these features are added to Actions, we will build in the conversions

Stages

Stages are converted to jobs. For example, a job "JobA" in a stage "Stage1", becomes a job named "Stage1_JobA"

Azure Pipelines YAML
stages:
- stage: Build
  displayName: 'Build Stage'
  jobs:
  - job: Build
    displayName: 'Build job'
    pool:
      vmImage: windows-latest
    steps:
    - task: PowerShell@2
      inputs:
        targetType: 'inline'
        script: |
         Write-Host "Hello world!"

  - job: Build2
    displayName: 'Build job 2'
    pool:
      vmImage: windows-latest
    steps:
    - task: PowerShell@2
      inputs:
        targetType: 'inline'
        script: |
         Write-Host "Hello world 2!"
GitHub Actions YAML
jobs:
  Build_Stage_Build:
    name: Build job
    runs-on: windows-latest
    steps:
    - uses: actions/checkout@v1
    - run: 
        Write-Host "Hello world!"
      shell: powershell
  Build_Stage_Build2:
    name: Build job 2
    runs-on: windows-latest
    steps:
    - uses: actions/checkout@v1
    - run: 
        Write-Host "Hello world 2!"
      shell: powershell

Parameters

Parameters become variables

Azure Pipelines YAML
parameters: 
  buildConfiguration: 'Release'
  buildPlatform: 'Any CPU'

jobs:
  - job: Build
    displayName: 'Build job'
    pool:
      vmImage: windows-latest
    steps:
    - task: PowerShell@2
      displayName: 'Test'
      inputs:
        targetType: inline
        script: |
          Write-Host "Hello world ${{parameters.buildConfiguration}} ${{parameters.buildPlatform}}"
GitHub Actions YAML
env:
  buildConfiguration: Release
  buildPlatform: Any CPU
jobs:
  Build:
    name: Build job
    runs-on: windows-latest
    steps:
    - uses: actions/checkout@v1
    - name: Test
      run: Write-Host "Hello world ${{ env.buildConfiguration }} ${{ env.buildPlatform }}"
      shell: powershell

RunOnce deployment strategy and deployment jobs

The strategy and deployment job is consolidated to a job, with the strategy removed, as there is no GitHub equivalent

Azure Pipelines YAML
jobs:
  - deployment: DeployInfrastructure
    displayName: Deploy job
    environment: Dev
    pool:
      vmImage: windows-latest
    strategy:
      runOnce:
        deploy:
          steps:
          - task: PowerShell@2
            displayName: 'Test'
            inputs:
              targetType: inline
              script: |
                Write-Host ""Hello world""";
GitHub Actions YAML
jobs:
  DeployInfrastructure:
    name: Deploy job
    runs-on: windows-latest
    steps:
    - name: Test
      run: Write-Host ""Hello world""
      shell: powershell

Templates

There are no templates in GitHub actions. At this time we are converting the template into an (almost) empty job.

jobs:
- template: azure-pipelines-build-template.yml
  parameters:
    buildConfiguration: 'Release'
    buildPlatform: 'Any CPU'
    vmImage: windows-latest
jobs:
  job_1_template:
    #: 'Note: Azure DevOps template does not have an equivalent in GitHub Actions yet'
    steps:
    - uses: actions/checkout@v1

Conditions

Conditions are processing with about 98% accuracy. There are some system variables that still need conversions, but we've tried to handle the most popular combinations.

System Variables

This is our current table of how we are translating Azure DevOps system variables, to GitHub Environment variables.

Azure Pipelines GitHub Actions
Build.ArtifactStagingDirectory github.workspace
Build.BuildId github.run_id
Build.BuildNumber github.run_number
Build.SourceBranch github.ref
Build.Repository.Name github.repository
Build.SourcesDirectory github.workspace
Build.StagingDirectory github.workspace
System.DefaultWorkingDirectory github.workspace
Agent.OS runner.os

Architecture

The core functionality is contained in a .NET Standard 2.0 class, "AzurePipelinesToGitHubActionsConverter.Core".

  • In the conversion object, is a public call, "ConvertAzurePipelineToGitHubAction", to convert Azure DevOps yaml to GitHub Actions yaml:
  • In the same conversion object is a call to convert individual tasks/steps: "ConvertAzurePinelineTaskToGitHubActionTask"
  • The GitHubActionsSerialization object has calls to serialize and deserialize GitHub actions

Testing:

  • There is a .NET CORE 3.1 MSTest project for tests, "AzurePipelinesToGitHubActionsConverter.Tests"

Current projects consuming this:

References

Made with help from https://github.com/aaubry/YamlDotNet and https://en.wikipedia.org/wiki/YAML.

Contributing

Pull requests are welcome. For major changes, please open an issue first to discuss what you would like to change. Please use a consistent naming convention for your feature branches to identify the work done in the branch. Some suggestions for naming:

  • features/feature-name
  • bugfix/description
  • hotfix/description

azurepipelinestogithubactionsconverter's People

Contributors

bytemech avatar dependabot-preview[bot] avatar dependabot[bot] avatar f2calv avatar samsmithnz avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar

azurepipelinestogithubactionsconverter's Issues

Add UseRubyVersion@0 task

# Ruby
# Package your Ruby project.
# Add steps that install rails, analyze code, save build artifacts, deploy, and more:
# https://docs.microsoft.com/azure/devops/pipelines/languages/ruby

trigger:
- master

pool:
  vmImage: 'ubuntu-latest'

steps:
- task: UseRubyVersion@0
  inputs:
    versionSpec: '>= 2.5'

- script: |
    gem install bundler
    bundle install --retry=3 --jobs=4
  displayName: 'bundle install'

- script: bundle exec rake
  displayName: 'bundle exec rake'

Add Maven@3 task

# Maven
# Build your Java project and run tests with Apache Maven.
# Add steps that analyze code, save build artifacts, deploy, and more:
# https://docs.microsoft.com/azure/devops/pipelines/languages/java

trigger:
- master

pool:
  vmImage: 'ubuntu-latest'

steps:
- task: Maven@3
  inputs:
    mavenPomFile: 'pom.xml'
    mavenOptions: '-Xmx3072m'
    javaHomeOption: 'JDKVersion'
    jdkVersionOption: '1.8'
    jdkArchitectureOption: 'x64'
    publishJUnitResults: true
    testResultsFiles: '**/surefire-reports/TEST-*.xml'
    goals: 'package'

Bug: multiple extra newline characters appearing on unknown tasks

For example:

this Azure DevOps YAML:
pool:
vmImage: 'ubuntu-16.04'

variables:
DOTNET_SKIP_FIRST_TIME_EXPERIENCE: true

steps:

  • task: PublishPipelineArtifact@0
    displayName: Store artifact
    inputs:
    artifactName: 'MyProject'
    targetPath: 'MyProject/bin/release/netcoreapp2.2/publish/'

Becomes:
env:
DOTNET_SKIP_FIRST_TIME_EXPERIENCE: true
jobs:
build:
runs-on: ubuntu-16.04
steps:
- uses: actions/checkout@v1
- #: 'This step does not have a conversion yet: PublishPipelineArtifact@0'
name: 'This step could not be migrated: Store artifact'
run:
#task: PublishPipelineArtifact@0

    #displayName: Store artifact

    #inputs:

    #  artifactName: MyProject

    #  targetPath: MyProject/bin/release/netcoreapp2.2/publish/

  shell: powershell

Add Ant@1 task

Currently this doesn't have a task conversion

# Ant
# Build your Java projects and run tests with Apache Ant.
# Add steps that save build artifacts and more:
# https://docs.microsoft.com/azure/devops/pipelines/languages/java

trigger:
- master

pool:
  vmImage: 'ubuntu-latest'

steps:
- task: Ant@1
  inputs:
    workingDirectory: ''
    buildFile: 'build.xml'
    javaHomeOption: 'JDKVersion'
    jdkVersionOption: '1.8'
    jdkArchitectureOption: 'x64'
    publishJUnitResults: true
    testResultsFiles: '**/TEST-*.xml'

reduce repository path depth

So the repository path is really very long, Windows has a max path/folder length of 260 (which will never change to maintain compatibility with older software) but when I build your project from my usual local development folder it won't build because one of the file paths is 261.

My local development folder is - C:\Users\Alex\source\repos\github\ - so not an unreasonable length...

The result is a failed build;
image

The full path is 261 chars!
C:\Users\Alex\source\repos\github\AzurePipelinesToGitHubActionsConverter\AzurePipelinesToGitHubActionsConverter\AzurePipelinesToGitHubActionsConverter.Tests\bin\Debug\netcoreapp3.1\Microsoft.VisualStudio.TestPlatform.MSTestAdapter.PlatformServices.Interface.dll

I would like to suggest renaming the root folder to /src which will save a bunch of chars and allow me (and others) to restore this into a directory other than c:\x :)

AzurePipelinesToGitHubActionsConverter\AzurePipelinesToGitHubActionsConverter\AzurePipelinesToGitHubActionsConverter.Tests
becomes
src\AzurePipelinesToGitHubActionsConverter\AzurePipelinesToGitHubActionsConverter.Tests

I guess this will affect the build pipeline(s).

Multi-line script doesn't add the pipe correctly

Script:

# Starter pipeline
# Start with a minimal pipeline that you can customize to build and deploy your code.
# Add steps that build, run tests, deploy, and more:
# https://aka.ms/yaml

trigger:
- master

pool:
  vmImage: 'ubuntu-latest'

steps:
- script: echo Hello, world!
  displayName: 'Run a one-line script'

- script: |
    echo Add other tasks to build, test, and deploy your project.
    echo See https://aka.ms/yaml
  displayName: 'Run a multi-line script'

Actual result:

on:
  push:
    branches:
    - master
jobs:
  build:
    runs-on: ubuntu-latest
    steps:
    - uses: actions/checkout@v1
    - name: Run a one-line script
      run: echo Hello, world!
    - name: Run a multi-line script
      run: 
        echo Add other tasks to build, test, and deploy your project.

        echo See https://aka.ms/yaml
                    

Expected result:

on:
  push:
    branches:
    - master
jobs:
  build:
    runs-on: ubuntu-latest
    steps:
    - uses: actions/checkout@v1
    - name: Run a one-line script
      run: echo Hello, world!
    - name: Run a multi-line script
      run: |
        echo Add other tasks to build, test, and deploy your project.
        echo See https://aka.ms/yaml
                    

MSBuild task is showing escaped newline characters instead of actual newlines

This YAML processes the msbuild with escaped newline characters, instead of real new lines:

# .NET Desktop
# Build and run tests for .NET Desktop or Windows classic desktop solutions.
# Add steps that publish symbols, save build artifacts, and more:
# https://docs.microsoft.com/azure/devops/pipelines/apps/windows/dot-net

trigger:
- master

pool:
  vmImage: 'windows-latest'

variables:
  solution: '**/*.sln'
  buildPlatform: 'Any CPU'
  buildConfiguration: 'Release'

steps:
- task: NuGetToolInstaller@1

- task: NuGetCommand@2
  inputs:
    restoreSolution: '$(solution)'

- task: VSBuild@1
  inputs:
    solution: '$(solution)'
    platform: '$(buildPlatform)'
    configuration: '$(buildConfiguration)'

- task: VSTest@2
  inputs:
    platform: '$(buildPlatform)'
    configuration: '$(buildConfiguration)'

Result:


#Note: Needs to be installed from marketplace: https://github.com/warrenbuckley/Setup-Nuget
on:
  push:
    branches:
    - master
env:
  solution: '**/*.sln'
  buildPlatform: Any CPU
  buildConfiguration: Release
jobs:
  build:
    runs-on: windows-latest
    steps:
    - uses: actions/checkout@v1
    - #: 'Note: Needs to be installed from marketplace: https://github.com/warrenbuckley/Setup-Nuget'
      uses: warrenbuckley/Setup-Nuget@v1
    - run: nuget  ${{ env.solution }}
      shell: powershell
    - run: " |\n    $msBuildExe = \"C:\\Program Files(x86)\\Microsoft Visual Studio\\2019\\Enterprise\\MSBuild\\Current\\Bin\\msbuild.exe\"\n    $targetSolution = \"${{ env.solution }}\"\n    #Note that the `\" is an escape character sequence to quote strings, and `& is needed to start the command\n    $command = \"`& `\"$msBuildExe`\" `\"$targetSolution`\" \n    Write - Host \"$command\"\n    Invoke - Expression $command"
      shell: powershell
    - run: |
            $vsTestConsoleExe = "C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\Common7\IDE\Extensions\TestPlatform\vstest.console.exe"
            $targetTestDll = ""
            $testRunSettings = " / Settings:`"`" "
            $parameters = "-- "    #Note that the `" is an escape character sequence to quote strings, and `& is needed to start the command
            $command = "`& `"$vsTestConsoleExe`" `"$targetTestDll`" $testRunSettings $parameters "
            Write - Host "$command"
            Invoke - Expression $command
      shell: powershell
                    

Need to fix common condition from variables when filtering by branch

Currently this condition:

condition: and(succeeded(), eq(variables['Build.SourceBranch'], 'refs/heads/master'))

Converts to:

if: and(success(),eq(variables['Build.SourceBranch'], 'refs/heads/master'))

But should convert to:

if: and(success(),eq(github.ref, 'refs/heads/master'))

Additionally, the condition:

condition: and(succeeded(), eq(variables['Build.SourceBranchName'], 'master'))

Doesn't have a logical conversion to GitHub, as branchName (or refName) doesn't exists, and should probably be:

if: and(success(),contains(github.ref, 'master'))

or

if: and(success(),endsWith(github.ref, 'master'))

variable groups not currently supported

Example:

variables:
- group: 'my group name'

Resolution:
need to support all variable types

  • 1. Regular/list based (currently support):
variables:
  configuration: debug
  platform: x64
  • 2. Irregular/object based:
variables:
# a regular variable
- name: myvariable
  value: myvalue
# a variable group
- group: myvariablegroup
# a reference to a variable template
- template: myvariabletemplate.yml

e.g.

variables: 
- group: 'my-var-group' # variable group
- name: 'devopsAccount' # new variable defined in YAML
  value: 'contoso'
- name: 'projectName' # new variable defined in YAML
  value: 'contosoads'

BUG: Publish Pipeline Artifact not converting

Pipelines YAML:

  • task: PublishPipelineArtifact@0
    displayName: Store artifact
    inputs:
    artifactName: 'MyProject'
    targetPath: 'MyProject/bin/release/netcoreapp2.2/publish/'
    condition: and(succeeded(), endsWith(variables['Agent.JobName'], 'DotNetCore22'))

Actions YAML:
- #: 'This step does not have a conversion yet: PublishPipelineArtifact@0'
name: Store artifact
run: "#task: PublishPipelineArtifact@0#displayName: Store artifact#condition: and(succeeded(), endsWith(variables['Agent.JobName'], 'DotNetCore22'))#inputs:# artifactname: MyProject# targetpath: MyProject/bin/release/netcoreapp2.2/publish/"
shell: powershell

Perhaps market this as a GitHub Actions serializer?

Is your feature request related to a problem? Please describe.
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]

Describe the solution you'd like
A clear and concise description of what you want to happen.

Describe alternatives you've considered
A clear and concise description of any alternative solutions or features you've considered.

Additional context
Add any other context or screenshots about the feature request here.

Extra null steps appearing

Extra null steps appearing, (see the extra -) why?

    steps:
    - uses: actions/checkout@v1
    - #: 'Note that "AZURE_SP" secret is required to be setup and added into GitHub Secrets: https://help.github.com/en/actions/automating-your-workflow-with-github-actions/creating-and-using-encrypted-secrets'
      name: Azure Login
      uses: azure/login@v1
      with:
        creds: ${{ secrets.AZURE_SP }}
    - 
    - 
    - name: Download the build artifacts
      uses: actions/[email protected]
      with:
        name: drop

Add support for Pull Requests

Is your feature request related to a problem? Please describe.
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]

Describe the solution you'd like
A clear and concise description of what you want to happen.

Describe alternatives you've considered
A clear and concise description of any alternative solutions or features you've considered.

Additional context
Add any other context or screenshots about the feature request here.

Powershell when targettype is "FilePath" is not working

Currently:

    - task: PowerShell@2
      displayName: 'PowerShell test task'
      inputs:
        targetType: FilePath
        filePath: MyProject/BuildVersion.ps1
        arguments: -ProjectFile "MyProject/MyProject.Web/MyProject.Web.csproj"

Just returns:

- name: PowerShell test task
  shell: powershell

but should return:

- name: PowerShell test task
  run: MyProject/BuildVersion.ps1 -ProjectFile ""MyProject/MyProject.Web/MyProject.Web.csproj""
  shell: powershell

Add UsePythonVersion@0 task

# Python package
# Create and test a Python package on multiple Python versions.
# Add steps that analyze code, save the dist with the build record, publish to a PyPI-compatible index, and more:
# https://docs.microsoft.com/azure/devops/pipelines/languages/python

trigger:
- master

pool:
  vmImage: 'ubuntu-latest'
strategy:
  matrix:
    Python27:
      python.version: '2.7'
    Python35:
      python.version: '3.5'
    Python36:
      python.version: '3.6'
    Python37:
      python.version: '3.7'

steps:
- task: UsePythonVersion@0
  inputs:
    versionSpec: '$(python.version)'
  displayName: 'Use Python $(python.version)'

- script: |
    python -m pip install --upgrade pip
    pip install -r requirements.txt
  displayName: 'Install dependencies'

- script: |
    pip install pytest pytest-azurepipelines
    pytest
  displayName: 'pytest'

Add better support for resources, especially repositories

Repositories are set in Azure DevOps at the beginning of the pipeline, and then referenced later in checkouts. This changes in GitHub, to a model where they are only set and referenced the checkout.

Additionally, GitHub only supports GitHub repos, whereas Azure DevOps supports Azure Repos, GitHub, and (with a service connection) BitBucket.

This initial translation will only target GitHub repos, and then as we go we will add messages for the others

  • Add support for GitHub repos
  • Add support for Azure Repos/Bitbucket (probably a message that this needs to be reviewed)

Pipelines: https://docs.microsoft.com/en-us/azure/devops/pipelines/yaml-schema?view=azure-devops&tabs=schema%2Cparameter-schema#resources
Actions: https://github.com/actions/checkout

Bug: Invalid YAML unit test has differences running in Windows (dev laptop) and Linux (runner)

X InvalidStepIndividualStepTest [30ms]
Error Message:
Assert.AreEqual failed.

Expected:
<- #: 'This step does not have a conversion yet: invalid fake task'
name: 'This step could not be migrated'
run: '#task: invalid fake task'
shell: powershell>.

Actual:
<- #: 'This step does not have a conversion yet: invalid fake task'
name: 'This step could not be migrated'
run: '#task: invalid fake task'
shell: powershell>.

Stack Trace:
at AzurePipelinesToGitHubActionsConverter.Tests.StepsTest.InvalidStepIndividualStepTest() in /home/runner/work/AzurePipelinesToGitHubActionsConverter/AzurePipelinesToGitHubActionsConverter/AzurePipelinesToGitHubActionsConverter/AzurePipelinesToGitHubActionsConverter.Tests/StepsTest.cs:line 25

Resolve issues with Docker@2 task

Need to handle:

  • build
  • push
  • build and push
  • login
  • logout
    - task: Docker@2
      displayName: Build an image
      inputs:
        command: build
        dockerfile: '{{ dockerfilePath }}'
        tags: |
          $(tag)

Add Docker and AzureFunctionAppContainer Tasks

Resolve missing tasks for Docker@1 and AzureFunctionAppContainer@1

# Docker image, Azure Container Registry, and Azure Functions app
# Build a Docker image, push it to an Azure Container Registry, and deploy it to an Azure Functions app.
# https://docs.microsoft.com/azure/devops/pipelines/languages/docker

trigger:
- master

resources:
- repo: self

variables:
  # ========================================================================
  #                          Mandatory variables 
  # ========================================================================

 # Update Azure.ResourceGroupName value with Azure resource group name.
  Azure.ResourceGroupName: '{{#toAlphaNumericString repositoryName 50}}{{/toAlphaNumericString}}'

  # Update Azure.ServiceConnectionId value with AzureRm service endpoint.
  Azure.ServiceConnectionId: '{{ azureServiceConnectionId }}'

  # Update Azure.Location value with Azure Location.
  Azure.Location: 'eastus'

  # Update ACR.Name value with ACR name. Please note ACR names should be all lower-case and alphanumeric only.
  ACR.Name: '{{#toAlphaNumericString repositoryName 46}}{{/toAlphaNumericString}}{{#shortGuid}}{{/shortGuid}}'
  
  # Update FunctionApp.Name value with a name that identifies your new function app. Valid characters are a-z, 0-9, and -.
  FunctionApp.Name: '{{#toAlphaNumericString repositoryName 46}}{{/toAlphaNumericString}}{{#shortGuid}}{{/shortGuid}}'
  
  # Update StorageAccount.Name value with Storage account name. Storage account names must be between 3 and 24 characters in length and use numbers and lower-case letters only.
  StorageAccount.Name: '{{#toAlphaNumericString repositoryName 20}}{{/toAlphaNumericString}}{{#shortGuid}}{{/shortGuid}}'
  
  # Update ServicePlan.Name value with a name of the app service plan.
  ServicePlan.Name: '{{#toAlphaNumericString repositoryName 45}}{{/toAlphaNumericString}}-plan'

  # ========================================================================
  #                           Optional variables 
  # ========================================================================

  ACR.ImageName: '$(ACR.Name):$(Build.BuildId)'
  ACR.FullName: '$(ACR.Name).azurecr.io'
  ACR.Sku: 'Standard'
  Azure.CreateResources: 'true' # Update Azure.CreateResources to false if you have already created resources like resource group and azure container registry.
  System.Debug: 'false'

jobs:

- job: CreateResources
  displayName: Create resources
  condition: and(succeeded(), eq(variables['Azure.CreateResources'], 'true'))

  pool:
    vmImage: 'ubuntu-latest'

  steps:
  - task: AzureResourceGroupDeployment@2
    displayName: 'Azure Deployment:Create Azure Container Registry, Azure WebApp Service'
    inputs:
      azureSubscription: '$(Azure.ServiceConnectionId)'
      resourceGroupName: '$(Azure.ResourceGroupName)'
      location: '$(Azure.Location)'
      templateLocation: 'URL of the file'
      csmFileLink: 'https://raw.githubusercontent.com/Microsoft/azure-pipelines-yaml/master/templates/resources/arm/functionapp.json'
      overrideParameters: '-registryName "$(ACR.Name)" -registryLocation "$(Azure.Location)" -functionAppName "$(FunctionApp.Name)" -hostingPlanName "$(ServicePlan.Name)" -storageAccountName "$(StorageAccount.Name)"'

- job: BuildImage
  displayName: Build
  dependsOn: CreateResources
  condition: or(succeeded(), ne(variables['Azure.CreateResources'], 'true'))

  pool:
    vmImage: 'ubuntu-latest'

  steps:
  - task: Docker@1
    displayName: 'Build an image'
    inputs:
      azureSubscriptionEndpoint: '$(Azure.ServiceConnectionId)'
      azureContainerRegistry: '$(ACR.FullName)'
      imageName: '$(ACR.ImageName)'
      command: build
      dockerFile: '**/Dockerfile'

  - task: Docker@1
    displayName: 'Push an image'
    inputs:
      azureSubscriptionEndpoint: '$(Azure.ServiceConnectionId)'
      azureContainerRegistry: '$(ACR.FullName)'
      imageName: '$(ACR.ImageName)'
      command: push

- job: DeployApp
  displayName: Deploy
  dependsOn: BuildImage
  condition: succeeded()

  pool:
    vmImage: 'ubuntu-latest'

  steps:
  - task: AzureFunctionAppContainer@1
    displayName: 'Azure Function App on Container Deploy: $(FunctionApp.Name)'
    inputs:
      azureSubscription: '$(Azure.ServiceConnectionId)'
      appName: $(FunctionApp.Name)
      imageName: '$(ACR.FullName)/$(ACR.ImageName)'

Add XamariniOS@2 task

# Xamarin.iOS
# Build a Xamarin.iOS project.
# Add steps that install certificates, test, sign, and distribute an app, save build artifacts, and more:
# https://docs.microsoft.com/azure/devops/pipelines/languages/xamarin

trigger:
- master

pool:
  vmImage: 'macos-latest'

steps:
# To manually select a Xamarin SDK version on the Microsoft-hosted macOS agent,
# configure this task with the *Mono* version that is associated with the
# Xamarin SDK version that you need, and set the "enabled" property to true.
# See https://go.microsoft.com/fwlink/?linkid=871629
- script: sudo $AGENT_HOMEDIRECTORY/scripts/select-xamarin-sdk.sh 5_12_0
  displayName: 'Select the Xamarin SDK version'
  enabled: false

- task: NuGetToolInstaller@1

- task: NuGetCommand@2
  inputs:
    restoreSolution: '**/*.sln'

- task: XamariniOS@2
  inputs:
    solutionFile: '**/*.sln'
    configuration: 'Release'
    buildForSimulator: true
    packageApp: false

Add task for AzureWebAppContainer@1

# Docker image, Azure Container Registry, and Azure Web App
# Build a Docker image, push it to an Azure Container Registry, and deploy it to an Azure Web App.
# https://docs.microsoft.com/azure/devops/pipelines/languages/docker

trigger:
- master

resources:
- repo: self

variables:
  # ========================================================================
  #                          Mandatory variables 
  # ========================================================================

 # Update Azure.ResourceGroupName value with Azure resource group name.
  Azure.ResourceGroupName: '{{#toAlphaNumericString repositoryName 50}}{{/toAlphaNumericString}}'

  # Update Azure.ServiceConnectionId value with AzureRm service endpoint.
  Azure.ServiceConnectionId: '{{ azureServiceConnectionId }}'

  # Update Azure.Location value with Azure Location.
  Azure.Location: 'eastus'

  # Update ACR.Name value with ACR name. Please note ACR names should be all lower-case and alphanumeric only.
  ACR.Name: '{{#toAlphaNumericString repositoryName 46}}{{/toAlphaNumericString}}{{#shortGuid}}{{/shortGuid}}'
  
  # Update Web.Name value with a name that identifies your new Web app. Valid characters are a-z, 0-9, and -.
  WebApp.Name: '{{#toAlphaNumericString repositoryName 46}}{{/toAlphaNumericString}}{{#shortGuid}}{{/shortGuid}}'
  
  # Update ServicePlan.Name value with a name of the app service plan.
  ServicePlan.Name: '{{#toAlphaNumericString repositoryName 45}}{{/toAlphaNumericString}}-plan'

  # ========================================================================
  #                           Optional variables 
  # ========================================================================
  
  ACR.ImageName: '$(ACR.Name):$(Build.BuildId)'
  ACR.FullName: '$(ACR.Name).azurecr.io'
  Azure.CreateResources: 'true' # Update Azure.CreateResources to false if you have already created resources like resource group and azure container registry.
  System.Debug: 'false'

jobs:

- job: CreateResources
  displayName: Create resources
  condition: and(succeeded(), eq(variables['Azure.CreateResources'], 'true'))

  pool:
    vmImage: 'ubuntu-latest'

  steps:
  - task: AzureResourceGroupDeployment@2
    displayName: 'Azure Deployment:Create Azure Container Registry, Azure WebApp Service'
    inputs:
      azureSubscription: '$(Azure.ServiceConnectionId)'
      resourceGroupName: '$(Azure.ResourceGroupName)'
      location: '$(Azure.Location)'
      templateLocation: 'URL of the file'
      csmFileLink: 'https://raw.githubusercontent.com/Microsoft/azure-pipelines-yaml/master/templates/resources/arm/webapp-on-containers.json'
      overrideParameters: '-registryName "$(ACR.Name)" -registryLocation "$(Azure.Location)" -imageName "$(ACR.ImageName)" -webAppName "$(WebApp.Name)" -hostingPlanName "$(ServicePlan.Name)"'

- job: BuildImage
  displayName: Build
  dependsOn: CreateResources
  condition: or(succeeded(), ne(variables['Azure.CreateResources'], 'true'))

  pool:
    vmImage: 'ubuntu-latest'

  steps:
  - task: Docker@1
    displayName: 'Build an image'
    inputs:
      azureSubscriptionEndpoint: '$(Azure.ServiceConnectionId)'
      azureContainerRegistry: '$(ACR.FullName)'
      imageName: '$(ACR.ImageName)'
      command: build
      dockerFile: '**/Dockerfile'

  - task: Docker@1
    displayName: 'Push an image'
    inputs:
      azureSubscriptionEndpoint: '$(Azure.ServiceConnectionId)'
      azureContainerRegistry: '$(ACR.FullName)'
      imageName: '$(ACR.ImageName)'
      command: push

- job: DeployApp
  displayName: Deploy
  dependsOn: BuildImage
  condition: succeeded()

  pool:
    vmImage: 'ubuntu-latest'

  steps:
  - task: AzureWebAppContainer@1
    displayName: 'Azure Web App on Container Deploy: $(WebApp.Name)'
    inputs:
      azureSubscription: '$(Azure.ServiceConnectionId)'
      appName: $(WebApp.Name)
      imageName: '$(ACR.FullName)/$(ACR.ImageName)'

Resolve unexpected null reference exception

This should work, but throws an error:

Unexpected error: System.NullReferenceException: Object reference not set to an instance of an object.
at AzurePipelinesToGitHubActionsConverter.Core.Conversion.StepsProcessing.GetStepInput(Step step, String name)
at AzurePipelinesToGitHubActionsConverter.Core.Conversion.StepsProcessing.CreatePublishBuildArtifactsStep(Step step)
at AzurePipelinesToGitHubActionsConverter.Core.Conversion.StepsProcessing.ProcessStep(Step step)
at AzurePipelinesToGitHubActionsConverter.Core.Conversion.PipelineProcessing2.ProcessSteps(Step[] steps, Boolean addCheckoutStep) at AzurePipelinesToGitHubActionsConverter.Core.Conversion.PipelineProcessing2.ProcessPipeline(AzurePipelinesRoot2 azurePipeline, String[] simpleTrigger, Trigger complexTrigger, Dictionary2 simpleVariables, Variables[] complexVariables)
at AzurePipelinesToGitHubActionsConverter.Core.Conversion.Conversion.ConvertAzurePipelineToGitHubAction(String input)
at PipelinesToActionsWeb.Controllers.HomeController.ProcessConversion(String input) in D:\a\AzurePipelinesToGitHubActionsConverterWeb\AzurePipelinesToGitHubActionsConverterWeb\PipelinesToActions\PipelinesToActions\Controllers\HomeController.cs:line 44

# HTML
# Archive your static HTML project and save it with the build record.
# Add steps that build, run tests, deploy, and more:
# https://aka.ms/yaml

trigger:
- master

pool:
  vmImage: 'ubuntu-latest'

steps:
- task: ArchiveFiles@2
  inputs:
    rootFolderOrFile: '$(build.sourcesDirectory)'
    includeRootFolder: false
- task: PublishBuildArtifacts@1

Add NodeTool@0 task

# Node.js
# Build a general Node.js project with npm.
# Add steps that analyze code, save build artifacts, deploy, and more:
# https://docs.microsoft.com/azure/devops/pipelines/languages/javascript

trigger:
- master

pool:
  vmImage: 'ubuntu-latest'

steps:
- task: NodeTool@0
  inputs:
    versionSpec: '10.x'
  displayName: 'Install Node.js'

- script: |
    npm install
    npm run build
  displayName: 'npm install and build'

Add support for trigger types

    trigger:
      batch: true
      branches:
        include:
        - features/*
        exclude:
        - features/experimental/*
      paths:
        exclude:
        - README.md

Add support for Xcode@5 and CocoaPods@0 tasks

Azure DevOps schema

# Xcode
# Build, test, or archive an Xcode workspace on macOS. Optionally package an app.
- task: Xcode@5
  inputs:
    #actions: 'build' 
    #configuration: '$(Configuration)' # Optional
    #sdk: '$(SDK)' # Optional
    #xcWorkspacePath: '**/*.xcodeproj/project.xcworkspace' # Optional
    #scheme: # Optional
    #xcodeVersion: 'default' # Optional. Options: 8, 9, 10, default, specifyPath
    #xcodeDeveloperDir: # Optional
    packageApp: 
    #archivePath: # Optional
    #exportPath: 'output/$(SDK)/$(Configuration)' # Optional
    #exportOptions: 'auto' # Optional. Options: auto, plist, specify
    #exportMethod: 'development' # Required when exportOptions == Specify
    #exportTeamId: # Optional
    #exportOptionsPlist: # Required when exportOptions == Plist
    #exportArgs: # Optional
    #signingOption: 'nosign' # Optional. Options: nosign, default, manual, auto
    #signingIdentity: # Optional
    #provisioningProfileUuid: # Optional
    #provisioningProfileName: # Optional
    #teamId: # Optional
    #destinationPlatformOption: 'default' # Optional. Options: default, iOS, tvOS, macOS, custom
    #destinationPlatform: # Optional
    #destinationTypeOption: 'simulators' # Optional. Options: simulators, devices
    #destinationSimulators: 'iPhone 7' # Optional
    #destinationDevices: # Optional
    #args: # Optional
    #workingDirectory: # Optional
    #useXcpretty: true # Optional
    #publishJUnitResults: # Optional

Also include CocoaPods@0

Add Gradle@2 task

Currently this doesn't have a task conversion

# Android
# Build your Android project with Gradle.
# Add steps that test, sign, and distribute the APK, save build artifacts, and more:
# https://docs.microsoft.com/azure/devops/pipelines/languages/android

trigger:
- master

pool:
  vmImage: 'macos-latest'

steps:
- task: Gradle@2
  inputs:
    workingDirectory: ''
    gradleWrapperFile: 'gradlew'
    gradleOptions: '-Xmx3072m'
    publishJUnitResults: false
    testResultsFiles: '**/TEST-*.xml'
    tasks: 'assembleDebug'

Add automated builds that can validate that the conversion works in real time.

Perhaps I can create a separate integration test that generates some scripts similar to the unit tests, but then commits them to the repo and runs them as part of the pull request build validation.

This would require:

  • The ability to commit to the current/another repo as part of a GitHub Action CI pipeline
  • The ability to have the pull request integration build wait for the builds deployed to the repo to complete

Schedules not converting

Azure Pipeline code:

schedules:
- cron: "0 0 * * *"

GitHub Actions code:

on:
  schedule:
    # * is a special character in YAML so you have to quote this string
    - cron:  '*/15 * * * *'

Bug: Functional tests not displaying on multiple lines correctly

Pipelines YAML:
- task: VSTest@2
displayName: 'Run functional smoke tests on website and web service'
inputs:
searchFolder: '$(build.artifactstagingdirectory)'
testAssemblyVer2: |
**\FeatureFlags.FunctionalTests\FeatureFlags.FunctionalTests.dll
uiTests: true
runSettingsFile: '$(build.artifactstagingdirectory)/drop/FunctionalTests/FeatureFlags.FunctionalTests/test.runsettings'

Actions YAML: (all on one line)

  • name: Run functional smoke tests on website and web service
    run: " |\n $vsTestConsoleExe = "C:\\Program Files (x86)\\Microsoft Visual Studio\\2019\\Enterprise\\Common7\\IDE\\Extensions\\TestPlatform\\vstest.console.exe"\n $targetTestDll = "**\FeatureFlags.FunctionalTests\FeatureFlags.FunctionalTests.dll\n"\n $testRunSettings = "/Settings:\"${GITHUB_WORKSPACE}/drop/FunctionalTests/FeatureFlags.FunctionalTests/test.runsettings" "\n $parameters = " -- TestEnvironment="Beta123" ServiceUrl="https://featureflags-data-eu-service-staging.azurewebsites.net/\" WebsiteUrl="https://featureflags-data-eu-web-staging.azurewebsites.net/\" "\n #Note that the \" is an escape character to quote strings, and the & is needed to start the command\n $command = "& "$vsTestConsoleExe\" "$targetTestDll`" $testRunSettings $parameters " \n Write-Host "$command"\n Invoke-Expression $command\n "
    shell: powershell

Use versions for actions

When using actions it is best practice NOT to use @master versioning. For the upload/download artifacts you should use a tagged version like @v2

Bug: Deploy website task does not seem to be populating properties

Azure DevOps YAML:
- task: AzureRmWebAppDeployment@3
displayName: 'Azure App Service Deploy: web site'
inputs:
azureSubscription: 'SamLearnsAzure connection to Azure Portal'
WebAppName: $(WebsiteName)
DeployToSlotFlag: true
ResourceGroupName: $(ResourceGroupName)
SlotName: 'staging'
Package: '$(build.artifactstagingdirectory)/drop/FeatureFlags.Web.zip'
TakeAppOfflineFlag: true
JSONFiles: '**/appsettings.json'

Actions YAML:
- name: 'Azure App Service Deploy: web site'
uses: Azure/webapps-deploy@v1
with:
app-name:
package:
slot-name:

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.