3

I would like to setup continuous deployment from a GitLab repository to an Azure App using a PowerShell script and the Azure CLI. There is already an answer for doing this using the Azure RM module and Windows PowerShell, but as these are now deprecated, I am looking specifically for a solution that uses the new Az module and PowerShelll Core.

The solution should give a a PowerShell (Core) script to setup a Continuous Deployment directly from GitLab to Azure. It must make use of the Az module. Once the setup script is run, each subsequent commit/merge to the GitLab repository should then automatically be deployed to Azure. Preferably, this PowerShell script should work for both public and private repositories that are hosted on GitLab, but I'm willing to accept solutions that only work on public repositories.

Tangiest
  • 43,737
  • 24
  • 82
  • 113
  • Note, for eveyone voting to close, I've asked this question as Windows Powershell and the Azure RM module are being deprecated in favour of PowerShell Core and the new Az module (using the Azure CLI). I've created this new question asking specificially for a canonical answer using the Azure CLI and Powershell Core. I plan on offering a bounty for this question when it is open to me in 2 days. Thanks. – Tangiest Dec 17 '18 at 10:57
  • @rickvdbosch This question is created to give a canonical answer for future Azure development using PowerShell Core and the new Az module (using the Azure CLI). I've already got an answer for my specific needs at https://stackoverflow.com/a/53729332/35483, and have just awarded a bounty for it.If there is an issue with me asking this specific question, I'm happy to close. – Tangiest Dec 17 '18 at 10:59
  • Did you figure out how to set automatic deployment on commit? The answer from the previous question look the same as the github sample, does it work with gitlab now? – Mike Twc Dec 18 '18 at 17:07
  • Hi, any update this issue? – Joy Wang Dec 19 '18 at 00:59
  • @MikeTwc sorry, not enough space in my initial comment to mention that as there is no further development taking place in the PowerShell AzureRM module, it will never be possible to setup an automated CI to a GitLab repository in Azure using it. The only way to script this is using the Azure CLI (PowerShell Az module), as in the answer by Joy Wang below. – Tangiest Dec 19 '18 at 12:16
  • @JoyWang sorry, I'm not too sure what you mean by updates? Do you need additional information for your answer? – Tangiest Dec 19 '18 at 12:17
  • @MikeTwc no, the answer is identical to the script at https://docs.microsoft.com/en-gb/azure/app-service/scripts/powershell-deploy-github?toc=%2fpowershell%2fmodule%2ftoc.json It will only setup your web app with the code from the Git repository, but will not automatically deploy on further commits. You have 2 options - either rebuild the web app (in a different deployment slot ) to pull in any further commits, or manually sync the latest commits in the Azure Portal's Deployment Center blade. It is possible to setup an automated CI with GitLab using the Azure CLI, hence this new question. – Tangiest Dec 19 '18 at 12:18
  • I mean if my soluation works or not? – Joy Wang Dec 19 '18 at 13:31
  • @JoyWang thanks for clarifying. I haven't yet had a chance to test it - I'll do so at some point today and update you. – Tangiest Dec 19 '18 at 13:34
  • well, I believe it will work, wait for you.;-) – Joy Wang Dec 19 '18 at 13:38

2 Answers2

1

Try the command below for Az, my repository is public, it works fine on my side.

$gitrepo="your git repository url"
$webappname="joyazapp"
$location="centralus"

New-AzResourceGroup -Name joyazgroup -Location $location

New-AzAppServicePlan -Name joyazplan -Location $location -ResourceGroupName joyazgroup -Tier Free

New-AzWebApp -Name joyazapp -Location $location -AppServicePlan joyazplan -ResourceGroupName joyazgroup

$PropertiesObject = @{
    repoUrl = "$gitrepo";
    branch = "master";
    isManualIntegration = $false
}

