synhershko / NAppUpdate

A simple framework for providing auto-update support to .NET applications
http://www.code972.com/blog/2010/08/nappupdate-application-auto-update-framework-for-dotnet/
Apache License 2.0
525 stars 163 forks source link

Update feed generator #9

Open synhershko opened 13 years ago

synhershko commented 13 years ago

Create and support an update feed generator functionality.

Here's a very initial take on what I consider to be a flexible and effective approach. Would love to hear any thoughts:

  1. Pointed to an application directory containing a NAppUpdate DLL, the feed-generator desktop application will use Reflection to detect all objects implementing IUpdateTask, IUpdateCondition and IUpdateSource in all assemblies in that folder. It will then list them in a nice organized manner (TBD), and allow the creation of complex feeds in a simple graphical UI.
  2. Explanatory text to be displayed by the application for each task / condition / source type will be available through fields we will add to the interfaces, and each implementing object will have to provide. Another option is to use a class-scope attribute. This text will then be displayed in tooltips etc.
  3. The rest of the fields in each object will use attributes to signal the feed generator their exact state - if they are required, what's their expected input (regex?), validation type (?), and explanatory text (to be displayed in forms by the input fields). I will provide concrete examples at a later time.
  4. Output will be in the NauXml format (which should be standardized further prior to any release of such application). I don't think there is any reason to support any other formats.
  5. NauXml Feeds should be able to be read into this application. This perhaps will need some code adjustments in the core, and will also allow to load other feed types.
  6. It would be nice if we could create all that in a such a way so it could be used by a web application too, at least partially, to allow feed updates on the fly.
gleb-sevruk commented 13 years ago

At now we have only file update tasks? It can be gui-application, that read directory with application exe, and subdirectories, then, reflect over assemblies versions, and generate minimalistic feed? Than user can add more condition to each file?

synhershko commented 13 years ago

At now we have only file update tasks?

Yes, but you can't rely on that. More tasks could be RegistryUpdateTask, InstallServiceTask,..., you get the point. This is why the work has to be done in the interfaces scope.

It can be gui-application, that read directory with application exe, and subdirectories, then, reflect over assemblies versions, and generate minimalistic feed? Than user can add more condition to each file?

The feed generator will only display the user with all available options for tasks and conditions (this is where Reflection comes in). Then the user will use the app to create tasks. He will also be able to put conditions on them. The feed generator is just the tool to present the user with his options and let him set the configurations as per his requirements.

gleb-sevruk commented 13 years ago

At this point I can't get how to automatically generate tasks, differs from FileUpdate. Maybe it should be done manually? Specify reg file, service installer, or sql-changescript?

synhershko commented 13 years ago

Quite simple, by reflecting on the objects structure to detect the exposed fields which the user will fill them in. I'm doing some work on the library to get it there, will update when it'll be ready.

gleb-sevruk commented 13 years ago

Can I start some work dedicated to feed genarator application?

synhershko commented 13 years ago

I guess you can start with the UI. I checked in my current work, this will not necessarily look like this when I'm done, but thats the general idea:

https://github.com/synhershko/NAppUpdate/tree/better-tasks

ghost commented 13 years ago

I've made a bit of a start on this - I couldn't see anything from Excelion, so I've just made my own fork.

At this stage it reflects over a directory, looks for IUpdateTask and IUpdateCondition. I'm new to NAU, so I'm not entirely sure where IUpdateSource should be placed (per-item, as a "global" setting for each feed, etc). I had a quick peek in better-tasks, and noticed that those changes are "old" compared to the master branch, so I've stopped before inspecting attributes. (And I'm new to Git - I'm used to Hg, and the tooling is pretty different - so merging away didn't sound too fun ;))

feed generator v1

As it may look, it's very much "draft 1" style UI - is this the sort of thing you had envisaged though?

From a continuous integration point of view, I think abstracting it out so it works as a GUI/desktop app, web app and a MSBuild task (I use MSBuild for the project I've got in mind, so that'd be easier for me). That level of automation may require an additional file/set of rules to pass in a bunch of file hashes of the previous version. eg, If v1 of my app ships with XYZ external dependencies, they may not ever change nor are being recompiled so the hashes will match and shouldn't be updated.

synhershko commented 13 years ago

The better-tasks branch should have made things a bit more generic and easy to use in tools like this by being able to reflect on properties too. Need to review it again and either finish or discard.

As I see this, tasks are not file-based. So you should be able to create a task, and only if its a FileUpdateTask allow for selecting which file to update etc. All Conditions are relevant to all sort of tasks, even file-based conditions.

