Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Export Path in a multi-developer source code environment #529

Open
rsonnier-cfs opened this issue Aug 13, 2024 · 10 comments
Open

Export Path in a multi-developer source code environment #529

rsonnier-cfs opened this issue Aug 13, 2024 · 10 comments

Comments

@rsonnier-cfs
Copy link

rsonnier-cfs commented Aug 13, 2024

Background:
We have 3 developers and about 50 individual ms-access databases supporting over 200 users across multiple facilities. Our distributed version control system, therefore has 4 source folders, one for each developer and a "master" repository for a common synchronization destination.
Each source folder has a sub folder for each of the 50 databases. Each developer uses msaccess-vcs-addin [version control.accda] to export to our respective user# source code repositories. Then we use TortoiseHG with GIT to commit, merge, push/pull, etc. between Master and User# source. Each user synchronizes their individual source folder with \ShareDatabase\MasterRepository.

(These share and folder names below have been changed to a generic representation of the folder structure for the purpose of this discussion.)
...\ShareDatabase (database location for current version of all dbs)

...\ShareDatabase\User1-Development (User1 in progress databases, )
...\ShareDatabase\User2-Development (User2 in progress databases)
...\ShareDatabase\User3-Development (User3 in progress databases)

...\ShareDatabase\User1-Development\Source_User1 (User1 source code repository)
...\ShareDatabase\User2-Development\Source_User2 (User2 source code repository)
...\ShareDatabase\User3-Development\Source_User3 (User3 source code repository)
...\ShareDatabase\MasterRepository (Master source code repository for all users to synch with)

PROBLEM:
With version 3, as well with version 4, VCS options allows you to designate an Export Folder. When an initial export is performed by User1 [version control.accda] creates a .json file which stores the export folder location. That is great, unless you have a developer team, with each developer having a different source code folder. When the next developer (User2) has to work on the same database, [version control.accda] reads the .json file to get the export folder last used, and sets the export location to the .json export folder location. This results in User2 exporting to the User1 source code folder. Now user2 will not see the changes pending to commit in Tortoise. And similarly, User1 will see pending changes that they did not create.

We resolved this issue by a few small modifications to [version control.accda]:

  1. Use a couple of variables in the Options Export Folder string in Options form:
    "...\ShareDatabase%Uname%-Development\SOURCE_%Uname%\%dbname%.src"
    Results in Proj-properties.json having the following:
    "VCS Source Path": "...\ShareDatabase\100\%Uname%-Development\SOURCE_%Uname%\%dbname%.src"

Now version control can read the string from the .json and substitute the variables as follows:


Module modFunctions;
'Added: Gets user NT Username used in Public Function GetExportFolder
Public Function User_FX() As String

Dim lSize As Long
Dim lpstrBuffer As String, trimStr As String
lSize = 255
lpstrBuffer = Space$(lSize)
If GetUserName(lpstrBuffer, lSize) Then
User_FX = Left$(lpstrBuffer, lSize - 1)
Else
User_FX = "Unknown"
End If
On Error GoTo 0
End Function

Module clsOptions;
Public Function GetExportFolder() As String

Dim strFullPath As String
If Me.ExportFolder = vbNullString Then
    If DatabaseFileOpen Then
        ' Build default path using project file name
        strFullPath = CurrentProject.FullName & ".src" & PathSep
    Else
        ' Check options file path
        If Len(m_strOptionsFilePath) Then
            strFullPath = FSO.GetParentFolderName(m_strOptionsFilePath)
        End If
    End If
Else
    If Left$(Me.ExportFolder, 2) = PathSep & PathSep Then
        ' UNC path
        strFullPath = Me.ExportFolder
    ElseIf Left$(Me.ExportFolder, 1) = PathSep Then
        ' Relative path (from database file location)
        strFullPath = CurrentProject.Path & Me.ExportFolder
    Else
        ' Other absolute path (i.e. c:\myfiles\)
        strFullPath = Me.ExportFolder
    End If
    ' Placeholder replacements
    If InStr(1, strFullPath, "%dbName%", vbTextCompare) > 0 Then
        strFullPath = Replace(strFullPath, "%dbName%", CurrentProject.Name, , , vbTextCompare)
    End If

    ' 08/01/2024 Modified by RSonnier to allow %UName% variable in the Export Folder Path
    If InStr(1, strFullPath, "%Uname%", vbTextCompare) > 0 Then
        strFullPath = Replace(strFullPath, "%Uname%", User_FX(), , , vbTextCompare)
    End If

End If
@hecon5
Copy link
Contributor

hecon5 commented Aug 13, 2024

Is there a particular reason you're not using local repositories on each user's machine and then syncing to a remote location instead of the always-remote method you're doing here?

We all have a local on our machine repo that syncs to the remote. We use strict branches (stable,dev, test) with merges only permitted via pull requests; and work branches off dev to test features.

