Azure Devops - run build only in the folder that have changes - azure

I have a some spark jobs which are written on scala and build using maven.
Right now the follow a path like this
/src/job1/<<build data>>
/src/job2/<<build data>>
.....
This build data holds the code, pom.xml, tests and other thinks needed for each job pass to maven.
We have a root folder that has a father pom.xml that builds all the code, but I don't want to build all the code every time. I want to be able to test and build only the code for the jobs that changes.
The only way that I think is possible is to run build an tests only in the folders that changes was detected but I can't seem to do that without create one azure devops build for each folder, any ideas?
TL:DR - How to pass the path of folder that have changes in azure devops to the build process?

How to pass the path of folder that have changes in azure devops to the build process?
We could add a powershell scripts to check the folder or path, like:
$editedFiles = git diff HEAD HEAD~ --name-only
echo "$($editedFiles.Length) files modified:"
$editedFiles | ForEach-Object {
echo $_
Switch -Wildcard ($_ ) {
'/src/job1' {
Write-Output "##vso[task.setvariable variable=job1]True"
}
'/src/job2' {
Write-Output "##vso[task.setvariable variable=job2]True" }
}
}
This script sets variables which are then referenced in custom conditions in the pipeline build task or in the build pipeline:
and(succeeded(), eq(variables['job1'], 'True'))
You could check this similar thread for some details.
Hope this helps.

You can work around this by creating a script that will do the following:
Get the changeset/commit in the build to check which files are changed.
Based on the files changes, you define the logic to decide which folder it should build, run tests, etc.
This solution will require you to build all the logic to decide which folders to build and test.

Thanks for your inputs. I was able to do it with your inputs on git, I realized that we are using gitflow workflow and every time that we have pull request to the master branch (meaning deployment) a commit is created with starting "Merged PR", this way I can compare the latest two commits and check what changed.
How I'm doing:
# This part uses this to get the latest two pull requests hashes
$last_pr_commit=git log --grep="^Merged PR" -n 1 --pretty=format:"%h" --abbrev=200
$second_last_pr_commit=git log -n 1 --grep="^Merged PR" --oneline --abbrev=200 $last_pr_commit^...HEAD~2 --pretty=format:"%h"
# This get the path of the files
$result=git diff $last_pr_commit $second_last_pr_commit --name-only
And then I just build the ones that I'm interested.
ForEach ($line in $($result -split "`r`n"))
{
# In my case I only need the two first parts of path
$folderPath=$line.split('/')[0]+'/'+$line.split('/')[1]
if ($line.contains('.scala')){
# Running the tests and packaging
mvn package $folderPath
}
}
This is powershell but it can work with bash changing the for loop.
Thanks

Related

How to modify the repository / storage location for Test Results in azure pipeline

For one of my project the TestResults.zip file is publishing on url https://dev.azure.com/MyProject/Project/_TestManagement/Runs?runId=8309822&_a=runCharts.
I want to change storage location for TestResults.zip file from above given URL to my own defined repository location.(Like: Myproject/target/surefire-reports.zip) How to do that?
Because in my azure pipeline the test are running and when it comes to create a zip for TestResults it's storing in given above URL and i want to store in one of my project sub-module under target directory so that i can create a zip file.
Please help me to resolve this issue.
Many Thanks
How to modify the repository / storage location for Test Results in azure pipeline
It is not recommended to publish the test results to the repo.
If you still want do that, you could use git command line to submit the test file to the repo in the pipeline after the test task, like:
cd $(System.DefaultWorkingDirectory)
copy Path\surefire-reports.zip target
cd target
git add surefire-reports.zip
git commit -m "Add a test file"
git push https://PATn#dev.azure.com/YourOrganization/YourProject/_git/xxx.test HEAD:master
You could check the similar thread for some more details.

Gitlab CI to deliver files to a remote server (rsync)