I agree with the abstraction requirement - I was actually aiming at that direction (see #6 above).

I'm a bit swamped at the moment, would you mind if I'll get back to you on this also with some more work from my side in about 3 weeks from now?

ghost commented 13 years ago

No stress. :)

In the meantime, I'll try and invert the UI/flow to be task based. Now you've explain that, it makes much more sense - my history with auto-updating is really just ClickOnce (which is file based only), which has led me to NAU ;)

As for the better-tasks branch, yes, I agree that its much easier to reflect the properties and attributes of, but as my first delve into Git I forked from the wrong branch. As I mentioned, the tooling is vastly different so things didn't reaaaally go the way I wanted to. To get the ball rolling, though, I think something like this is an 'ok' starting point.

synhershko commented 13 years ago

Sorry about the delay, but this would take a bit longer. Will keep you posted.

synhershko commented 13 years ago

OK, I just pushed an update for this, that should get you going good.

The new way it works is as follows: IUpdateTask and IUpdateCondition both extend INauFieldsHolder. This tells NAU the task and condition objects have attributes that need populating; those properties are decorated with NauFieldAttribute. The reader then feeds them with data from the feed. Previously it worked in a much less flexible way with a Dictionary object, which is now gone.

Every such property has an alias and a description that are hardcoded in the class code. It also allows you to specify which attribute is mandatory and which is not. By design, a mandatory attribute that is not set is ignored (always returns true if a condition, or does nothing if a task). The developer creating the task/condition creates those attributes and describes them in code, and this info is then available to you through reflection from any feed generator implementation. See FileUpdateTask and Utils.Reflection for some samples in code.

The only thing missing now, as far as I can tell, is a task group, and I will add it soon.

Let me know how it sounds, and whether I missed anything.

ghost commented 13 years ago

Thanks, I'll hopefully get a chance to look at this again last this week.

ghost commented 13 years ago

Man, that's some horrible English I had going there in my last comment. Uhh, I meant I'd try and get back to it later in the week - well, last week now. Aaaanyway..

NauField looks great, combined with the property type, it'd be (relatively) easy to put up a checkbox (bool) or textbox (text/int). The only issue from the GUI generation side is that I can see is that LocalPath (on FileUpdatePath) should have a file browser. This is where it could get interesting, could either assume that if a property is a string and has a Path suffix that it's a file and a textbox+browse button UI should be generated, or just hard code in some extra rules for FileUpdateTask.

How does this process sound for the GUI app?

  1. File -> New Update, select base folder, reflects to populate collections
  2. On the left half,
    1. Textboxes for filling in details about the update/NAU feed file
    2. A listbox where tasks assigned to the update will appear
  3. On the right half, the "current" task being added, with a dropdown at the top of that half with all the available tasks.
  4. When a task is selected, UI updates to reflect properties that must be set, Add Task adds it to the 'Update' collection of tasks.
  5. When done, user clicks Build/Save/Something to generate NAU update file.

I haven't sold myself on it yet, which is why there isn't a better mockup ;)

synhershko commented 13 years ago

Good point on Paths. Perhaps we can use a Path object? or introduce another variable to the attribute? will be cleaner than parsing the prop name. I think making the prop of type Path is our best option here.

I was actually thinking about a more visual approach - something like a toolbar to the left where you can drag tasks and conditions to a panel on the right, and once dragged they will be displayed as forms (based on reflection on their props). This will assure a very smooth process, and the current code structure already allows that.

ghost commented 13 years ago

Path object is a much better idea!

What you're describing for the GUI sounds similar to GraphEdit (somewhat obscure, for building DirectShow filter graphs), while I like the idea, I shudder at how to implement it. I'll do some reading up, but I've always hated doing drag and drop stuff ;)

synhershko commented 13 years ago

Me too, GUIs and desktop apps make me shrug.

On Thu, Sep 1, 2011 at 4:10 PM, aeoth < reply@reply.github.com>wrote:

Path object is a much better idea!

What you're describing for the GUI sounds similar to GraphEdit (somewhat obscure, for building DirectShow filter graphs), while I like the idea, I shudder at how to implement it. I'll do some reading up, but I've always hated doing drag and drop stuff ;)

Reply to this email directly or view it on GitHub: https://github.com/synhershko/NAppUpdate/issues/9#issuecomment-1967847

jesuswasrasta commented 13 years ago

Hi! I'm looking for an auto-update solution for a .NET application, and your solution seems to be good for me. Sorry for the (probably) noob questio: where can I find documentation on writing my own xml Feed, Tasks and so on? Have you some resources where to point me?

Just to back on topic, there's a working alpha of this GUI Update feed generator?

Thank you, and congratulations for this very good piece of software! :-)

gleb-sevruk commented 13 years ago

