Guide: Automagically package and publish addons
DISCLAIMER
The TravisCI section of this guide is no longer maintained, as the majority of the community has moved over to use GitHub Actions instead. The rest of this guide is still valid, but if you want to use GitHub actions instead of TravisCI please see this: https://github.com/BigWigsMods/packa...tions-workflow Original post: Any seasoned developer will agree that automating repetitive tasks is a good idea, and one of the most repetitive things we do as addon developers is publishing addon updates. This guide will instruct you how you can automate packaging and publishing new releases, so you can focus more on developing the addon itself. With this tool, addons can be published at the two major addon sites; CurseForge/WoWAce (and thus Curse), and WoWInterface. Addons can also be published (packaged) on GitHub in case you'd also want that. To do this we're going to rely on a few tools. Tools You've probably already heard of Git, it's basically a tool to keep track of changes done to your project's code, among other things. If you've heard of (or used) Git, you've probably also heard of (and used) GitHub, an online service that lets you host your Git repositories in the cloud. But you've probably not heard of Travis CI, it's a tool exclusively made for GitHub that lets developers run automated tests on their code. We'll be using this to package and release our addon(s). Last but not least there is the BigWigs packager script which will do all of the actual work for us. These tools combined will automatically do everything you would normally do when publishing a new version for your addon(s), such as increasing the Version field in your TOC file, fetching localization, embedding libraries and more, then finally zip everything and publish. How it works After the setup (see the next two posts), the following happens:
So, all you have to do (once set up) is to push to GitHub with a tag, like so: git tag -am "Tag v2.0" v2.0 && git push origin master --tags I'm not going into how to use Git and GitHub, there are plenty of guides that will explain that better than I can do here, so I'm going to focus on the specifics for the actual packaging tools; Travis CI and the packager script. Sidenote: You don't have to use GitHub and Travis CI, you could just as well just run the script locally, or use it with other CI tools for GitLab or Bitbucket, but this guide focuses on GitHub and Travis CI. |
2 Attachment(s)
Travis CI Setup
Visit the Travis CI website and log in by authenticating it with GitHub. Once authenticated you can visit your profile page where you'll find a list of all your repositories on GitHub. To enable Travis CI for a project, find it in this list, then "Settings" button next to it. In here you'll want to make sure only "Build pushed branches" is enabled, like so: Further down on this page you'll find a section called "Environment Variables", here you'll enter your credentials for each site you want your addons to be released at. Here's a list of what to put in the "Name" and "Value" boxes:
Here's an example: Once that's set up you'll need to create a ".travis.yml" file in the root of your repository, right next to your TOC file. The naming of this file is crucial, as well as this content: YAML Code:
All this file does is letting Travis CI know what to do; Install the required software, download the packager script and run it. The only thing you need to keep in mind here is the "branches" part. This will make sure that Travis CI only runs when there is a new tag. It checks this by looking at the name of the branch (tags are techically branches), then uses regular expressions to match it against your versioning schema. You'll most likely need to tweak this to your own versioning schema, reply and I'll assist you. And that's it for the Travis CI part! |
1 Attachment(s)
Customizing the packaging
This part is specifically for instructing the packager on how to package your addon, and where it should upload to. TOC You'll need to add additional fields to your addon's TOC file, this will let the packager know where to upload your packaged addon to. You do this by finding the appropriate "IDs" for the various supported sites and adding them to the TOC file. The WoWInterface ID is easy to find, it's in the URL for your addon. E.g. "22213" in wowinterface.com/downloads/info22213-BonusRollPreview. For CurseForge you'll find it as "Project ID" under "About This Project" on the project page. E.g. "54902" for wow.curseforge.com/projects/bonusrollpreview. Add the ones you want to release on to the TOC file with their respective field names, here's an example: TOC Code:
Packager Metadata This file will deal with additional (all optional) things you'd like the packager to do to your packaged addon, be it embedding external libraries, creating changelogs automatically, etc. This is all done in a new file named ".pkgmeta" which needs to be located at the root of your addon, next to the TOC file. Here's a link to documentation on what you can include in this file: https://authors.curseforge.com/knowl...ckagemeta-file An example where I specify some libraries it should include: YAML Code:
In addition to this file, additional substitutions can be done to your addon's files (not just the TOC file), such as filling in the Version field in the TOC file to your latest tag, inserting localizations from CurseForge, and much more. More info: https://authors.curseforge.com/knowl...-substitutions I personally always use the automatic versioning, so my TOC file looks something like this (note the version field): TOC Code:
And that's it! Now you can tag and push to GitHub and the packager will do everything else! |
Reserved. 10chars
|
If you're having trouble making the .pkgmeta and .travis.yml files, do the following:
1. Open up a terminal (e.g. Git Bash on Windows) in the root directory for your addon. 2. Type/paste in the following: touch .pkgmeta .travis.ymlWindows is kind of backwards when it comes to naming files, this solves that. |
Nice, i was recently thinking about doing this, i just wasn't sure if this is even properly possible atm without hacks or not. Definitely gonna try it later.
|
I've a question regarding the Travis CI part:
I already have a simple travis.yml (based on https://github.com/WeakAuras/WeakAur...er/.travis.yml), all it does is run luacheck to catch any syntax errors if I forgot to run my offline build tools (which should be done automatically, but I haven't gotten around to that yet). Can I just add the relevant parts to it without adding the "language: c" part, or must I add it for this script to work? Will it interfere with the execution if I do add it? Basically, I would want to combine the two to run the syntax check first and then deploy the file. Also, for the regular expression: My tags are usually named rXX-(alpha|beta)?(-YY), such as r21-beta-3 or r25-alpha or simply r27/r27-2/etc. (a release version). This was mostly so that Curse can detect the alpha/beta/release state properly, as I'm using their API via GitHub webhooks. The packager script apparently would consider all of them beta, and worse still, package untagged commits as alpha versions when they aren't ready for deployment at all. Now, I think the branches option would filter out the untagged commits, but how do I have the script package as alpha/beta/release correctly without forking/modifying it or changing my versioning scheme? Maybe Travis could detect them and rename it before calling the script? |
Quote:
and the "default" language is (afaik) Ruby. There is a "language: generic" that I'd prefer to use, but it's not documented so I'm staying away from using it. You can add multiple scripts, but I'd recommend you use "after_script: " for the packager, to make sure that luacheck finishes first. Quote:
https://github.com/BigWigsMods/packa...sh#L1791-L1798 If the Git push was not a tag, it'll default to alpha. If the Git push was a tag, it'll check if the version matches "1.2.3" or "v1.2.3" or has the word "release" in it, if not it'll be flagged as beta. So, without modifying the script, your normal pushes will always be alpha, and your "releases" will be beta. I'd recommend you fork the packager on GitHub, make the changes to match your versioning, then use that instead for the "after_script: ". An alternative would be to apply a patch to the script before running it. Something like this would do: Code:
file_type= ^r\d+(-(alpha|beta))?(-\d+)?$ |
Thanks for your reply. That is the exact same portion I was looking at earlier, and I don't really want to fork it unless I have to as that means I need to pull changes in to keep it updated... and I'm lazy :P
I have literally no clue how to use Travis or just bash scripts in it, and even after trying various things and googling a lot I can't seem to get it to accept the "patch" you posted as a valid parameter in my after_script block. This is the best that I've got, though no matter what, none of the block indicators I found seems to work: GitHub gist for the invalid .travis.yml file Right now the error message is Code:
syntax error: (<unknown>): could not find expected ':' while scanning a simple key at line 19 column 1 |
Some issues with your yml file:
- You're ignoring the whitespace requirements of YAML (not really your fault, YAML is anal) - You're running the "patch" before the release script is even downloaded - You're attempting to start curl with "/curl", this is not WoW :P - There's BBCode in the curl line (that's this forums fault for parsing links in code snippets) - Incorrect syntax for the branch expression I created a patch file: https://gist.github.com/p3lim/d77edf...-release-patch And fixed your yml file, using that patch file: https://gist.github.com/p3lim/d77edf...ile-travis-yml The major difference here (apart from the syntax errors here and there) is this: - It downloads the release script and saves it to disk, instead of piping it directly into bash (like in the guide) - It downloads and applies the patch (linked above) - Lastly, it runs the script Full changelog: https://gist.github.com/p3lim/d77edf...8a45/revisions |
Wow, thank you so much! I really have no clue what I'm doing. I just tried to somehow make it work with the info this guide gives and my very limited knowledge.
I forked your gist to have a backup of it in case you want to delete it, but otherwise I can just have Travis download yours if you don't mind? The build completed successfully now, but I don't think the release script is doing what it should... yet. All it did was create a GitHub release (for my alpha file, no less...), which isn't ideal. It also skipped the localization and there was no mention of uploading anything to WOWI at all. This is the build log: Travis-CI.org I'm sure I am still missing something, but from what I see the whole point of using it over the CurseForge + GitHub webhooks solution is to have WOWI included. So far my addons have only been on Curse, but I've updated a smaller addon yesterday to see if I could get it to work. CurseForge has not received any update (do I still need the old webhook?) and I'm not sure how the process works here. |
Quote:
Quote:
That's the only way (aside from arguments to the script directly, not very portable) the script will know which addon on their respective sites will be updated (aside from GitHub which already knows the repo). Also notice the last part in the 3rd post, it will automagically update the version field in your TOC file also. |
Everything seems to have worked now. Thank you! I should be able to use the same approach to upload my other addons here as well.
I am aware of the version substitution, but I had not added it to that specific addon yet. |
I found an issue in the release.sh script.
From the old times of svn, we could directly refer to a subdirectory inside an external library. This survived ad is managed byt the curse packager but not from release.sh. Here is the example Code:
externals: fatal: repository 'https://github.com/alarofrunetotem/LibInit.git/LibInit/' not found Actually, the right behavious would be: Code:
git clone https://github.com/alarofrunetotem/LibInit.git tempdir |
Quote:
|
Uploading to WowAce
Thank you for this detailled guide, I managed to set it up smoothly!
The packager script, however, does not upload to WowAce (and thus CurseForge). When looking at the script, it specifically checks whether the project_page is curseforge. In my case, however, it is a WowAce project page. Is it possible at all to upload to WowAce? |
Quote:
https://github.com/BigWigsMods/packager/pull/15 |
Quote:
|
Quote:
Quote:
|
Thanks!
Thank you p3lim for this guide. I have implemented this for my add-ons and (after a few trials and errors) it's working great.
Do you know if there is a way to provide CurseForge with the supported version? Right now, every build uploaded to CurseForge is flagged for 8.0 and I have to go and manually replace the flag for 7.3.5. It would be really great if there was a way to read the .toc files and use the interface version number to flag the build on CurseForge correctly. |
.toc is a little bit of a weird one, because 70300 could mean 7.3 like it could mean 7.3.2 or 7.3.5, so it's probably not as simple as just reading from .toc.
Unless they finally started adding minor revision number to interface version number, at least, but I imagine they have reasons for why they haven't done that. |
Quote:
Modify your ".travis.yaml", changing the line that says "script" into this: Code:
script: curl -sO https://raw.githubusercontent.com/BigWigsMods/packager/master/release.sh Quote:
https://api.wowinterface.com/addons/compatible.json |
Quote:
Thank you again ^^ |
Thank you for this guide!
I already had a .pkgmeta for the CurseForge packer so setting this up for my addon was quite easy and I got my first automated release to WoWI :) I am a bit confused about the release to GitHub. I used the "Draft a Release" feature on the side but that does not work with the packer since that already creates a release on the site? Code:
Uploading ChocolateBar-v3.1.2.zip (7.3.0) to https://www.wowinterface.com/downloads/info12326 Code:
git tag v3.1.3 && push --tags Two side notes: As you mentioned I had to adjust the regular expression in the .travis.yml to work with my version scheme. It has a leading "v". Since this version scheme is quite common you could include an info how to adjust regex for that scheme in the guide. I noticed that the CurseForge link to the keywords substitutions has changed. |
Quote:
|
Quote:
If that doesn't happen, report it on the packager repo. Quote:
Quote:
|
Quote:
Regarding the Curse version stuff, their new versions endpoint is lacking and they don't seem keen on improving it. The old platform included "in_development" and "internal_id" (toc) so it was pretty easy to pick the current version. Now the only context you get is the version name, so when the version isn't set manually all I can do is grab the latest one, which obviously doesn't work so well when there is a new version in testing. :mad: As a stopgap I committed using 7.3.5 as the default version for Curse uploads, but I really am hoping the endpoint gets better. The WoWI versions json, on the other hand, is much nicer and has a "default" flag :p (Although it would be nice if they added new patch versions) |
Quote:
|
Quote:
|
Thank you for the excellent guide! You have tremendously simplified my workflow and made it much easier to push out new releases!
My question is related to the pkgmeta file. I'm relatively new to the addon writing world, and I'm trying to understand the difference between externals, dependencies, and tools. Could you point me to a good guide on when to use each? The Curse documentation is sorely lacking beyond the bare how-to; it assumes you already know what the difference is. Besides, the automated method bypasses the Curse packager anyway. As an example, I've been using LibStub, CallbackHandler, and LibDataBroker in my addons, and until now, I've simply placed those files in my repository and included them in my .toc file. I tried to include them as externals, but I ended up with a massive amount of files I didn't need in my addon zip file, like test cases and documentation. I'm now moving towards the Ace3 framework, so I thought to include Ace3 and the other libraries I'm using in my externals list - but I got with something like three copies of libstub and callbackhandler, including in directories under the Ace3 hierarchy! I played around with it a bit, but eventually gave up and went back to just including the files I want in my repo. Any advice would be appreciated. |
Quote:
Optional-/required-dependencies is metadata Curse uses for their client (afaik). Tools-used I think is just something you'd put in so that tool would get some points for the rewards program (again, CF stuff). In your example with the three libraries: Code:
externals: Another field in .pkgmeta is the "ignore" list. Sadly, not enough libraries use this field, such as LibStub, so you'll end up with useless files like you mentioned. The packager will recursively check for the ignore list in the externals' .pkgmeta file, but it won't recursively get their externals (if any). You can however add externals' files you want to ignore for the packaging, as it's the last thing it does. As for Ace3, check out Phanx's addons (specifically Grid), she's using a bucketload of Ace3 modules in that addon, and uses this packager as well. While looking at it, notice how she's managed to get all of the libraries from externals alone, you only see them referenced in .pkgmeta and Grid.toc. |
Thanks again for the awesome advice, I'll check it out!
|
Quote:
Proof of concept: Create a new project with the following .pkgmeta. Package it using release.sh. You'll see the tests subdir under Libs/LibStub is packaged. Code:
ignore: |
I coded up the changes necessary to have the ignore directive apply to externals, and submitted it as a pull request to the main packager repository:
https://github.com/BigWigsMods/packager/pull/17 |
Code:
install: echo -e "[alias]\nclone = clone --insecure" > ~/.hgrc |
I'm a bit curious about this. I checked Travis-CI and it doesn't seem to have any native support for Lua. I'm assuming that without some additional scripts, it doesn't actually validate the code, but rather just packages it, yeah?
|
Quote:
|
Quote:
|
Quote:
Quote:
|
Quote:
Everything else is detected from the .travis.yml file. Edit: I've updated the guide to reflect the changes from travis-ci.org to travis-ci.com. (Although personally I've moved over to CircleCI instead, see packager#18 if you're interested) |
Quote:
https://github.com/Rainrider/oUF_Dis...er/.travis.yml (Sorry for the late response, I seem to have missed your reply.) |
Quote:
|
Quote:
I switched over because after TravisCI merged org to com my GitHub organization (where all my addons are hosted) got screwed up, and TravisCI support couldn't help me with it and told me to just wait for the merge to go through by itself (which could take months), so it was more of a necessity for me. We still use TravisCI for oUF, and there's no real need to change. |
Regex string
Hey, thanks for the great tutorial!
The only thing I would love to get some help with is the regex string, as I cant get it to work. x) The format I usually use for my versions is either a tag with 8.0.1.18 for a full release or 8.0.1.18-alpha/beta for beta/alpha releases. Any help with this would be wonderful! With regards, Dajn |
Quote:
Code:
/^\d+\.\d+\.\d+\.\d+(-\w+)?$/ |
Quote:
Been trying to get the hang of regex lately as I will start use it at work a lot, so this tutorial was a step in the right direction to start to learn it. :) With regards, Dajn |
Hey p3lim I'm having an issue where the packager isn't uploading properly to wowinterface.com
My tags are in the following format. v5.4, v.5.5, v5.6 etc.. so I changed the regex to the following Code:
/^v?\d+\.\d+(\.\d+)?(-\S*)?$/ So I then added a .pkgmeta file but left it empty. That didn't seem to work. So I'm thinking that something needs to go into this file. I don't need externals or anything. Just simply upload the addon as is to wowinterface. BTW: Yes I did make the modifications to the .toc file and added the addon IDs for both curse and wowinterface.com Code:
## X-Curse-Project-ID: 28603 |
Lol!!!!
Quote:
Code:
|
Quote:
Happy it all works for you :). |
Trying to get this setup myself and not having much luck with the regex even tho it should work :/
Currently they get tagged as vA.B.C(.D) so can be v8.0.0 or v8.0.0.1 Trying - ^v\d+.\d+.\d+(.\d+)?$ which works in any self-tests I do, but on Travis i'm getting 'Branch "v8.0.1.4" not included per configuration.' What have I done wrong? :) |
1 Attachment(s)
Quote:
Could you show me your .travis.yml file? |
Quote:
Code:
sudo: false Bah I think I see the problem already... forgot the /'s |
Quote:
I mentioned an alternative to the Travis method here, which eliminates the need to verify tag structure (it just assumes any tag is a release-ready version). (Plus, it's easier to set up and expand upon ;)) |
3 Attachment(s)
Thanks p3lim for providing this. I need some help.
I added the .travis.yml and the .pkgmeta to one of my addons in my github repo. Currently the .pkgmeta and the .travis.yml use CRLF as ending. Is that a problem? I told GIT bash for windows not to mess with line endings. https://github.com/zorker/rothui/tre...w8.0/rVignette I then used the git command you provided using git bash for windows in the git directory of rVignette. I'm not sure but I think my whole repo got that tag?! Is that correct? https://github.com/zorker/rothui/tree/v800.20181025 Once I started the git bash command I had to log into github and the tag completed. But nothing else seem to have happened? What am I missing? I had added the wowi token to the Travis page before. My travis page is all grey and says: There is no build on the default branch yet? Ok I checked the travis request page. I can see some error messages now. Travis does seem to try to generate a new build when I commit with Github desktop to master. (The first two requests) Why is that? *edit* Ohhh I see. It would run on any commit but when reading the config file would only react to branches that match the pattern. That being said. To correct the error from my understanding I have to put the .travis.yml in the repo root right? What does that mean for the packager? Will he parse all directories and upload all of them at once? If I only make a change to one of the addons all will be updated? How do I do this for specific directories? |
Quote:
E.g, if you tag the repo (and tags only work on repo-level, as with branches), every project you have in that repo (as you've set it up) will get the same tag. The packager and Travis expects Git to be used as it was intended; one repo per project, and each project has its own .travis.yml file at the root, and tagging the repo will trigger Travis/packager. |
It relates back to Google Code and SVN days. When Google Code closed there was an option to move all of it to Github which I did.
That is why there is one huge mono repo for all of it. Never saw a reason to change that. |
Quote:
If you ever want to manage dependencies, external tooling, collaboration, or versioning (just to name a few), monorepos is going to become a problem, fast. My suggestion to you is to spend some time splitting up your single repo into multiple, preferably one per addon, then you'll be able to fully utilize Git as it was intended, which includes being able to use the packager with TravisCI in an automated fashion. Example of splitting while preserving history: https://www.atlassian.com/blog/git/t...sitory-git-way |
Right, it would appear I'm doing something wrong with git, and I can't quite figure out what, so I'm turning here for help. Even tagging exactly in the manner suggested in the op, I keep tripping this:
Code:
if [ -z "$TRAVIS_TAG" ]; then I'm sure there's something obvious I'm missing, but I'm stumped, so any help would be appreciated. The repo in question is at https://github.com/Aiue/AQT, in case an extra set of eyes looking at stuff helps. |
Quote:
|
You can use Github Actions (just need to signup for it and afaik everyone asking gets immediate access to it) to run the packager with no other dependencies
here is an example: https://github.com/mooreatv/AuctionD...packaging.yaml |
All times are GMT -6. The time now is 08:34 AM. |
vBulletin © 2024, Jelsoft Enterprises Ltd
© 2004 - 2022 MMOUI