Jump to content




Github Auto Updating (For the new guys)


7 replies to this topic

#1 nateracecar5

  • Members
  • 94 posts

Posted 30 March 2014 - 08:41 PM

There is some indentation issues in some of the code objects. Sorry about that! Will fix when I feel like it is a problem.

EDIT: For anyone using this in CC v1.63+, in the config you need to disable the domain whitelist for this tutorial to work. It will look like this:
# A semicolon limited list of wildcards for domains that can be accessed through the "http" API on Computers. Set this to "*" to access to the entire internet.
S:http_whitelist=*pastebin.com;*computercraft.info

Set it to "S:http_whitelist:*" and you should be all set

Hi everyone! This is my first tutorial, so I hope you enjoy it! We are going to be creating a Github auto updater for your programs! This will include the installer, and the update checker. You will need a couple of things:

- A github account
- Github Shell (Or Github Desktop, which is what I use personally)
- A computercraft emulator or the ingame mod (Duh ;D )
- The HTTP api will need to be enabled

First, we will be making the installer. This will be a bare minimum, and will only have the checking and downloading. We will not be making this look fancy, and it will only download a program with the command:
print("Hello world!")
We will then create a program which has the update checking in it, and opens the installer.

Let's begin!

In the updater, we want to create a function called "downloadFiles". This function will have the arguments url, and path. It will look like this:
local function downloadFiles(url, path)
end

The url is the url of your download link, and the path is where you want it to go. Now we will create a loop. This will check 3 times to see if there is a download. Inside that update loop, we will have a response variable that equals http.get(url). We will then add an if statement checking if response is true. Your current code should look like this:
local function downloadFiles(url, path)
  for i = 1, 3 do
	local response = http.get(url)
	if response then
	end
  end
end

Now, since we already check if response, we will now get the data from the response, and store it in a data variable. We will then check if there is a path, that way we don't have data just sitting around. Your code should look like this:
local function downloadFiles(url, path)
  for i = 1, 3 do
	local response  = http.get(url)
	if response then
	  local data = response.readAll()
	  if path then
	  end
	end
	return true
  end
end

See that return true? That's just going to return so we know that there was a response. There should always be a path, or the function will just error, but it's safe to check anyway.

Now we will add the part of the function that puts the data in a file. We will be using the IO api for this. We will create the variable f, which will equal io.open. We will then write that file and close it. It is required that you close a file, or some things could break. Not just the computer, but you won't be able to delete it from your computer's native explorer until you close Minecraft. Your current code should look like this. This is the finished function:
local function downloadFiles(url, path)
for i = 1, 3 do
  local response = http.get(url)
  if response then
   local data = response.readAll()
   if path then
	local f = io.open(path, "w")
	f:write(data)
	f:close()
   end
   return true
  end
end
return false
end

Notice that return false? You might think that after returning true, it returns false. What's up with that? Well, after a function returns, it breaks out of the function, and completes it. If it returns true, then the function will be complete, and not finish the loop. If it doesn't, it will loop three times and then return false. Now you have to use this function to download your files. We will do that later, because we will need to post 4 files to github.

Save this file, and call it installer.


Now we will start on update checking! We will create a new file, and call it checker. To start, open checker and copy the downloadFiles() function into it. This is important, because if the installer is deleted, we will redownload it. The installer is one of the three files we will put on github.

Now to start. We want to create a checkForUpdates function, which will take one argument, and that will be updateUrl. Your new function should look like this:
function checkForUpdates(updateUrl)
end

Now, we will do the same loop, and the same response check, along with the same data check. You can go ahead and copy that from the downloadFiles function. Your function should now look like this:
function checkForUpdates(updateUrl)
for i = 1, 3 do
  local response = http.get(updateUrl)
  if response then
   local data = response.readAll()
   if data ~= currentVersion then
   end
  end
end
end

Do you see that line that says "if data ~= currentVersion"? We will put a variable at the top of this program, called currentVersion that will hold our version number. The data from the file we will check will be another version number. If these versions do not match, we will update. In order to have a successful update, when you post your new code to github, make sure both files have the same version. Anyway, your code should look like this:
currentVersion = 1.0
function checkForUpdates(updateUrl)
for i = 1, 3 do
  local response = http.get(updateUrl)
  if response then
   local data = response.readAll()
   if data ~= currentVersion then
   end
  end
end
end

