(Unofficial) Anvil Version Control for Dummies

Thanks to everyone who’s helped me get up and running recently, especially @stucork @hjp @aldo.ercolani @bridget @meredydd . I’ve taken the trouble to write up my recent learnings as a Tutorial, taking as little for granted as possible, hence quite a verbose post I’m afraid. If you have any improvements, corrections, or comments to offer I think you can now contribute directly thanks to @stucork who turned this into a Wiki post!


OVERVIEW

This Tutorial assumes little or no prior knowledge of version control or environment management concepts, Git/Github, command line incantations or SSH. It’s divided into different ‘levels’ which build on each other and hopefully don’t pre-suppose any knowledge or defer to other tutorials apart from Level 1 which relates entirely to the Anvil workspace (or “IDE” - Integrated Development Environment) and is essential pre-reading.

What level you reach after that is totally up to you, and depends on how much control and sophistication you think you’ll need to achieve your goals as an Anvil developer.

Levels 1-5 deal with organic Anvil features and functions. If you want to jump to version control
using Git then please scroll straight to Level 6. If you’re comfortable with Git but not SSH then Level 7 is for you. Levels 9-10 deal with sharing multiple versions with multiple developers (through Github) while keeping in sync with the Anvil IDE.


LEVEL 1: Anvil's Organic Version Control

Basic incremental version control is covered very nicely already in the Anvil docs. Start by reading these two pages if you haven’t already:

i) Anvil Docs | Version Control
ii) Anvil Docs | Version Control

Where I first ran into confusion was with the third article about Git (Anvil Docs | Git). It assumed knowledge I didn’t have, and the rest of this Tutorial is basically an attempt to fill that gap now that I’ve been through the learning curve, nudged along by other kind souls on this Forum.


LEVEL 2: The Dev-Test-Prod concept

One of the most simple but helpful concepts for software development imho is the idea of organising your code and associated data into three similar but ring-fenced areas typically called Development (DEV), Testing (TEST), and Production (PROD or ‘master’). There are many different ways of implementing and refining this simple approach and not everyone even uses the same terminology, including Anvil. The underlying model is worth getting straight in your head though, since it often helps to understand what we’re trying to achieve and why before jumping into asking how

So a Development environment is one where you can safely hack around and play with ideas and dummy data without upsetting anyone, except perhaps yourself (!). When you create your first Anvil app you’re effectively thrown into a Development environment right away. If you’re working with other developers you might want to give them a copy of your Development environment to play with, but you’ll need a way to compare notes later on and merge the best bits of your respective creations, without breaking each other’s work… but that’s Level 6+ later on.

A Test environment is basically a copy of your Development environment, or typically an earlier version of your Development environment, which you’ve chosen to share with a select group of friendly Testers who create their own data, play around, and generally try to break things in the spirit of quality control and continuous improvement (and generally making you feel completely inadequate as a coder!). When you Publish your app in Anvil, presumably only sharing the link with a nice small group at first, you’re effectively creating a new stand-alone Test environment which other people can access while you continue to tinker with code and data changes in your Development environment. Anvil offers several methods for giving people access to your app, but a good option for Testers is sending a private link I’d suggest:


When you Publish an even better version of the code you’ve been working on in Development (sometimes called ‘promoting’ from DEV to TEST), you’ll replace the Test environment with the latest version of Development and this cycle goes round and round until eventually you’ve created a masterpiece that your Testers simply can’t find fault with. At that point you’re ready to go live and share with the general public, or in other words, create a Production environment.

So a Production environment is a fully public and ‘live’ version of your app which you’ve chosen to share with the world. Real users, real passwords, real credit card details, real data, and real legal obligations such as data privacy. Scary but exciting stuff. The usual way of giving general access to your Production environment is simply by sharing the public link. In Anvil you can do this either in the Publish app menu or Share your app menu.



LEVEL 3: Getting a little more organised

When you create a single app in Anvil you have a good number of choices for Publishing , Sharing , Cloning , and Downloading your app as well as going back through your Version History to revert changes or Publish from a particular version previous version. If you have a Business Account you can even invite other people to join your organisation and share your app that way too - although presently I don’t recommend this method because a) Only one person can work on your app at a time; b) there’s no active notification system, so you won’t know someone else has been tinkering unless they tell you separately or you diligently check the Version History before starting your own work; c) even if you know someone has made changes, it’s not obvious where or what those changes are.