We only ever deliver code that's merged into stable or dev; and each developer can pull the stable and dev branches to their machines to build and deploy; we use a modified version of msaccess-devops to accomplish this. Especially for remote employees, this process is leagues faster than working off a common network drive folder system.

@hecon5
Copy link
Contributor

hecon5 commented Aug 13, 2024

See #514 for some more discussion on this; and why you might consider a slightly different workflow when you're using git/VCS.

@rsonnier-cfs
Copy link
Author

Yes, so you are not the first to ask about our unconventional topology. Ill try to explain as there are some huge advantages to our setup.

  1. First we have high end server and network hardware and all SSD data storage. The large majority of our development is performed on a virtual server Remote Desktop. Performance is normally not an issue. All data is replicated to a second site at intervals throughout the day. We can recover files on 2 hours increments throughout the day.
  2. We have a really cool SQL setup. Our SQL environment is completely replicated on a separate server as well, so we have a complete test environment which our development RDP server sees as "live". When using the Remote Desktop develop server environment, all data ODBC requests are automatically routed to the test SQL database. We no longer have to re-link our MS-Access ODBC linked tables to a sandbox for development, then back to live server for production. We can just copy the tested release over to production and deploy. If we want to test on live data, or see more recent data, we can always open the Access app on our local desktop which is connected to the live SQL database. We update the test SQL database every weekend, and can also update midweek if necessary.
  3. All hard desktops are using folder redirection anyway, so 'local' profile files are actually stored on the shares anyway.
  4. We can easily hop over to another developers share and see their projects if necessary when a developer is out of the office for any reason.
  5. We typically have developers working on separate Access databases anyway. If other requests are coming in for the same database project, the same developer will take those as they are already working on that application. We don't end up with a lot of merges for this reason.
  6. We don't normally have branches of development. We get tasks, code the changes. test and deploy. All of our development is for private intra-company processes. And we are really good too! Never make a mistake!! LOL!!!

@hecon5
Copy link
Contributor

hecon5 commented Aug 15, 2024

Ah, RDC does make a difference for remote performance. That said, it reads like your workflow is branching with extra steps: one of the key features of git development is to facilitate merging of components in a streamlined way. It looks and sounds a lot like you do branching, you just don't call it that. What you're doing reads a lot like you do a merge with fast forward when you push upstream.

There's nothing preventing you from using an SQL setup like you have and branching + separate dev folders on the same server, and a fair number of upsides (IMHO). This has the added benefit of not requiring fancy workarounds (read: non-typical and prone to issues when someone unfamiliar interacts with your setup), and you get all the upsides of git and the addin, you can still peek at other's code when they step away, and an additional layer of protection from git pushes. You might also look into worktrees - they're pretty close to what you're doing anyway and have some upsides.

It would look like this; it looks a little more convoluted than it is; and depending on how you setup your source files, you could probably get away with not having a second folder for each DB like I have here (all .src folders are in Dev Repo folder directly); I just split it out for reasons.

└── Server /
    ├── Share DB \ Basis Repo (bare repository, no work is done directly in here) "upstream"/
    ├── Share DB \ Dev 1 Folder (holds all of Dev 1 development folders; no work is done here, just a holding point)/
    │   ├── Dev 1 Repo Work Folder 1 (This is a "local" repository on "stable" branch) for "stable" building/
    │   │   ├── Overall Support Docs 
    │   │   └── DB 1 Work/
    │   │       ├── Support Files folder
    │   │       ├── DB1.accdb.src folder
    │   │       ├── DB1.accdb
    │   │       ├── DB1-backup1.accdb
    │   │       ├── DB 2 Work/
    │   │       │   ├── Support Files
    │   │       │   ├── DB2.accda.src
    │   │       │   └── DB2.accdb
    │   │       ├── DB3.accdb.src/
    │   │       │   ├── Support Files
    │   │       │   ├── DB3.accda.src
    │   │       │   └── DB3.accdb
    │   │       └── DBn.accdb.src/
    │   │           ├── Support Files
    │   │           ├── DBn.accda.src
    │   │           └── DBn.accdb
    │   └── Dev 1 Repo Work Folder2 (A work tree copy branched separately from folder 1 on the "work task 1" branch) for "task 1"/
    │       └── mirrors folder structure above; but work is done on the relevant DB on a work branch / work tree.
    └── Share DB \ Dev 2 Folder (similar to Dev 1)

Each dev commits / pushes to "upstream" on work branches while they work all other devs can see those in real time when they fetch from the upstream basis without going into each other's sand boxes (still can, but you don't need to). This also builds good code hygiene and practice, as undoing/reverting things becomes easier. You can also more simply cherry pick bits as needed to place on the stable/dev/test branches. This folder setup does not require any changes to the Addin; as each addin is built according to its name and .src files.

Sorry this got a bit long winded, and perhaps convoluted, but from also having several devs on a team, and several dbs, I suspect using git branches and more frequent commits and pushes you'll get exactly what you want without needing fancy footwork.

@rsonnier-cfs
Copy link
Author

rsonnier-cfs commented Aug 20, 2024

