Best Practices for SVN/GIT on projects

I am now experimenting with keeping my data/projects directory as a git repository, similar to described in this thread.

It’s still a bit of a bumpy process, but it definitely feels more precise (i.e. safe) than the prior methods of maintaining project history.

One question I’m still trying to figure out is if there are any sub-directories or files that we should add to the .gitignore files. At the moment, I’m suspicious of the conversion-report.txt file and the .resources directory. Can anyone provide guidance on this topic, please?

3 Likes

Hmm. Yes, ignoring conversion-report.txt and the .resources folder is a good start.

I can’t think of any others off the top of my head.

So, I’m piecing together a project update gateway event script. Here’s the first working revision:

projects_directory = '/var/lib/ignition/data/projects'

def project_updated():
	current_gateway = system.tag.readBlocking(['[System]Gateway/SystemName'])[0].getValue()
	current_project = system.util.getProjectName()
	update_message = 'Updated {g}:{p}'.format(g=current_gateway, p=current_project)
	print(update_message)
	add_command = 'git -C {pd} add .'.split(' ')
	add_command[2] = projects_directory
	system.util.execute(add_command)
	commit_command = 'git -C {pd} commit -m {msg}'.split(' ')
	commit_command[2] = projects_directory
	commit_command[5] = update_message
	system.util.execute(commit_command)

Yes, my parameter replacement in the command strings has hard-coded indices at the moment. I was originally doing format() before split(), but bumped into issues with it splitting my commit messages. This is just my quick-and-dirty fix at the moment.

Some questions I have:

  • Is that a good way to access git? I don’t want to have to install/maintain any libraries, so I suspect that means I’ll be calling the command line git to do the work.
  • Is there some way to auto-detect the projects directory path? I couldn’t find anything with a few minutes of searching the manual and forum.
  • Is there any way to grab more info about the project change that triggered the event? I would like to have information like which user triggered the save and which project components were updated.

EDIT: Something isn’t quite right with this script since the commit doesn’t always happen. I’m guessing the calls to system.util.execute don’t block for the command to finish. Is that possibly the issue?

What you’ve got there is essentially “correct”, for the limited implementation of the project update script we currently have - we’re definitely planning to revisit in future, and add some of the “obvious” information like project name, modification actor (if available! remember that changes could come directly from the filesystem), etcc.
I think you’ll need to use something like Python’s builtin subprocess module (eg, subprocess.call()) rather than system.util.execute() to make the git call block.

Interesting chasing-my-own-tail moment: I just did a git pull in the projects directory of one server to bring it in sync with the other, which changed some files, which triggered the project change event, which then tried to add/commit everything!

In this particular case it was okay since the projects directory was in sync with a commit (i.e. the add/commit both did nothing). But, I’m pretty sure there would be some very ugly consequences in many other cases…

Let this be a warning to any other people following this path: don’t enable a project change script like I have above if you will be doing any work in the projects directory that could ever possibly leave the git repo in an incomplete state. I can’t imagine the chaos this would cause if I were doing a git merge in the projects directory and hit a conflict.

I imagine a reasonable solution would be a lockout memory tag that indicates that git add/commit should be disabled for the time being. A developer would turn it on before doing git work on the command line, and the script above would do nothing when it was set. This would allow the setting to be changed without changing the project properties.

1 Like

Incidental nice features: switching from system.util.execute to subprocess.call will include the output of the git command in the wrapper log, and switching from print to a system.util.getLogger object also adds in more hints about the source of the trigger.

INFO   | jvm 1    | 2019/11/27 16:54:11 | I [c.revision_helper             ] [16:54:11]: Updated ignition1:customer project-name=customer, request-origin=1.2.3.4, session-user=jbuser, session-project=customer, session-id=34947258
INFO   | jvm 1    | 2019/11/27 16:54:11 | [master e78f6c9] Updated ignition1:customer
INFO   | jvm 1    | 2019/11/27 16:54:11 |  4 files changed, 11 insertions(+), 8 deletions(-)
I

Hmm, you could try something like this to get your own access to that meta-information. It’s not guaranteed to be available, but you can try:

from org.slf4j import MDC
user = MDC.get("session-user")
if user is not None:
# you have an actual username

Should probably use org.slf4j.MDC instead.

1 Like

In case anyone lands here in the forum first, the IA team just recently put out an excellent whitepaper discussing issues and methods related to deploying Ignition on revision control like git: