TFS Code search is a great feature. Our developers love it; they can easily search for anything within the millions lines of code we have in our various repos.
However, by default, this feature works only on the repo’s default branch. This can be nice for a general-purpose search, but when working on multiple branches with considerable differences between them, it is not good enough.
It took a lot of digging to find out that you can add up to 5 additional branches to be included in the code search. Go to the project’s settings > Version Control > select the repo and go to the Options tab. there you will find this well-hidden option.
Adding branches should trigger auomtatic re-indexing of the repository. To monitor the status, or force re-indexing in case of need, see the Code Search Admin page.
First time I encounter a Git behavior which, on first look, seems to defy common sense.
1. create a feature branch off master
2. perform some changes and commit (in this example – add a new line to foo.c)
3. merge the changes to master using a pull request with squash
4. on the feature branch, revert the previous commit (in this example – remove the line from foo.c)
5. merge master to the feature branch
One would expect that the reverted content will remain or that at least a manual merge conflict will occur. But surprise – the merge overrides them with the content on master (the content before the revert).
So why it happens? because how three-way merge works when there is a single common ancestor.
In the diagram, you can see that C1 is the common ancestor of C3 and C4. When doing the merge, git compares C4 to C1 and C3 to C1.
Since C1 and C4 are identical, it causes git to “understand” that the feature branch did not change the file at all, so it should take the change introduced in C3 and apply it as the merge result.
How it differs from a regular (non squashed) merge?
In this case, the common ancestor changes. It is now C2. So git compares C2 and C3, find that they are identical, hence selecting the change between C2 and C4 as the “interesting” change to apply as the merge result.
Conclusion: if you merge with squash, do not use the same branch to introduce additional changes…
Recently we upgraded one of our JIRA instances. It all seems well at first and then small problems started to pile up.
After contacting Atlassian support, it turns out we should have upgraded our database server (Oracle in this case) before the upgrade (“it’s in the documentation!”). We didn’t, so some data upgrade tasks silently failed, without any notification during or after the upgrade process.
I was surprised. As a long-time installation developer I learned one thing: users don’t read the documentation until they have problems. They certainly don’t read installation guides; at most they skim through the release notes. That’s why every installation I create includes some basic validations regarding the environment (e.g. OS, database, Java…).
So, I suggested Atlassian to add this kind of checks to their own installer and they immediately agreed. All that’s left is to gather enough votes so it would go into their suggestion review process. Appreciate your help!
Let’s say you have two JIRA projects, project K using a Kanban board and project S using a Scrum board. Each project with its own set of statuses and workflows.
Now, users of project S want to see issues from project K on their Scrum board. They update the board filter accordingly, but to their surprise, many project K issues are not visible in the Backlog.
Why? because a JIRA board (either Scrum or Kanban) only shows issues whose statuses are mapped to the board’s columns (e.g. To Do, In Progress, Done).
Issues with unmapped status are not displayed on the board at all. This is useful in some scenarios but confusing in others, such as in the example above.
To remedy the situation, go to the Scrum board’s configuration, and under the ‘Columns’ sections you can map or unmap statuses as you see fit.
I recently encountered an elusive bug, which eventually I tracked down to the fact that environment variables are not replaced in a certain string even though it is set by calling os.path.expandvars(original string).
Turns out, the problem is that expandvars() doesn’t expand variables who are enclosed within a string literal. I couldn’t find it documented anywhere but facts are, this is the case.
>>> import os
>>> os.environ['VAR1'] = 'Value1'
>>> s1 = "this is '%VAR1%'"
"this is '%VAR1%'"
>>> s2 = "this is %VAR1%"
'this is Value1'
It may be a good idea in some cases, but for me it was quite an annoyance.
Here’s a short explanation how to execute python unit tests during VSTS/TFS builds, without the need of plug-ins. The basic idea is to create a JUnit XML from your test results, and then have it published to the TFS build dashboard.
First, on the relevant build agent(s), install the pytest module. You can use the following command, or your favorite CM tool.
python -m pip install pytest
Next, edit your build definition in TFS, and add two build steps: one (Batch Script) for running py.test to generate a junit XML, and one (Publish Test Results) for publishing the xml to the test results page.
The full command line to run the tests is as follows (in this example, the unittest code is in test_MyApp.py):
InstallShield users may have noticed that, in all the ‘select folder’ type dialogs, there is no ‘Create New Folder’ button. If the user wants to create one, he can only do it from Windows itself, or (in some dialogs) type it as text. This is because all these dialogs call the SelectDir() function when clicking Browse.
This is of course very inconvenient, I saw several uses complain about it, but the situation remains.
I came up with a solution, inspired by this KB Article (how to browse for files in InstallScript). Basically I created my own version of AskDestPath() dialog, and modified the behavior so when clicking Browse it will call a custom function i wrote, based on Windows API SHBrowseForFolder().
You can find the custom function on my GitHub here.
The only issue I have is that I cannot set the initial folder. This is a known drawback of this specific API function, and there is a known C++ workaround – but it cannot apply to InstallShield since it does not support pointers to functions (it crashes if you try).