I'm working with SVN but I would like to move on to Git, and more specifically to Gitlab.
I have the following structure:
MyStructure/
customer/
client1/
delivery.sh
MyFiletoSend.sh
client2/
delivery.sh
MyFiletoSend2.sh
Currently, the "delivery.sh" will send the modifications (rsync) of the file "MyFiletoSend.sh" to the server "client1".
Can I run the "delivery.sh" via Gitlab automatically after/before the git push only on the files modified in this push?
Example:
I have a modification to make to the file "MyFiletoSend.sh" from client1/
I make my change
commit and push
Gitlab is running "delivery.sh" on my "client1/" file.
The file "MyFiletoSend.sh" is sent to the server of "client1" without touching "client2".
Yes, it is possible
but first of all you need to understand how gitlab ci works. Read this article https://docs.gitlab.com/ee/ci/yaml/
You will create a step in your pipeline that will do what you want after you push the code (in master or in any other branch/mr)
and about the job? you have to create one, you can use this code to help you
https://gist.github.com/hnlq715/6c222ba0fd868bae7e4dfd3af61bf26e
Assuming your delivery.sh scripts have all the rsync logic required, GitLab has built-in logic to detect changes in files and execute bash commands in response. You can create a separate job for each client, which can run in parallel in the same stage. This approach is also auditable in that it will clearly show you which clients got updated and with which version of the file.
update-client-1:
stage: update-clients
only:
changes:
# Detect change only in MyFiletoSend.sh:
- customer/client1/MyFiletoSend.sh
# Detect any change in the customer folder:
- customer/client1/*
script:
- cd customer/client1
- delivery.sh
update-client-2:
stage: update-clients
only:
changes:
- customer/client2/*
script:
- cd customer/client2
- delivery.sh
# repeat for all remaining clients
For more information: https://docs.gitlab.com/ee/ci/yaml/#onlychangesexceptchanges

GitLab CI Yocto Build - How to use SSTATE and DL_DIR

How to configure GitLab CI to store the SSTATE_DIR and the DL_DIR between several jobs? Currently, bitbake rebuilds the complete project every time, which is very time consuming. So i would like to use the sstage again. I tried caching, but building time increases effectively, due to the big zip/unzip overhead.
I don't even need a shared sstate between several projects, just a method to store the output between jobs.
I'm using Gitlab 11.2.3 with a shell executor as runner.
Thanks a lot!
In version 11.10, GIT_CLEAN_FLAGS was added, which could be used to achieve what you want to do with the shell executor.
For completeness: when using the docker executor, this can be achieved by using docker volumes, which are persistent across builds.
If you're only using one runner for this, you could potentially use GIT_STRATEGY: none, which would re-use the project workspace for the following job; relevant documentation. However, this wouldn't be extremely accurate in case you have multiple jobs running which requires the runner, as it could dilute the repository, if jobs are started from across different pipelines.
Another way, if you're still using one runner, is you could just copy the directories out and back into the job you require.
Otherwise, you may potentially be out of luck, and have to wait for the sticky runners issue.
You can reuse a shared-state cache between jobs simply as follows:
Specify the path to the sstate-cache directory in the .yml file of your
gitlab-ci pipeline. An example fragment from one of mine:
myrepo.yml
stages:
...
...
variables:
...
TCM_MACHINE: buzby2
...
SSTATE_CACHE: /sstate-cache/$TCM_MACHINE/PLAT3/
PURGE_SSTATE_CACHE: N
...
In my case /sstate-cache/$TCM_MACHINE/PLAT3/ is a directory in the docker container
that runs the build. This path is mounted in the docker container from a
permanent sstate cache directory on the build-server's filesystem, /var/bitbake/sstate-cache/<machine-id>/PLAT3.
PURGE_SSTATE_CACHE is overridable by a private variable
in the pipeline schedule settings so that I can optionally delete the cache for a squeaky clean
build.
Ensure that the setting of SSTATE_CACHE is appended to the bitbake conf/local.conf
file of the build, e.g.
.build_image: &build_image
stage: build
tags:
...
before_script:
...
script:
- echo "SSTATE_DIR ?= \"$SSTATE_CACHE\"" >> conf/local.conf
...
Apply the same pattern to DL_DIR if you use it.
Variables you use in the .yml file can be overriden by gitlab-ci trigger
or schedule variables. See Priority of variables

Having nested pipelines in the same repository

I am working on a micro-services project, each service has its own pipeline because it gets deployed to a server of its own, we have each project in its own repository on gitlab with its own .gitlab-ci.yml but I want to collect all of these services in a single repository to make them easier to maintain and trigger a deployment of all the services when a commit is pushed.
The issue is I don't want to have a big fat yaml file that contains the build & deployment process of each service but instead keep the yaml files in the services folders and have a yaml file on the root that references them, i.e.:
| service1
| service1-code
| .gitlab-ci.yaml << build process for service1
| service2
| service2-code
| .gitlab-ci.yaml << build process for service2
| .gitlab-ci.yaml << reference to service1/yaml & service2/yaml
Is that doable?
There is currently no way for GitLab to do this, and there is an open issue to add this feature for monorepos.
(...) keep the yaml files in the services folders and have a yaml file on the root that references them
Just found this comment on GitLab by robindegen.
We create separate repositories, and a parent main repository that has
them as submodules. This works just fine for doing CI on subsets. When
we push to master on the main repo (to update the submodules), a full
CI run is done on everything, including integration tests.
I recon a CI clone includes submodules so this would just work. So if you already have a repo per project; have your cake and eat it too!

GitLab CI/CD pull code from repository before building ASP.NET Core

I have GitLab running on computer A, development environment (Visual studio Pro) on computer B and Windows Server on computer C.
I set up GitLab-Runner on computer C (Windows server). I also set up .gitlab-ci.yml file to perform build and run tests for ASP.NET Core application on every commit.
I don't know how can I get code on computer C (Windows server) so I can build it (dotnet msbuild /p:Configuration=Release "%SOLUTION%"). It bothers me that not a single example .gitlab-ci.yml I found on net, doesn't pull code form GitLab, before building application. Why?
Is this correct way to set-up CI/CD:
User create pull request (a new branch is created)
User writes code
User commit code to branch from computer B.
GitLab runner is started on computer C.
It needs to pull code from current branch (CI_COMMIT_REF_NAME)
Build, test, deploy ...
Should I use common git command to get the code, or is this something GitLab runner already do? Where is the code?
Why no-one pull code from GitLab in .gitlab-ci.yml?
Edited:
I get error
'"git"' is not recognized as an internal or external command
. Solution in my case was restart GitLab-Runner. Source.
#MilanVidakovic explain that source is automatically downloaded (which I didn't know).
I just have one remaining problem of how to get correct path to my .sln file.
Here is my complete .gitlab-ci.yml file:
variables:
SOLUTION: missing_path_to_solution #TODO
before_script:
- dotnet restore
stages:
- build
build:
stage: build
script:
- echo "Building %CI_COMMIT_REF_NAME% branch."
- dotnet msbuild /p:Configuration=Release "%SOLUTION%"
except:
- tags
I need to set correct variable for SOLUTION. My dir (where GitLab-Runner is located) currently holds this folder/files:
- config.toml
- gitlab-runner.exe
- builds/
- 7cab42e4/
- 0/
- web/ # I think this is project group in GitLab
- test/ # I think this is project name in GitLab
- .sln
- AND ALL OTHER PROJECT FILES #Based on first look
- testm.tmp
So, what are 7cab42e4, 0. Or better how to get correct path to my project structure? Is there any predefined variable?
Edited2:
Answer is CI_PROJECT_DIR.
I'm not sure I follow completely.
On every commit, Gitlab runner is fetching your repository to C:\gitlab-runner\builds.. on the local machine (Computer C), and builds/deploys or does whatever you've provided as an action for the stage.
Also, I don't see the need for building the source code again. If you're using Computer C for both runner and tests/acceptance, just let the runner do the building and add Artifacts item in your .gitlab-ci.yaml. Path defined in artifacts will retain your executables on Computer C, which you are then able to use for whatever purposes.
Hope it helps.
Edit after comment:
When you push to repository, Gitlab CI/CD automatically checks your root folder for .gitlab-ci.yaml file. If its there, the runner takes over, parses the file and starts executing jobs/stages.
As soon as the file itself is valid and contains proper jobs and stages, runner fetches the latest commit (automatically) and does whatever script item tells it to do.
To verify that everything works correctly, go to your Gitlab -> CI / CD -> Pipelines, and check out whats going on. You should see something like this:
Maybe it would be best if you posted your .yaml file, there could be a number of reasons your runner is not picking up the code. For instance, maybe your .yaml tags are not matching what runner is created to pick up etc.

Resources