Interesting that this has now come full circle to the original issue that I started the thread with. Thank you for the suggestions and I will evaluate if we need to implement any of that going forward. In your proposed redesign of my live (and working well) development environment, the issue with Version Control pulling the export path from the json file still exists since version control wants to export to whatever the last export location was regardless of who the developer was. My proposed solution doesn't affect the handling of the export location as it currently functions, it just allows me to use a variable to send the exported source to the location I want per user.

One solution is the one I suggested to allow the use of user variables in the path; which I have implemented and working in my copy and wanted to share in case anyone else could use it.

Another solution is to simply not pull the previous export path from the .json file and simply use the path each user has defined in the VCS options. Not sure why VCS uses where it was last exported to, since when updating or merging the last export path will become the current path for the next export. Maybe you don't merge/update the .json files. Or what if the developer wants to change the source code location? Or maybe I am just not understanding something here...

Not a big deal as I can quickly implement my fix on future versions as I did when migrating to V4. Of more concern is the issues I have with the build...but that's another thread.

@hecon5
Copy link
Contributor

hecon5 commented Aug 21, 2024

Are all the devs opening the /same/ Access file to develop on?

If so, then I think what you're saying might make sense, VCS does want to export to the prior location.

In the example I mentioned above, each person would have their own version of the file, and in that case, each person only exports to their single location. When deploying, the file is copied/moved to the deploy location for use.

I can see how if you're all using a single set of develop files how a user variable might make sense.

@rsonnier-cfs
Copy link
Author

If I understand the question then yes. When a user gets a task, they copy the current .mdb that needs to change to their dev folder, make the code changes, test, export to source, then copy the modified .mdb back to the current/active database folder. (VCS Build is not yet working for us.) At that point we have internal scripts that we run to build .mde, and move to production. Daily automated routines move/copy the .mde files to "live" each evening. The developer then commits and pushes the source in TortoiseHG. Our goal is to have build working soon.

One of the issues with build deals with the same logic in the build path. Build logic assumes VCS knows where to put the newly built file. Currently in my testing, build gets the build destination from a .json file (which is the last build path used) and the replaces the current .mdb (with backup of the original file) so again I have had to modify the VCS code for build to use another location. I just don't understand why VCS doesn't let the developer control the export path and build path. Again, it seems that maybe we run into the issues since we don't follow the strict branches (stable,dev, test) logic you refer to above.

Another method of addressing the issue would be to simply prompt the developer to choose from 2 paths for the export or build process. Either the user's path defined in options, or the previous path used from .json if they are different. But there is no option for a build path; something else I see as a oversight.

@joyfullservice
Copy link
Owner

Thank you both for the input and discussions here. Perhaps I can just add a few thoughts regarding the design of the tool with regard to the export and build paths. In a typical usage scenario, you have a binary database file paired with a corresponding set of source files. The add-in facilitates the two-way synchronization to make sure the source files match the binary database. From a development perspective, the binary database is an artifact of the source files. The source files are the "source of truth" and the database can be built from any version of source files.

The recommended setup involves excluding the binary database from version control, since you can build it at any time from just the source files. I like to keep the database in close proximity to the source files, so that's why the default setup is for the source to export into a subfolder of the database location. This way you can see at a glance where the source files are for a particular database.

When you do a build, you are building that specific set of source files into a binary database file. In the default setup, this will build the database in the parent folder of the source file folder. This keeps everything together in the same place. If you are working directly on a checked out branch, and the binary file is excluded with a .gitignore file, then the only changes you will see are the source file changes during the development cycle.

Generally speaking, the more you separate the binary database file from the source files, the more complexity you add to the setup. Am I sure I am working on the right binary? Where exactly is this database exporting? If I build from source, where can I expect to find the newly built database? In your environment it sounds like you have some very strict guidelines and processes to keep things organized, and that's perfectly fine. You need to work out the approach that works for you.

Please understand that I am not saying you need to change your setup, or that what you are doing isn't working. I am just sharing some of the background on the typical usage of the add-in and how that impacts design decisions on things like export/build paths. Because, in a sense, the database is the IDE, there is a pretty tight coupling between source files and the database. The path that I would encourage most users towards is keeping things simple and leveraging git branching to manage different versions of source files. But in a case like yours where you have a very specific setup and development workflow, I can certainly see how things like expandable variables in the export path are helpful.

You might be interested to know that expanding environment variables in the export path is actually something that I have added about six months ago on the dev branch after the 4.0 release, and can not only expand the USERNAME but any other environment variable. (See: 11f2acf) This should roll out in the next general release, or you can build the dev branch to start testing this now.

Hope that helps!

@hecon5
Copy link
Contributor

hecon5 commented Oct 10, 2024

Since this appears to be answered (perhaps resolved, too with the additional environment variables) should this be closed?

@hecon5
Copy link
Contributor

hecon5 commented Oct 10, 2024

Forgot to tag @joyfullservice and @rsonnier-cfs, sorry!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants