How to not run dependent plan if changeset does not match 'include file' in repository settings
Asked by Pavel Matyska:

Hi,

We have a repository which contains partially dependent projects. Lets say ProjectBase, ProjectA and ProjectB, ProjectA references ProjectBase and ProjectB also references ProjectBase, but ProjectA and ProjectB are otherwise independent. We need to compile all projects together due to these references, but we need to test them separately. This means, when changes occur on ProjectA, we do not need and do not want to run test for ProjectB, we need to run tests for ProjectA only.

We come up with the solution using dependent Bamboo plans. First plan checks out code from repository and compiles all projects with their test projects and publishes them in an artifact. Then we have plans that run tests for specific projects, one plan for ProjectA tests and one plan for ProjectB tests. These plans consume that artifact and use the compilation output of the first plan. They do not need to checkout the repository again, everything is contained in the artifact. The repository is rather large and we want to check it out as few as possible. We set same repository for the test plan to ensure that it will test same changesets as the compilation plan.

How can we run the test plans according to a changeset that runs a compilation plan? We observed that when the changeset is in ProjectA, plan for ProjectB correctly has no changeset listed in 'Commits' tab, but since it is a child plan of the compilation plan, it still got triggered and run jobs for that project.

Note: blocking test plans/waiting for the compilation plan to complete works as expected. For simplicity I describe the problem using only three projects, but we have about 15 projects in that repository, so it is crucial for us to run only tests that matter at the moment of a commit. Obviously, when the changeset is in ProjectBase, it triggers all test plans, there is no way around it.

*Note 2: Sorry for possible duplicity, I asked about hour before but I cannot find the question in question list any more.*


Answers:
author: Daniel Santos
body: Hi [@Pavel Matyska](/t5/user/viewprofilepage/user-id/1298719)

Your description led me to think that things could be configured upsidedown.  
When I think in dependencies this is the scenario I imagine:

* ProjectBase is a library
* ProjectA is another library or app that uses what is produced by ProjectBase
* ProjectB is another library or app that uses what is produced by ProjectBase

In this example, there is no reason to avoid building ProjectA or ProjectB, unless you don't want to update one of them anymore. This could be easily solved by removing the dependency configuration and adding a scheduled trigger.

In your project, I have the impression that the big package should be the child of the 15 plans. It would be triggered any time you had a trigger in any of those plans.

Regarding the repository size, have you tried to use shallow clones?  
Are you using remote agents or local agents to build your plans?  

Bamboo uses cached repositories and this should save the checkout time. It would be just a matter of copying the differences.

I guess that if you can explain why you need ProejctBase to be the parent of the 15 plans it will help me to think on a different approach of solving it. Using dependencies does not seem the best option for you. We can't conditionally decide what child will be triggered or not. Maybe using the [Pre-Post Build Command Runner](https://marketplace.atlassian.com/apps/5581/pre-post-build-command-runner?hosting=server&tab=overview) in conjunction with this configuration, but I never tried that before.

comments: author: Pavel Matyska
body: Hi Daniel,

Maybe I described it wrong. We need to compile all projects together, ProjectBase, ProjectA and ProjectB. Since we use NUnit to test our libraries we need to compile our test libraries together with our project libraries in the compilation step. In compilation step we also run obfuscation, which is time consuming and we would like to perform it as less as possible. Output of all projects is obfuscated and then packed to an archive. Then we (would) have plans for each projecs that runs its tests. So one compilation plan and many test plans.

Our needs are:

Use case 1:

Change is made in ProjectX. For (possible) simplicity, compile ALL projects and compile ALL test libraries. Then run tests for ProjectX only.

Use case 2:

Change is made in ProjectBase. Compile all projects and compile all test libraries. Then run tests for each project.

Let me stop explaining our needs in this example and use our real projects and their purpose, it will be clearer to understand.

We are working on many network protocol clients, which we publish as libraries (.dll). For example we have clients for SFTP protocol, HTTP protocol, IMAP protocol and many others. Each client is in its own library. So when we update one client, lets say SFTP, we do not want to run tests for HTTP or IMAP clients. We also have shared functionality of handling certificates or using network sockets. These functionalities are in other libraries (in my example this was ProjectBase), so when we change one of this shared functionality, we need to test those shared libraries and all clients as well so we make sure that, SFTP, HTTP, IMAP, and so on, still works as we expect. In this case, we need to run all tests for all libraries we have. What I described in this whole paragraph we do not know how to achieve.