For all these reasons you might like to think about creating three separate versions of your app (e.g. MyApp-DEV , MyApp-TEST , MyApp-PROD ) which you can manage and control access to individually and with more precision. To do so, simply rename your original app to MyApp-PROD or similar, then Share your app...


Copy the link and paste it into a new browser Window to create “Clone of MyApp-PROD” and rename that to “MyApp-DEV”. Repeat for MyApp-TEST .

Footnote: I just noticed you have to rename your cloned app TWICE actually:

Once at the very top of the App Browser menu…

And once under Client Code / Server Code:


LEVEL 4: Do you really need three copies of the app?

Because of Anvil’s nice Publish feature, each copy of your app can effectively be managed as if it were two environments - one ‘master’ branch and one ‘development’ branch.


You could therefore just create just two versions of the app in Anvil to cover the different uses of DEV, TEST and PROD:

App1: MyApp-DEV-TEST
App2: MyApp-PROD

The main question here though is whether you’re happy for the same data to be shared between DEV and TEST. If you’re a one-man or one-woman band and doing most of the testing yourself, and for consistency you want to always be working off the same data, then this slimline approach might be ideal.

N.B. Sharing data between TEST and PROD would be crazy so don’t even think about a combined TEST-PROD environment!


LEVEL 5: Sharing with other developers/testers using Anvil

Regardless of whether you now have 2 or 3 instances of your app in Anvil, if you want to share one of them (code and data), just open the App Menu then Share App... as follows:


Alternatively, Download as a file from the same menu (above), share that file outside of Anvil, and have your co-developers Import rather than Create a new project. [Ed. I’m not sure if this also copies the data tables… could someone confirm please?]


LEVEL 6: Syncing between your local computer and Anvil using GIT

