I am using Umbraco Formulate on Umbraco Cloud, and I'd like it to play a bit nicer with Umbraco Deploy.
That is, I want to be able to create a form on one environment, and then transfer it to another environment with Umbraco Deploy. I can already sort of do this so long as I make all changes to forms on my local environment, because I can then commit the forms to Git (forms are stored as files).
I'm not really sure how to go about this, but I'm thinking there are a few possible ways:
Value Connector Create a value connector so that when a page has a picked form is transferred, the form is transferred too (kind of like how media gets transferred if it's picked by a page). I'm not even sure if this is possible, but I could see this working.
Transfer Dialog I could create a dialog that, when you right click, allows a user to select "Transfer", and that will then transfer the form to the specified environment. This would treat forms more like data.
Commit to Git If there were some way to let Umbraco Cloud know about a newly created file, I could hopefully have Umbraco Cloud commit forms to the repo whenever they're created/modified/deleted. This would be treating forms similarly to how document types are treated (the difference being that the form on the file system isn't really a remnant, but it's the entity itself).
I have no idea how to go about any of this. Is there documentation to go through? Maybe a repo that shows one of these approaches working? Perhaps you have some knowledge of which approach is most viable?
Anything you can do to help to get me started would be appreciated.
Trouble is, it seems to only be for property editors. Formulate has its own section and doesn't really store much in the database (aside from the form picker property editor). I doubt it would show how to transfer files that don't exist in the database.
I would love to have the ability to notify Deploy about a newly created file, in order to get it committed. I have an issue here https://issues.umbraco.org/issue/UAAS-649
First off, thanks for that video. It might be enough to get me started, but I'll have to start digging in some code to see if I can make it work for my scenario.
Although the video was for Courier rather than Umbraco Deploy, I'm hoping that the concepts are essentially the same in Umbraco Deploy. From what I gather, there are two things I need to do:
Subclass ItemProvider I apparently need to subclass ItemProvider to make Umbraco Cloud aware of how to deal with my type of item (e.g., to serialize/deserialize).
Notification I need to send a notification to Umbraco Cloud using BasicEventManager.SendToCache so Umbraco Cloud knows that my item needs to be transferred.
Seems like this means I would transfer the form files over HTTP rather than via Git. It's unclear to me if this creates an item in the queue or if it just transfers instantly, but my guess is it tosses it in the queue. Or maybe it does toss it in Git (like it does with the file artifact that corresponds to a document type).
I will tinker with it a bit to see if I can figure something out, but I would still love if somebody with some experience in this area could point me in the right direction.
For example, since I'm dealing with files, maybe the right way to deal with it in my item provider is to add a dependency (maybe there is a built-in one for generic files) rather than serializing the already serialized form. It's still not super clear to me at this point.
Seems like ItemProvider and BasicEventManager do not exist in Umbraco Deploy, so that's a dead end.
I poked around the code and noticed something like this may be possible:
var service = default(Umbraco.Deploy.ISourceControlService);
service.AddFiles("name", "type", new[] { "file1.txt" });
This brings up some questions:
Interface Instance How do I get an instance of the class the implements that interface?
Name/Type What are the name/type parameters for?
Files What format should the files be in (e.g., c:\website\file1.txt or /file1.txt or ~/file1.txt)?
My hope is that I can use ISourceControlService.AddFiles to add files to Git when running on Umbraco Cloud. If somebody could provide some answers to the above questions, that would go a long way toward figuring this out.
I suppose I might also only want to call AddFiles() when in Umbraco Cloud (i.e., not when running on a local developer's computer), so if there is some boolean I can check to see if the current environment is Umbraco Cloud (e.g., CurrentEnvironment.IsUmbracoCloud), that may also be of use. Though, I could also see it being the case that AddFiles() already takes this into account. Hard to say without seeing the source.
Hmmm, no luck getting an instance of ISourceControlService so far. I tried to create a class that implements IValueConnector and that had an ISourceControlService parameter in the constructor, but I got an error message:
Not really sure I can get an instance of the class without using some brittle reflection shenanigans, and it may end up that this will not even work how I'm hoping.
Any help on this would be appreciated. I'm banging my head against a wall.
If you open Umbraco.Deploy.dll in dotPeek or similar, you can search for usages of ISourceControlService, and see how it is implemented. I did that, and it gave me an idea of what to do. I haven't tried if it works yet though.
I'm not sure if this breaches the license, so I'm not going to add more details for now :)
I noticed I can get an instance of ISourceControlService via Umbraco.Deploy.DeployComponent.SourceControlService. I'll toy with that a bit to see if I can make anything happen.
var service = global::Umbraco.Deploy.DeployComponent.SourceControlService;
var path = "~/App_Data/Formulate/Json/Forms/fb06ee9c2dc84512bc13e3679e23d3e1.form";
path = HostingEnvironment.MapPath(path);
service.AddFiles("fb06ee9c2dc84512bc13e3679e23d3e1.form", "Form", new[] { path });
The first two parameters of AddFiles are used to construct a message for the Git commit. In this case, that message would be Adding Form 'fb06ee9c2dc84512bc13e3679e23d3e1.form'.
I imagine they are also used in the Umbraco Cloud UI, but in that UI it just said "Worked on Other and changed one item" (I imagine because it doesn't recognize "Form" as a known type, it just defaults to referring to it as "Other").
I tried 7 variations of the file path, and the one in which I map the path using HostingEnvironment.MapPath was the only one that seemed to work (FYI, that's in the System.Web.Hosting namespace).
One other thing to note is that you'll need the Umbraco Deploy MyGet feed in order to install the UmbracoDeploy NuGet package (e.g., if you have a class library). You can ensure you have access to that feed by adding a NuGet.config file in the same directory as your Visual Studio .sln file with the following contents:
That will ensure you have access to both the normal NuGet feed as well as the Umbraco Deploy MyGet feed.
FYI, the AddFiles call only seems to do anything on Umbraco Cloud environments (i.e., it seemed to be unnecessary to add a check to see if a developer is running on their local).
Really, really wish this were documented. I suppose it now is, in a way.
Since it works, this is what I'll be going with for now. If anybody discovers an alternative at some point in the future, please do reply with that information.
You can also see that I'm calling RemoveFiles() when "Remove from Cloud" is clicked. One thing to note about RemoveFiles is that it both removes the file from Git and the file system. That was not clear to me at first, so I'll probably have to go back and make this a bit more sophisticated.
Transferring Non-Content with Umbraco Deploy?
I am using Umbraco Formulate on Umbraco Cloud, and I'd like it to play a bit nicer with Umbraco Deploy.
That is, I want to be able to create a form on one environment, and then transfer it to another environment with Umbraco Deploy. I can already sort of do this so long as I make all changes to forms on my local environment, because I can then commit the forms to Git (forms are stored as files).
I'm not really sure how to go about this, but I'm thinking there are a few possible ways:
I have no idea how to go about any of this. Is there documentation to go through? Maybe a repo that shows one of these approaches working? Perhaps you have some knowledge of which approach is most viable?
Anything you can do to help to get me started would be appreciated.
I do note that there is this repo: https://github.com/umbraco/Umbraco.Deploy.Contrib
Trouble is, it seems to only be for property editors. Formulate has its own section and doesn't really store much in the database (aside from the form picker property editor). I doubt it would show how to transfer files that don't exist in the database.
Hi Nicholas
There was a talk on this topic at Codegarden 16. You can see the video here: https://vimeo.com/channels/codegarden16/183620667
I would love to have the ability to notify Deploy about a newly created file, in order to get it committed. I have an issue here https://issues.umbraco.org/issue/UAAS-649
Hi Søren,
First off, thanks for that video. It might be enough to get me started, but I'll have to start digging in some code to see if I can make it work for my scenario.
Also, I've moved your issue over to GitHub since Umbraco is no longer using the old issue tracker: https://github.com/umbraco/Umbraco.Cloud.Issues/issues/33
Although the video was for Courier rather than Umbraco Deploy, I'm hoping that the concepts are essentially the same in Umbraco Deploy. From what I gather, there are two things I need to do:
Seems like this means I would transfer the form files over HTTP rather than via Git. It's unclear to me if this creates an item in the queue or if it just transfers instantly, but my guess is it tosses it in the queue. Or maybe it does toss it in Git (like it does with the file artifact that corresponds to a document type).
I will tinker with it a bit to see if I can figure something out, but I would still love if somebody with some experience in this area could point me in the right direction.
For example, since I'm dealing with files, maybe the right way to deal with it in my item provider is to add a dependency (maybe there is a built-in one for generic files) rather than serializing the already serialized form. It's still not super clear to me at this point.
Seems like ItemProvider and BasicEventManager do not exist in Umbraco Deploy, so that's a dead end.
I poked around the code and noticed something like this may be possible:
This brings up some questions:
c:\website\file1.txt
or/file1.txt
or~/file1.txt
)?My hope is that I can use
ISourceControlService.AddFiles
to add files to Git when running on Umbraco Cloud. If somebody could provide some answers to the above questions, that would go a long way toward figuring this out.I suppose I might also only want to call
AddFiles()
when in Umbraco Cloud (i.e., not when running on a local developer's computer), so if there is some boolean I can check to see if the current environment is Umbraco Cloud (e.g.,CurrentEnvironment.IsUmbracoCloud
), that may also be of use. Though, I could also see it being the case thatAddFiles()
already takes this into account. Hard to say without seeing the source.Hmmm, no luck getting an instance of
ISourceControlService
so far. I tried to create a class that implementsIValueConnector
and that had anISourceControlService
parameter in the constructor, but I got an error message:Not really sure I can get an instance of the class without using some brittle reflection shenanigans, and it may end up that this will not even work how I'm hoping.
Any help on this would be appreciated. I'm banging my head against a wall.
Hi Nicholas
If you open Umbraco.Deploy.dll in dotPeek or similar, you can search for usages of ISourceControlService, and see how it is implemented. I did that, and it gave me an idea of what to do. I haven't tried if it works yet though.
I'm not sure if this breaches the license, so I'm not going to add more details for now :)
Hi Søren,
I'd love to hear what you discovered. Can you send me a message here? https://code101.net/contact/
I noticed I can get an instance of
ISourceControlService
viaUmbraco.Deploy.DeployComponent.SourceControlService
. I'll toy with that a bit to see if I can make anything happen.I figured it out!
This is what you need to do:
The first two parameters of
AddFiles
are used to construct a message for the Git commit. In this case, that message would beAdding Form 'fb06ee9c2dc84512bc13e3679e23d3e1.form'
.I imagine they are also used in the Umbraco Cloud UI, but in that UI it just said "Worked on Other and changed one item" (I imagine because it doesn't recognize "Form" as a known type, it just defaults to referring to it as "Other").
I tried 7 variations of the file path, and the one in which I map the path using
HostingEnvironment.MapPath
was the only one that seemed to work (FYI, that's in theSystem.Web.Hosting
namespace).One other thing to note is that you'll need the Umbraco Deploy MyGet feed in order to install the
UmbracoDeploy
NuGet package (e.g., if you have a class library). You can ensure you have access to that feed by adding aNuGet.config
file in the same directory as your Visual Studio.sln
file with the following contents:That will ensure you have access to both the normal NuGet feed as well as the Umbraco Deploy MyGet feed.
FYI, the
AddFiles
call only seems to do anything on Umbraco Cloud environments (i.e., it seemed to be unnecessary to add a check to see if a developer is running on their local).Really, really wish this were documented. I suppose it now is, in a way.
Great that you got it working!
I was going in another direction by reimplementing the AddFiles method, but never got to try it out. Your solution seems a lot better!
Yep, it does seem like the best way to go at present, even if it is "accidental" and "undocumented": https://github.com/umbraco/Umbraco.Cloud.Issues/issues/33
Since it works, this is what I'll be going with for now. If anybody discovers an alternative at some point in the future, please do reply with that information.
If anybody is curious to see a working implementation, I just made one:
Clicking "Store to Umbraco Cloud" calls
AddFiles()
: https://github.com/rhythmagency/formulate/commit/ea5228404f257350b18779157f6c10756f41eb52You can also see that I'm calling
RemoveFiles()
when "Remove from Cloud" is clicked. One thing to note about RemoveFiles is that it both removes the file from Git and the file system. That was not clear to me at first, so I'll probably have to go back and make this a bit more sophisticated.is working on a reply...