All you need to do - is to change assembly version in project properties. Then create a folder with all NEW files, put xml feed there. Then invoke update from client program.

In feed just put file name, and assembly version, greater than client's version. It is for files - just copy-paste each.

For tasks, i.e. run update script to database, don't sure. You can track db version in database, and embed update scripts in resources script from 1.0 to 1.1, than 1.1 to 1.2, so on.

jesuswasrasta commented 13 years ago

Thank you. I posted a more specific request on Google Group: http://groups.google.com/group/nappupdate/browse_thread/thread/efd0de05553114c7

I want to do a simple task: copy all my assemblies in a tmp folder, then do a cold update about all of them, with no particular condition. There's a way to do a similar job?

I'm new on this project; I think something like this, using the star-key on updateTo attribute: < ?xml version="1.0" encoding="utf-8" ? > < Feed > < Tasks > < FileUpdateTask apply="app-restart" updateTo="my\application\folder\updates*" localPath="my\application\folder\binaries\" > < Description>New version bla bla bla...< /Description> < /FileUpdateTask > < /Tasks > < /Feed >

Can someone point me on the right direction? Thank you, Nando

synhershko commented 13 years ago

Nando, thanks

Not many docs available at the moment, working on it.

As for the Feed Generator, thats a question for @aeoth.

Will answer your question in the mailing list

jesuswasrasta commented 13 years ago

Thank you Itamar. Just to drive away my doubts: no way to to a FileUpdateTask using star, like "copy alla file from folder X to folder Y"? I have to play with source code, indeed :-)

synhershko commented 13 years ago

Wrong thread for this discussion, please see my reply to the mailing list

On Wed, Oct 12, 2011 at 4:09 PM, jesus-was-rasta < reply@reply.github.com>wrote:

Thank you Itamar. Just to drive away my doubts: no way to to a FileUpdateTask using star, like "copy alla file from folder X to folder Y"? I have to play with source code, indeed :-)

Reply to this email directly or view it on GitHub: https://github.com/synhershko/NAppUpdate/issues/9#issuecomment-2379551

jesuswasrasta commented 13 years ago

Ops, sorry, thanks.

AdamWorld commented 12 years ago

Hi! I'd like to thank you for what you did. Now where can I get update feed generator? I try to find in @aeoth but I couldn't find. Help me. Thank you.

synhershko commented 12 years ago

https://github.com/aeoth/NAppUpdate/tree/feedgenerator

AdamWorld commented 12 years ago

Thank you for quick response. I run it but i think it is not completed. Comboitems are empty, and nothing to select , nothing to be generated. Should I change code to complete your work? (I hope at least feed.xml would be generated) Thank you.

synhershko commented 12 years ago

Yes you can probably take this up from where @aeoth stopped. There's some discussion above you probably want to read.

AdamWorld commented 12 years ago

Hi!

  1. There three brunches(Master, feedgenerator,...) and the sources are different between Master brunch and Feedgenerator one. What should i use for most up to date source?
  2. And may i modify some source and inform you the changes?
  3. I have a problem for subdirectory structure. <FileUpdateTask apply="app-restart" updateTo="file:///d:/1/Images/song_bg.jpg" localPath="Images/song_bg.jpg" As you can see there is subdirectory "Images". When I use that task, app doesn't succeeds. Would you give me a hint for that?

Thank you.

synhershko commented 12 years ago

Answered in the mailing list

drewkeller commented 12 years ago

Where is the feed generator stuff? Github can't seem to find the urls in the above comments.

synhershko commented 12 years ago

Unfortunately the authors seem to have deleted it. Some may still be available, see https://github.com/synhershko/NAppUpdate/network

There is no official feed generator in upstream

drewkeller commented 12 years ago

I haven't used Github much. The network view is pretty cool.

I found a branch on the network that was added a month ago by TrickUK with what he calls a crude feed generator: https://github.com/TrickUK/NAppUpdate

synhershko commented 12 years ago

@drewkeller @phillipp good work on the FeedBuilder, I pulled it now

The workflow you assumed is not how I originally envisioned it. See the full discussion above, but basically we can't really assume a simple deploy process where all update tasks are FileUpdateTask and files are all present locally. For example, how would you allow use of RegistryTask or other custom tasks?

This is the main reason why I moved the tasks and conditions to heavily rely on reflection - the intention was that to have the feed generator automatically detect all available tasks and conditions and show them as available tools. Then it would allow you to build your feed using drag and drop or something similar.

Any chance you will support that as well? let me know if I can help in any way.

vbjay commented 9 years ago

I think using mef is the way to set this up.https://msdn.microsoft.com/en-us/library/dd460648(v=vs.110).aspx