So if you’ve never heard of Git before (https://git-scm.com/) it’s basically a “free and open source distributed version control system designed to handle everything from small to very large projects with speed and efficiency.” Basically if you want to work on a local copy of your Anvil/Python code and sync any changes automatically with Anvil and (best of all) compare line by line what’s changed between versions, perhaps using a fancy IDE like VS Code or PyCharm (there are numerous alternatives) just follow these steps:

  1. install Git
  2. Get yourself an SSH Key (see Level 7 below…). Despite suggestions it should be possible, I was unable to make Git work with Anvil using user id and password (or Github Desktop - see later), and so using SSH was the only solution for me. As it turns out, SSH is a handy thing to know about anyway.
  3. Share your app (now renamed ‘MyApp-DEV’) then Clone with Git
  4. Paste your (long) SSH Key into the big box, copy the git clone ssh:// incantation from the small box, and click Save.
  5. Open up a Command Prompt, navigate to your usual Python projects folder, paste the git clone ssh:// incantation and follow prompts. You should now see a new folder (the “origin”) with your app name and the following subfolders [Ed… maybe not pytest initially?]:
    image
  6. Go back to your Command prompt, navigate to the root of your new local ‘origin’ folder and enter: git remote add Anvil_MyApp-DEV ssh://...git where ssh://...git is the final part of the command you copied from the small box in Step 4 above (but without the app name MyApp-DEV at the end, and optionally prefixing your remote name with “Anvil_” to distinguish it from any other remotes - see later).

You should now be set up to automatically see and sync changes you make on Anvil (the ‘remote’) and your newly cloned local folder (the ‘origin’). You can pull changes from Anvil to your local folder, and push changes from your local folder to Anvil, where it will register as a new line in your Version History. Crucially you can also now use Git (and other tools) to view the ‘diffs’… line by line comparisons of the different versions of every file. There are some really nice colour-coded GUIs that show this information graphically… for example VS Code which I’ve already mentioned and Github Desktop (see Level 9 below). Welcome to whole new world of version control!

And here’s how Git integration looks in Anvil’s Version History:

Footnote: Any files you add to the root of your new, local, origin directory won’t show up in the Anvil IDE - they might still be there on the Anvil remote server and accessible with os and pathlib Python commands, just not visible in the Anvil IDE which basically just exposes client_code, server_code, and theme. I only mention this because it’s common practice to put a readme file and license file in the root of the origin - which you can still do, you just won’t see it on Anvil (unless my feature request is actioned :wink:).


LEVEL 7: Secure Shell (SSH)

SSH is a protocol for logging in to servers (or services such as Anvil/Github/Digital Ocean etc.) without using passwords. You create a public and private key which are saved to your HOME (or USER) directory and then you just need to give the public key to the relevant server/service.

  1. Windows 10 has SSH pre-installed, likewise MacOS and Linux I believe.
  2. Open the Command Prompt and type ssh-keygen -t rsa
  3. Use a text editor to navigate to your HOME or USER folder then the newly created .ssh directory.
  4. Open id_ras.pub and copy the text which should start with "ssh-rsa " and runs on for several lines. On Windows 10 you can just enter more %userprofile%\.ssh\id_rsa.pub | clip on the command line (from any directory) and the text will be copied to your clipboard.

You can use one SSH key for everything, or if you’re concerned about security create a key for Anvil and additional keys for additional services, or even a new key for every single app on Anvil. To make a new key for Anvil you just type ssh-add /home/brad/.ssh/id_rsa_anvil for example.

Not essential for Anvil, but you can find more information on SSH by watching this hour long video :sleeping: or scanning through the associated command snippets (‘gist’) here.


LEVEL 8: Pulling it all together...

At Level 3 you created three separate Anvil apps for DEV, TEST, and PROD and at Level 4 you paused to consider the alternative of creating just two separate apps, DEV+TEST, and PROD. At Level 6 you set up Git synchronisation between files and directories on your local computer (the ‘origin’) and Anvil (the ‘remote’).

So if it didn’t already occur to you already, the next step is just to repeat Level 6 for your remaining DEV, TEST or DEV+TEST environment(s). Once you’ve set up Git synchronisation for all 3 (or 2) of your Anvil apps, you can make changes either directly on Anvil, or locally, and you’ll be able to see what has changed line by line, all the while maintaining a perfect Version History you can restore from.

Then, when it comes time to ‘promote’ your latest changes from DEV to TEST just make sure your remote and origin for DEV are up to date and in sync, replace your local TEST folders and files with a copy from DEV, and then push those changes from local TEST to Anvil TEST. Likewise when you’re ready to promote TEST to PROD.

Footnote: I don’t think this will automatically copy, reset, or repair your data tables, so you might need to do that manually or by running a helper function. Also I haven’t read up on how Anvil backs up and restores data tables yet, so that might be something you need to consider managing yourself too.


LEVEL 9: Joining the Github community

Level 6 is fine if you’re mainly working on your own, but what if you want to open up development to the wider community in a structured way? If you don’t already know about Github, it’s a massive online repository for developing and sharing code: “The world’s leading software development platform” with loads of collaborative and issue management tools , discussion, and documentation tools built in.

It allows you to collaborate with other coders, creating branches (or forks) and then merging them back with the master version using ‘pull requests’. There’s also a snazzy client tool, the Github Desktop which I’m a fan of and integrations with editors/IDEs like VS Code. Click here to sign-up for a free Github account.

If you had created a Github account and downloaded the Github Desktop earlier and prefer to avoid Git incantations you could replace Level 6: Steps 6-7 with the following:

  1. Log in to https://github.com/, click on your profile photo (top right), Settings, SSH and GPG Keys, New SSH Key, put your app name in the small box and copy the (long) SSH key from Level 7 into the big box, then finally click on Add SSH Key.
  2. Open up Github Desktop, File, Accounts, Sign In using your new Github account name/email and password. File, Add Local Repository, Browse to your new local app folder and select it.

LEVEL 10: Creating additional remote copies of your local app

Using Git you can sync your local files not just with Anvil but also to a new ‘remote’ repository on Github (and elsewhere). Unfortunately the Github Desktop client doesn’t have the ability to create multiple ‘remotes’, but VS Code does…

  1. Create a new empty repository on Github: Click on your profile photo (top right), Your Repositories , New , Create Repository . To avoid errors, do not initialize the new repository with README , license, or gitignore files. You can add these files after your project has been pushed to GitHub.
  2. Copy the link https://github.com/<your account name>/<empty repository name>.git
  3. In VS Code go to Source Control (ctrl+shift+g), click on the three dots: More Actions , Push To... , Add a new remote... , give it a name*, copy the link from Step 2.

* You might like to prefix the name with “GitHub_” to avoid any confusion with the “Anvil_” remote you set up earlier.

If you don’t have VS Code or another editor that has this functionality for Step 3, or if you just prefer it, you can use a single Git incantation to set this up… From the Command Prompt, navigate to the root of your new local ‘ origin ’ folder (important!) and enter:

git remote add GitHub_MyApp-DEV https://github.com/<your github id>/MyApp-DEV.git

[Ed… is there also a git command to create the new remote repository (before adding it) instead of Steps 1 and 2 above?]

There’s probably no point in setting up a local copy of Production (unless you’re doing something clever with data configuration) and if you like me you’ve opted for a combined DEV-TEST environment then you only need to set up one local copy of DEV-TEST and just one additional remote repository on Github.

Here’s the sort of workflow you can now take advantage of:

  1. Make edits in the Anvil IDE or your local IDE (VS-Code, PyCharm or whatever) in the MyApp-DEV-TEST app.
  2. Use Git incantations, VS-Code, or Git Desktop to ‘pull’ edits to your local machine from Anvil (MyApp-DEV).
  3. Use Git incantations, VS-Code, or Git Desktop to ‘push’ from your local copy to Anvil and/or Github (where other developers can now contribute to your project using branch, fork, discuss, raise issues, collaborate on documentation in the normal Github way) *
  4. When it’s time to promote changes from DEV-TEST to PROD, just push all your local changes to Anvil TEST-DEV, Publish Anvil TEST-DEV to merge it with any unpublished DEV changes there, and then create a clone of TEST-DEV (see Level 3), renaming it as PROD (with a nice Release or Version Number schema if you don’t want to over-write your previous PROD) and Publish that to your fully public URL. [Ed… If you want to keep the previous version of PROD I think you might have to disable it e.g. by setting a dummy URL, but there might be a better way?]

( * ) If you experience problems pushing to Anvil, it might be because you’ve opened it in the browser at the same time as pushing, and it’s saved automatically. In that case you can go to Version History , restore to the version immediately before saved automatically and then push again.

There are other workflow suggestions dotted through the Forum, but if you’re a relative newcomer reading this Tutorial, rather than spending time theorising about the best way of working I suggest you just try this workflow for a while first and see if it works for you, then adjust your approach as required.


LEVEL 11: Pushing multiple branches from local machine to Anvil

What I stumbled on but haven’t seen documented anywhere is that from your local machine, you can also use Git (or in my case VS-Code) to create and push multiple branches (e.g. DEV1, DEV2, TEST1, TEST2) back to Anvil, which is brilliant!

Notice there’s even a helpful (but not very prominent) line linking DEV2 back to the Git Clone it was branched from…

And here’s how it looks when you merge DEV2 with ‘master’ locally using Git or Github Desktop etc and push back to the Anvil remote:

Notice again there’s a helpful (but not very prominent) line showing DEV2 has been merged into the Anvil remote (DEV). What’s not so clear perhaps is that the changes made in the Anvil IDE at 1:34pm have also incorporated in the 1:37pm version (I think).

I haven’t tested it myself but thanks to @owen.campbell for suggesting an additional step which, if I’ve understood his post avoids all instances using/overwriting the same data tables on Anvil… A problem I haven’t (knowingly) run into yet but might well do! Here’s the simple extra Git command:

git update-index --skip-worktree anvil.yaml

If you’re likely to use multiple branches like this, please read and support my Feature Request to make the View History a bit more explicit.


Phew - well done for getting all the way down to Level 11. As you can see it takes quite a few words to explain not just how and what to do, but why. I hope people find this Tutorial useful, especially newcomers, and that comments from more experienced developers will bear in mind the target audience and the need to be helpfully ‘opinionated’ about how do things, at least initially, rather than expect newbies to go through the same time-consuming learning curve and experiment with choices without really understanding the basics as I did.

One of the most amazing things about Anvil is how quickly even inexperienced coders can bash out a working prototype (many examples on the site justifiably claim to take < 3 hours), so if you’ll indulge me a whimsical closing thought, I do think it’s a shame it takes so long (relatively speaking) to set up and settle on good working practices for version control and collaboration, and that although Git/Github integration is supported in Anvil, it doesn’t just ‘work’ right out of the box.

I look forward to hearing people’s feedback!

All the best,
Peter

PS is there a prize for longest forum post ever? :wink:

23 Likes

I nearly took you up on that semi-implied challenge, but cut my post down when even I couldn’t be bothered to read it all back :slight_smile:

One of the “problems” with programming languages and their environments becoming easier to use is that one can lose sight of the fact that developing is hard. Anvil has lowered the bar to web development significantly but to do that it has had to hide and simplify some quite complex processes, as well as prioritise features. Team development moves you into non-trivial land.

I would love to see a version control built in that allows you to check out a package, blocking anyone else from working on it, and then merges all the changes, highlighting errors, creating a test environment just for you then…etc., etc. The problem is, I’ll bet there’ll be as many competing, incompatible ideas from others of varying development experience. And actually, that’s only what I think I want. If I ever got that I might end up saying, “Oh, no, that’s not as good as it sounded in my head!”

It’s a tough one, but I think when you are working on a project with a team, you have stepped onto the next rung of skills expectations and need to bite the bullet (which you’ve done).

I’ll bet that once you’ve worked through your list for the 40th+ time on large & non-trivial projects you won’t even notice the “Git incantations” (great phrase, by the way) as being anything other than just “what you need to do to make things work”.

What I would like to see is a really, really clear set of instructions, with pictures, of a team project set up where, for example, 2 people are working on the UI and 2 people are working on the back end. Advice on how to ensure no one clashes, what to do if they do, how to merge all the code, best practises. A proper guide that idiots like me could stick up on my wall and use as a bible, from someone(s [sic]) who really, really understand the process.

5 Likes

Thanks for your comments @david.wylie.

… actually I think this problem is exactly what Github seeks to solve while giving you flexibility in the way you structure and control your packages. I only stumbled on it today but it seems that’s already partly integrated and partly available within Anvil’s View History. Please see (and comment/like) my recent Feature Request on the topic?

Hehehe so true, and even over these last few days in my journey from ‘newbie’ to ‘not so newbie’ I’m starting to warm to the idea of a one line Git incantation rather than logging in through my browser and lots of menu clicking. However, since I started off with a pathological aversion to Git incantations, I think other newcomers are likely to be in the same boat, hence the idea of writing a more prescriptive and (hopefully) simpler Tutorial for first-time ‘dummies’ like me…

I’d like to see that too but certainly don’t “really really understand the process”!

I think the foundations of an answer will be obvious if my Feature Request is actioned, at which point you could simply create new branches “Dev1 - Back End”, “Dev2 - Back End”, “Dev3 - UI”, and “Dev4 - UI” in Github after inviting collaborators to the master Anvil remote. Each developer would create their own branch and when ready create a pull request for the app owner to review, discuss, and decide whether to merge using organic Github functionality.

I like being told what to do by people who really understand something. Then when I think I really understand it, then I go off piste :slight_smile:

3 Likes

I’d done some experimentation on multi-app projects with dev/prod versions and data tables. It was a bit of a mess, but some of the gotchas are shown in this thread: Cloning apps and data tables for Production and Development Apps

3 Likes

Hi all,

Does this diagram I’ve created for my Tutorial look right to you?

If you prefer to show rather than tell, please feel free to copy and amend the original PowerPoint slide here: https://github.com/PFython/WGACA-UK/blob/master/project%20management/Anvil%20Git%20Github.pptx

I see a common thread to every topic in (Unofficial) Anvil Version Control for Dummies

  1. Identification of a specific feature that varies from one [version of an] app to another.
  2. Identification of the source-code-level artifacts that go into that feature (app feature or Anvil feature), and where they can be found. In some files, these are just a fragment of the entire file.
  3. Using 2 to manage those artifacts, especially when Anvil’s default management does not do what’s appropriate in your specific case. This includes defining extra steps to perform, before and/or after an Anvil or Git action.

Do I have this abstracted properly?

1 Like

I think so, with the caveat that there might not be source-code-level artifacts (e.g. for data tables) to use.

1 Like

@jshaffstall, good catch! Thanks!

Yes, I can envision several app instances sharing some tables (e.g., to define prompts and help text) but not others (e.g., users). The distinction between shared and non-shared features/artifacts really is app-specific.

Revise that to “artifacts (source-code-level and otherwise)”.

1 Like

Yes, the complexities add up. Combine that with some of the resources needing duplicated for dev/prod splits and others being shared, and it’s tough to come up with a one-size-fits-all mechanism.

Putting all the resources into source code artifacts would help a lot, as would supporting more robust Git support in Anvil itself.

1 Like

Thanks for taking the time to read and think about my Tutorial, both.

I’m afraid your discussion has gone over my head though… Is there a Dummies’ level summary/recommended actions you think might be worth adding to the post? It’s now a forum Wiki so you should be able to edit directly… Maybe a new Level 12 entry?

Hi all,

I’ve merged a couple of other discussions into this thread that belong here, and reopened this thread now that it’s a wiki. Have at it!

2 Likes

Thank you, @meredydd. I would happily have posted here, had the topic been open.

This is more of an overview, a conceptual framework that your process fits into.

Let’s imagine that you have 2 Production apps, one for Customer A, and one for Customer B, each in its own Anvil repository. They are identical except for some customer-specific detail X, so A’s X and B’s X are different. (X may be a set of Secrets, a database table, a function or module, a logo, etc.)

When you need to update these apps (e.g., for a bug fix), you will need to preserve those distinct copies of feature X. To do that, you will need to know how Anvil represents them and/or refers to them, within each instance of the app, and how an update (e.g., git push) will affect those things. You may need to take steps before and/or after the update. The details will vary depending on how the feature is implemented, but this is the “big picture” that (I hope) every feature fits into.

Sometimes I need to see the trees. Sometimes I need to see the forest in order to understand the trees. :wink:

2 Likes

It’s tough to make a one-size fits all recommendation, since every app is a bit different.

The complexities in my case came from having a single “app” that was composed of multiple Anvil apps. This is a pretty typical pattern used with Anvil. One of my apps, for example, was for authors, another was for customers buying things, another was for readers, etc. These apps all shared some data tables (Users, for example, among others).

Splitting this combined app into Dev/Prod versions (at that time I wasn’t thinking in terms of test versions, since publishing Dev in Anvil worked fine for my testing) highlighted the complexities really well for me.

When you clone an Anvil app, the clone gets copies of the data tables used by the project it’s cloned from. In the case of a multi-app Anvil app that shares data tables, that means every Production clone of the various apps has its own copy of shared tables. You have to go through manually and fix that up. Luckily, that’s a one-time thing, but it’s complicated especially if you have data in the tables already and have linking fields to other tables.

Since data tables aren’t stored in the git repo you download, though, changes to those don’t get copied when you update Prod from Dev. You have to manually update the Prod data tables with changes made in Dev.

Specific steps I identified are in Cloning apps and data tables for Production and Development Apps - #4 by p.colbert I can’t even say that’s all of what would need done.

Anyway, it ends up being a mess, and I don’t think it’s in the For Dummies category. It was enough of a mess that I kind of stalled on development because migrating to Prod would have been error prone and time consuming.

There have been some feature requests that Anvil handle the Dev/Prod split more natively. I’m really hoping something along those lines is adopted because of the complexities in doing it manually.

2 Likes

Yes. My aim was to provide a way of thinking about an app’s features in a way that makes such reasoning easier. Maybe even amenable to automation.

For apps that “just happen” or are grown “organically”, it can be hard to identify where one feature begins and another leaves off. Even where features are added systematically, it sometimes happens that one body of code serves several interlocking features. So it’s not perfect. But the more we can isolate and separate things, the better chance we have of managing them deliberately (instead of mangling them accidentally!).

3 Likes

Until recently I had a setup similar to your diagram, with my DEV-TEST version shared to GitHub. But my latest thinking was that it would be better to have the PROD version on GitHub, for transparency’s sake. Otherwise no one would really know what code the PROD version is running, which I thought was part of the idea of open source?

Mine is just a solo project for the time being, but thinking ahead I guess pull requests to the PROD version on GitHub could be cloned to a new DEV/TEST version and tried out there before merging into the published branch on PROD?

1 Like