Also it is more complicated from disk usage point of view. We compile each client on many platforms, .NET 4.5, Android, iOS, .NET Standard, and some other platforms. For each platform we generate a solution from our code base and this solution is then compiled. Then we need to obfuscate all libraries for each platform together. These steps grow the working directory from clean and freshly cloned repository, which is about 300 MB, to at least 2-4 GB. This is why we would like to clone our repository to one working directory only and our attempt was to use artifacts instead of cloning full repository again. If each working directory for each library has those 4 GB, that will be at least 60 GB per branch. We manage to pick up and pass about 100 MB of libraries and other necessary files (configuration, build scripts and tools to run our tests) rather than 300 MB of freshly cloned repository. This 100 MB will not grow so much. What we know is that each bamboo job has its own working directory, so we still need to use build artifacts in some form. If we can work with one compilation and then use the artifact on all test jobs, we can narrow the disk space under 20 GB.  
We are using local agents. We already have our own tools to run tests on remote machines, so we need Bamboo as a compilation and test orchestration server.

Your note that we think this upside down can be more than true. We are new to bamboo, we are currently using CCNet. What we have now is many clones of our repository, for each protocol client one and it is really disk space consuming. What we expect from switching to bamboo is less disk usage, quicker test completion by using parallel execution of jobs and ability to easily create plans for feature branches.

Thank you in advance for your response.

Pavel


author: Daniel Santos
body: Hi [@Pavel Matyska](/t5/user/viewprofilepage/user-id/1298719)  

I think the sequence is correct. In my opinion (If I understood you correctly) this scenario is caused by:

1. Your subsequent projects are not self-contained due to the disk space restriction, requiring that ProjectBase is run every time to compile their code.
2. Bamboo has no feature for conditionally running dependent plans

What I see that could work (as a workaround):

1. Moving your subsequent plans to the main one. All of them as parallel jobs in the same stage
2. Configure your tests to be parallel jobs in the last stage.
3. Each job using a script task to call the tests.  
   This script will check variables to know if they should run or not the tests.  
   The job would run but would save a lot of time when there is no test to be run.  
   ??Keep in mind that parallel jobs require multiple agents available.  

   To discover which repository triggered the build you use a script like the one shared here: [Determine which Repo triggered a build](https://community.atlassian.com/t5/Bamboo-questions/Determine-which-Repo-triggered-a-build/qaq-p/1108462?utm_source=atlcomm&utm_medium=email&utm_campaign=kudos_answer&utm_content=topic)

I know this is not an elegant solution. I think the best option would be having each client compiling and testing its own code. You shouldn't need to compile ProjectBase if the changes are only happening on dependent plans.

There is a feature request that would be helpful in this case:

* [\[BAM-11257\] Conditional build step depending on value (or existence) of variable](https://jira.atlassian.com/browse/BAM-11257)

I tried a solution with the plugin mentioned in this thread ([Solved: How we can configure job with conditional tasks...](https://community.atlassian.com/t5/Bamboo-questions/How-we-can-configure-job-with-conditional-tasks-for-bamboo-Plug/qaq-p/1105461?utm_source=atlcomm&utm_medium=email&utm_campaign=answer_accepted_as_solution&utm_content=topic)) but it does not accept injected variables.  


author: Pavel Matyska
body: Hi Daniel,

Thank you for your response. We also thought about having a plan per project which would have compilation stage and test stage, although this configuration uses more disk space. It would also enable us to see results of last test run for each project. In the workaround solution when some test jobs would still be executed but skip running the tests, it would result in "passed" job state which would hide those last results.

We will try your suggested best option and see if it makes us happy.

Just a thought about triggers for one of your next version of bamboo. Would it be possible to make trigger of dependent plans appear in triggers tab of the plan (along with repository polling, schedule, ...) and make some "binary operators" on them, so a user can say: I want to run this plan when "(triggerA AND triggerB) OR triggerC" is triggered. It could open some new path of plan chaining. Also, it will enable a user to see all of the triggers at one place.

Anyway, thank you for your time and responses.

Pavel


author: Daniel Santos
body: Hi [@Pavel Matyska](/t5/user/viewprofilepage/user-id/1298719)  

You are always welcome!  

I really think the best approach is to have the projects self-contained. I didn't insist on this idea because it would probably require a repository refactory (to reduce disk usage).  

Regarding your idea for an improvement request, I just opened one:

* [\[BAM-20582\] Allow conditional triggering of child plans](https://jira.atlassian.com/browse/BAM-20582)

Thank you for sharing your feedback about the feature request.  

Have a good one!  


Tags: changeset

child-page

plan