Now we want to check if we have the installer. If we don't, we will download it. If we do, we will go straight to it. To do this, we will check if the installer exists using the FS api. Your code should look like this, and the function will be finished.
function checkForUpdates(updateUrl)
for i = 1, 3 do
  local response = http.get(updateUrl)
  if response then
   local data = response.readAll()
   if data ~= currentVersion then
   print("There's an update!!!")
   sleep(1)
	if not fs.exists("/installer") then
	 downloadFiles("https://raw.github.com/redstonefreak589/redos/master/installer", "/installer")
	end
	shell.run("/installer")
   end
  end
end
end

See that link? That is the link to my RedOS installer. You may download it if you like. You will also see the link to that project in my signature. Go check it out! Your whole program should look like this now:

currentVersion = 1.0
local function downloadFiles(url, path)
for i = 1, 3 do
  local response = http.get(url)
  if response then
   local data = response.readAll()
   if path then
	local f = io.open(path, "w")
	f:write(data)
	f:close()
   end
   return true
  end
end
return false
end
function checkForUpdates(updateUrl)
for i = 1, 3 do
  local response = http.get(updateUrl)
  if response then
   local data = response.readAll()
   if data ~= currentVersion then
	print("There's an update!!!")
	sleep(1)
	if not fs.exists("/installer") then
	 downloadFiles("https://raw.github.com/redstonefreak589/redos/master/installer", "/installer")
	end
	shell.run("/installer")
   end
  end
end
end

Now, we are finished with that file for now. You may be wondering "The functions don't get called, and I don't know what this version file you're talking about is!!" Well, let me get to that. We want to create a new file called "version". This will only have 1 line, and it is:
1.0

See where I'm going with this? The checkForUpdates function will check if there this file's version number, and compare it to the local variable. If it isn't the same, it will download a new file. Careful: you can create infinite loops if you change the version file's number, and not the currentVersion number. :)

Now go to github, and upload that version file to your repository. I will not create a tutorial on this. To get a raw version of the file, where all that's on the page is that number, you will want to create this url:
raw.github.com/<username>/<repository>/master/version

The username is your username, and the repository is the name of the repository you uploaded the file to. Version is the name of the file. If you changed the version file name, put that name in place of the version in the url. Now we will finish the checker file.

At the bottom of checker, we want to add the update checking function. All we do now is call the function!
checkForUpdates("http://raw.github.com/redstonefreak589/redos/master/version")

Remember that is the link to my version file. Make sure to add the http:// to the url! Your FINAL checker file should look like this:
currentVersion = 1.0
local function downloadFiles(url, path)
for i = 1, 3 do
  local response = http.get(url)
  if response then
   local data = response.readAll()
   if path then
	local f = io.open(path, "w")
	f:write(data)
	f:close()
   end
   return true
  end
end
return false
end
function checkForUpdates(updateUrl)
for i = 1, 3 do
  local response = http.get(updateUrl)
  if response then
   local data = response.readAll()
   if data ~= currentVersion then
	print("There's an update!!!")
	sleep(1)
	if not fs.exists("/installer") then
	 downloadFiles("https://raw.github.com/redstonefreak589/redos/master/installer", "/installer")
	end
	shell.run("/installer")
   end
  end
end
end
checkForUpdates("http://raw.github.com/redstonefreak589/redos/master/installer")

Now, remember how I said we will create a program that says hello world? We will create that and upload it to github. There will not be a tutorial on this part, because it's straight forward. Just create the program, call it "hi", enter the command "print("hello world!")", and upload. Plain and simple.

Now, go back to the very first program we created, the installer. At the bottom of it, we want to initialize the download command, so we will add the following to the bottom of it:
downloadFiles("http://raw.github.com/redstonefreak589/redos/master/redos", "/redos")

The first string/argument is the link to the file. The second one is the file to put it in. I put a slash in front to represent root. To create your download link, just change the following like above:
http://raw.github.com/<username>/<repository>/master/hi
.

Remember we called the program hi, so that's what we are using in our URL. The final file should look like this:
local function downloadFiles(url, path)
for i = 1, 3 do
  local response = http.get(url)
  if response then
   local data = response.readAll()
   if path then
	local f = io.open(path, "w")
	f:write(data)
	f:close()
   end
   return true
  end
end
return false
end
print("Downloading...")
downloadFiles("http://raw.github.com/redstonefreak589/redos/master/redos", "/redos")
downloadFiles("http://raw.github.com/redstonefreak589/redos/master/desktop", "/desktop")
print("Download complete!")

I'm using example links from my project for this, but you should use your own.