Set-AzResource -PropertyObject $PropertiesObject -ResourceGroupName joyazgroup -ResourceType Microsoft.Web/sites/sourcecontrols -ResourceName $webappname/web -ApiVersion 2018-02-01 -Force
Joy Wang
  • 39,905
  • 3
  • 30
  • 54
  • OK, I've finally got around to testing this answer (apologies for the delay), and the given solution DOESN'T work for GitLab hosted repositories. It errors on the Set-AzResource line, with the error message 'The parameter https://gitlab.com/MagicAndi/geekscode.net.git has an invalid value'. It will work if the isManualIntegration property is set to false, but in this case, it will not automatically deploy further commits to the GitLab repo to the web application in Azure. This mirrors the behaviour of the legacy AzureRM Set-AzureRmResource cmdlet. If you need further info, please let me know. – Tangiest Dec 24 '18 at 23:46
  • @MagicAndi Not sure why the `isManualIntegration` not work with GitLab, could you accept to use GitHub? – Joy Wang Dec 25 '18 at 02:34
  • Sorry, no. I had previously been mirroring my GitLab repository in GitHub and automatically deploying to Azure from there (see details of question https://stackoverflow.com/questions/52664359/deploy-code-from-gitlab-repository-to-azure-web-app-using-powershell). This question is meant to produce a canonical answer for setting up a CI to Azure from GitLab hosted repositories, using PowerShell and the Azure CLI. – Tangiest Dec 25 '18 at 12:00
1

I was playing around with gitlab and kudu rest APIs, and figured out how to automate manual solution you mentioned. The only extra step is to add gitlab api token to your code, but you just do it once for all projects. You can get it from your gitlab account settings under "Access Tokens". Some other notes:

To interact with kudu api the script is using autogenerated deployment credentials. But you can create a separate user for deployment and use it in all other projects (skipping that step). You can do it in azure CLI:

az webapp deployment user set --user-name someUser --password somepassword

GitLab API is using project ID, not the project name. The script is trying to retrieve project id automatically from repo URL, but you might copy/paste it from the project general setting on gitlab to be safe.

This solution works with private repos too. The only thing you'll see some error while creating a resource (because ssh key is not set up yet). But after script is completed it should be fine, so ignore the error. For public repos you can skip that key set up stuff at all

Here is the script:

function log {param($memo); Write-Host "[$((get-date).ToString("HH:mm:ss"))]: $memo" -ForegroundColor Green}

# =============== App and GitLab settings ==============


$webapp="geekscodeStackOverflow"
$resgroup = $webapp + "Group"
$plan = $webapp + "Plan"
$location="centralus"

$gitToken = "yourGitLabTokenHere"  
$repoUrl = "https://gitlab.com/MagicAndi/geekscode.net"
# $projID =  "99..."



# ============== DEPLOYMENT SCRIPT ==========================#

log "Setting up the app on azure"

New-AzResourceGroup -Name $resgroup -Location $location
New-AzAppServicePlan -Name $plan -Location $location -ResourceGroupName $resgroup -Tier Free
New-AzWebApp -Name $webapp -Location $location -AppServicePlan $plan -ResourceGroupName $resgroup

$appInfo = Get-AzWebApp -Name $webapp
$appRef = @{Name=$appInfo.Name; ResourceGroupName = $appInfo.ResourceGroup}
if(!$appInfo){Write-Host "app deployment failed" -ForegroundColor Red; return} else {Write-Host "App created:" -ForegroundColor Green}


# ================= linking web app to gitlab ========================= 
# you can do this manually: app dashboard / Deployment Centrer / External / App Service Kudu / git

log "setting up deployment "

$deployment = @{
  PropertyObject = @{ repoUrl = $repoUrl; branch = "master"; isMercurial= $false; isManualIntegration = $true }
  ResourceGroupName = $appInfo.ResourceGroup
  ResourceType = "Microsoft.Web/sites/sourcecontrols"
  ResourceName = $appInfo.Name + "/web"
  ApiVersion = "2018-02-01"
}

# you'll get error on this step for private repos because the key is not set up yet. You can ignore that error
Set-AzResource @deployment -Force

log "Extracting Deployment credentials"
# you can also create a user credentials in AZ CLI and skip this or manually get it in App's deployment center
$prof = Get-AzWebAppPublishingProfile @appRef | Select-Xml -XPath "//*[@publishMethod='MSDeploy']"
$deployCreds = $prof.node.userName + ":" + $prof.node.userPWD


log "Extracting Deployment key"
# Can skip for public repors
$keyUrl = "https://$webapp.scm.azurewebsites.net/api/sshkey?ensurePublicKey=1"
$base64AuthInfo = [Convert]::ToBase64String([Text.Encoding]::ASCII.GetBytes($deployCreds))
$head = @{Authorization=("Basic {0}" -f $base64AuthInfo)}
$deployKey =  Invoke-RestMethod -Uri $keyUrl -Headers $head -Method Get


#============== Setting Up GIT LAB ================ #

$gitApi = "https://gitlab.com/api/v4"
$gitHead = @{'PRIVATE-TOKEN'= $gitToken; 'Content-Type'='application/json'} 

# looking up project id by user/repo name. You can skip that and get the id from project general setting on GitLab
$repo = $repoUrl.Split("/")[-2,-1] -join "%2F"
$project = Invoke-RestMethod -Uri "$gitApi/projects/$repo" -Headers $head
$projID = $project.id
log "Setting up $repoUrl (project id $projID)"

# --- Adding deploy key to GitLab project (public repos can skip) ---
# You can copy the key manually - Go to Project / Settings / Repository / Deploy Keys
log "Adding deploy keys to GitLab project"
$keyBody = @{title="Azure_Key";key=$deployKey; can_push=$true} | ConvertTo-Json
Invoke-RestMethod "$gitApi/projects/$projID/deploy_keys/" -Headers $gitHead -Body $keyBody -Method Post

log "Setting up a webhook"
# this can be set manualy - go to Project / Settings / Integrations.
$whBody = @{url = "https://$deployCreds@$webapp.scm.azurewebsites.net/deploy"} | ConvertTo-Json
Invoke-RestMethod -Uri "$gitApi/projects/$projID/hooks/" -Headers $gitHead -Body $whBody -Method Post

log "deployment completed `ncheck out your app at https://$webapp.azurewebsites.net"
Mike Twc
  • 2,230
  • 2
  • 14
  • 19
  • Hi, sorry for the delay in replying. Just to confirm that I've tested the code for a public repository, and it successfully sets up a CI from GitLab to Azure. I'm currently testing for a private repository. – Tangiest Dec 25 '18 at 12:57
  • Just to confirm that I've accepted this solution as the answer, and awarded you the bounty. Thanks for your help. The given code works fine for a public repo, but is failing for me for a private repository, with the web hook giving the error message 'Hook execution failed: Net::ReadTimeout' when I test it in GitLab (Project > Settings > Integrations). I'm still looking into this. – Tangiest Dec 25 '18 at 15:34
  • Ignore my last. After a few hours, this started working successfully. No idea why it wasn't working initially, or why it has decided to work now. Can confirm that for both public and private repositories, the web hook automatically deploys the latest code to Azure. – Tangiest Dec 25 '18 at 17:16