Upload this to github, and call it installer. This is VERY important you call it installer. Now, go back to the checker file we created, and will will finish it up. See how I checked for the checker file as well? When we update our program, we want to grab the updated version of checker, because that will have a changed versionNumber variable in it to make sure it doesn't check again. Now run checker. It doesn't work right? Good! That's because both the version file and the versionNumber variable equal each other. Now, create a copy of checker, and change the version number in it. Change the version number in our version file to the same thing. Now reupload the copy of the checker file we made and the version file to github. If you run checker again, you will see it opens the installer, pulls the new checker file, and pulls the hi file. You have successfully created an update checker! Please tell me if there is anything wrong with this tutorial, or if you have any bugs that pop up along the way.



To create an update to your program, just change both version numbers in your checker, and your version file, and modify your hi file. Now upload them all to github, and you have a working, breathing (Not really) github update checker!

Edited by nateracecar5, 17 July 2014 - 06:24 PM.


#2 Engineer

  • Members
  • 1,378 posts
  • LocationThe Netherlands

Posted 05 April 2014 - 01:20 PM

This is so-called the hardcoded type of updating. You only update existing files, what if someone adds a file with development?
For that you can use the Github API, especially this link: https://api.github.c...ch>?recursive=1

Then you can parse yourself through the JSON and get the filenames/directories. I have done this in an installer I made (not published on the forums, though it is somewhere on github ;) ), and it is simpler than you think it is. You dont need a JSON API to do that, just 3 gsub calls and a loadstring.

That way you retrieve all files from the repo and the program functions better. I could write an extension to this tutorial about that, but I wont. Im pointing it out so you can do it!

#3 Sir_Mr_Bman

  • Members
  • 62 posts

Posted 05 April 2014 - 04:48 PM

Looks like a great tutorial! Too bad I already figured it out on my own... : P

Nice job on this! *upvote*

#4 apemanzilla

  • Members
  • 1,421 posts

Posted 07 April 2014 - 05:37 PM

View PostEngineer, on 05 April 2014 - 01:20 PM, said:

This is so-called the hardcoded type of updating. You only update existing files, what if someone adds a file with development?
For that you can use the Github API, especially this link: https://api.github.c...ch>?recursive=1

Then you can parse yourself through the JSON and get the filenames/directories. I have done this in an installer I made (not published on the forums, though it is somewhere on github ;) ), and it is simpler than you think it is. You dont need a JSON API to do that, just 3 gsub calls and a loadstring.

That way you retrieve all files from the repo and the program functions better. I could write an extension to this tutorial about that, but I wont. Im pointing it out so you can do it!
Here's a program I wrote a couple weeks ago that uses that method. It can also function as a GitHub program installer and updater....

Edited by Apemanzilla, 07 April 2014 - 05:37 PM.


#5 Engineer

  • Members
  • 1,378 posts
  • LocationThe Netherlands

Posted 07 April 2014 - 07:04 PM

View PostApemanzilla, on 07 April 2014 - 05:37 PM, said:

Here's a program I wrote a couple weeks ago that uses that method. It can also function as a GitHub program installer and updater....
Though it uses a full JSON api... You only need a few gsub calls and you can load it as table

Edited by Engineer, 07 April 2014 - 07:04 PM.


#6 apemanzilla

  • Members
  • 1,421 posts

Posted 07 April 2014 - 08:26 PM

View PostEngineer, on 07 April 2014 - 07:04 PM, said:

View PostApemanzilla, on 07 April 2014 - 05:37 PM, said:

Here's a program I wrote a couple weeks ago that uses that method. It can also function as a GitHub program installer and updater....
Though it uses a full JSON api... You only need a few gsub calls and you can load it as table
I was too lazy to write it myself and just download a JSON API, never really thought I'd be releasing it anyways which is why there's minimal error catching and it uses external APIs :P

#7 nateracecar5

  • Members
  • 94 posts

Posted 17 July 2014 - 03:29 AM

It's been a while since I've checked this website, since I've become inactive for quite some time. Didn't think anyone would actually use this, and the feedback I've gotten is much appreciated! Thank you all who read this. It really means a lot that I'm actually getting responses out to the community.

#8 hbomb79

  • Members
  • 352 posts
  • LocationOrewa, New Zealand

Posted 21 July 2014 - 05:53 AM

Wait so do i make a different file or not because you sat to then you show them both in the same section and dont call the program name with shell.run or an API

EDIT: I think i understand a bit now...

Edited by Hbomb_79, 21 July 2014 - 05:57 AM.






1 user(s) are reading this topic

0 members, 1 guests, 0 anonymous users