Gogs: a self-hosted Git Service written in Go
github.com
github.com
A single binary with zero dependancies is so awesome. With a ruby on rails app I need to worry about ruby version, ruby implementation, gem versions, compilation of C based gems, etc etc. With Go i simply copy up the binary and run it.
go get -u github.com/go/project
If you're writing native Go code, it doesn't matter if there's 0 or 1000+ dependencies, that one command will take care of everything. So there's no need to fear having extra dependencies, and you are welcome to reuse more code.Go takes the common parts of writing software and abstracts them away. Take any two distinct Go projects, and the only difference will be:
- Import Path
- Actual Code
Everything else works exactly the same no matter what project it is (assuming it follows idiomatic Go package conventions). Docs via godoc.org, standard testing, go vet, http://go-lint.appspot.com/, http://gocover.io/
No need to figure out how to install that particular project/library, how to get docs, how to run tests, etc.
Also their package managers have many issues you don't see with go (because go doesn't have a package manager, rather a source code dependency manager). For example python and ruby have many versions and not everything is available in all versions. What a user will do if he want to run a 2.7 and a 3.x python app? Sometimes they use the system compiler to produce binaries. I have seen it fail occasionally; for example charlock_holmes on a gentoo hardened system. Npm just floods your filesystem with npm_modules directories. I use a package manager so I won't have to install the same thing multiple times at multiple locations. Also it is very difficult to understand its directory structure. I searched the docs for hours in order to find where it stores the programs I install as a user (its path). Go is difficult to understand too in that aspect but it has all this info in one online document. You read it until you understand it.
Finally there are always the questions; should I use pip or easy_install? What does rvm, what gem and what bundle(r)? Why should users learn them? How may I update my current gems and remove old versions? Where is gruntjs and how do I run it?
Probably many more. If `go get` was good enough as you intended to say why do we have `godep, godeps, gom, gondler, goop, vendorize, party, gpm` and many more? Which one should I pick? It's better do GOPATH="_vendor:$GOPATH" go install or use one of them? Also, should I install go with apt/brew/pac or use gvm?
I like go, I use it for fun and work, but really, is getting annoying seeing all this `gophers` totally out of reality.
On the other hand, there isn't a way to not learn about gem, bundle, pip, easy_install, npm when you try to install apps written in their languages. Some times it is easy, as “gem install gollum” and some times it is difficult, as trying to install gitlab.
Haskell I really don't know because any haskell app I ever needed was in my distro's repositories. To be fair most Python packages are too.
Anyway, Go can't produce dynamically linked libraries yet even for Go applications. It really has no choice but to bundle them into one application.
For the later two can calling C functions is cheap. I would assume if you run Go with its default one thread option, it's cheap too. (Switching threads or even processes means context switching is what is usually expensive).
In order to provide efficient lightweight threads, Go allocates only a small amount of memory for each stack, growing it as function calls require it by appending another segment in a linked list. This makes thread creation very cheap.
The problem with segmented stacks is that they can cause "stack thrashing." Suppose a goroutine is right at the boundary between two stacks. It calls a function that exhausts the available segment, forcing the allocation of a new segment, which is then added to the linked list. The function runs, and then frees the segment upon return. If this boundary happens to fall within a tight loop, you'll see a severe drop in performance, to the point that it's completely unacceptable.
Recognizing this, Go relatively recently switched away from segmented stacks. It now uses a strategy called relocatable stacks, or contiguous stacks. See https://docs.google.com/document/d/1wAaf1rYoM4S4gtnPh0zOlGzW... for details. Similar concerns prompted Rust to move away from segmented stacks, but as relocatable stacks require a garbage collector that was not a viable way forward for Rust, so it just dropped the idea completely.
The problem with both approaches is that C has no knowledge or support of either segmented or relocatable stacks. This means that calling out to C in Go involves a completely different calling convention that involves switching to a larger stack, running there, and then switching back--which is very expensive, especially compared to languages like Lua where the C FFI is basically free. That's why Go reimplements glibc by performing its own system calls--to avoid the C FFI.
In conclusion, every language feature--no matter how enticing--has a cost.
The only package manager (pm) I like, is the pm of the distro I am using. If I am on Fedora, I like yum. When I am on Gentoo I like portage etc. The problem with most web apps is that they have dependencies that don't exist in your distro's pm. I'll take a static binary over a 3rd party pm any day. Let's not forget that one of the most important reasons for the existence of docker is to not have to set up an app in many different systems.
Ruby's Nokogiri for example is very very common and I've never found it simple to install.
Python has psycopg, numpy and a variety of others that are often very complex to install.
Node at least differentiates itself in that most of the database drivers have pure JS fallback implementations, so they'll work without the relevant libraries installed, just not as fast.
(test)> pip -q install pillow psycopg2 numpy
pip -q install pillow psycopg2 numpy 9.85s user 5.43s system 44% cpu 34.400 total
That was complex indeed.(it wasn't)
It's not going to get simpler than a single executable.
The second reason I switched was RAM consumption and here Go shines compared to Java, although I'll have to let Gogs run for a few days to see what happens.
I gave it a spin and it looks nice. I can see migrating from gitbucket to gogs, mainly for being able to run it on a small VPS. One thing that I didn't like was that the source version can only run from the source code directory. If I copy public and templates directories it should run from anywhere.
But you're right about static resources, they need to be in a directory structure. Fortunately, zip files make them easy to distribute.
What robovm can do is a great example of the joys of toolchains with a well-defined stable intermediate representation. (Or one of the joys, I should say -- the flowering of languages on top of the jvm is another.)
Go's first-class AST work is excellent stuff, but I'd love it even more if they fleshed out a well-defined, stable, portable intermediate format like LLVM's IR and java's bytecode. Making a release of software and knowing it can run on architectures you haven't even thought of yet is liberating. Sure, architectures don't come along "very often" (but they're starting to happen more often!), and sure, you can use a full vm at the bottom layer (but it's slow! It can't do a fraction of the optimizations possible with an IR/bytecode), and sure, you can just pretend the source is an IR (but if some library you use chooses a different build tool chain than you, you're going to have a bad time -- don't laugh, golang is too young to have bifurcated much yet, but give it time, and look at what happened around the go-get mess already; or, consider what happens when someone just adds more tooling like source generation, which has also already happened)... Taking the long view, I think an intermediate representation has proven incredibly useful for the jvm as a platform, and I hope golang also grows to offer such a route sometime in the future.
> sure, you can just pretend the source is an IR (but if some library you use chooses a different build tool chain than you, you're going to have a bad time
In the jvm world right now, for example, I won't touch maven with a ten foot poll. And yet I regularly use libraries produced by people who do. The portable, stable bytecode is a boundary between me and them where the buck stops. Anyone can use any build toolchain they like, and the interface for collaboration is well-defined.
Don't get me wrong, there are many things to love about golang, and there are many things to love about building from source. But I do think it's worth pausing to consider the flexibility that an intermediate representation can unlock.
But I'm inclined to agree that this is one area Go projects have a hard time with. The portability of the executable is great, but if you're doing anything that requires static assets, configuration, or data outside the context of the runtime, you can easily end up with a tough-to-manage mess of configuration.
What we've done for our internal Go projects is wrap them up with an .rpm installer that handles the creation of directories throughout the system, drops init scripts where they're appropriate, and sets up necessary cron jobs and logrotate rules. I don't think this is the best approach, but at the same time I'm not familiar with any good alternatives.
System configuration I think is a problem independent of the programming language and anything you try will feel as hack. As long as it works, it is ok. :)
This is mostly a sysadmin/devops issue, since all languages have the same issue.
I solve it through a CM tool (Ansible, in my case) that sets up my directories, rsyncs my templates and TOML config, and uploads my binary. Not having to worry the server running the same env as my dev environment removes a whole class of bugs/frustration.
You're kidding right? I thought that whole "devops" movement (call it what you like) was to get rid of the attitude of "other people's problem".
I live in environments that are (for the most part) regulated and demand by law that there is a strict separation between the people running and developing software, often open to interpretation is the 3rd role of people configuring the software.
The problem is that "I solve it..." just doesn't work. Either people solve it by working cooperatively together or it simply won't ever be deployed.
There's no such thing as a sysadmin problem, devops problem, developer problem. (No go downvote me for the tone of the next sentence) -- For me it's either get your ass moving, stand up, walk over to people and talk to them or get lost!
That's why frameworks exist, or packages like go-bindata or rakyll/statik (https://github.com/rakyll/statik), or CM tools that can wrap it all together.
Is there anything stopping one from appending a zip archive to the go binary, and having the binary open the executable as a zip file to get at the static assets ?
https://github.com/GeertJohan/go.rice
https://github.com/jteeuwen/go-bindata
EDIT: to add, the Go team is looking to add a generate command in go1.4 to help with this. See: https://groups.google.com/forum/m/#!topic/golang-dev/ZTD1qtp...
You mean, like every single language out there with native code compilers?
A big generation gap must have happened, for static compilation to be touted as awesome feature.
Two decades ago it was the only option in most operating systems.
Not an excuse for the lack of understanding, that static compilation is a standard feature that any language compiler to native code usually provides.
You can build your binary with the netgo build tag, but you must take into consideration that your binary might not behave correctly when running on systems with customised name resolution (NSS) settings, such as nss-ldap etc.
Go developers only distribute their open source software in a way that you only have to take the source, compile it, and run it, without having to worry about dependencies.
I see it all the time in the last 30 years of my career.
Maybe GNU/Linux kids nowadays don't.
Besides C is not the only language with native compiler.
Same goes for the use of "read-only" mounts and "RAM disks" as opposed to dependence on other, less reliable media.
I hope your comment continues to be upvoted; usually I see downvotes at any mention of static linking. Why, I can never be sure. If static binaries make some power user's life easier why should anyone else care? With reasonably-sized, well-written programs (or the use of a system like Go's), compilation can be quite fast. And easy enough for anyone to do if and when libraries change.
- https://github.com/geerlingguy/ansible-vagrant-examples/tree/master/gitlab
- https://github.com/geerlingguy/ansible-vagrant-examples/tree/master/gogs
Right now I still have a very basic git server for personal use with a bunch of bare repos and no UI, but I'm sorely tempted to start using Gogs or GitLab. GitLab wins for polish so far, but Gogs has caught up very quickly, and feels slightly faster.That's where I find GitLab super useful. My use-case however is just me, a single user, on a tiny VPS so GitLab is overkill. Awesome software though, and I'm a massive fan
Installing Gitlab was definitely one of the painpoints, having an executable that just works is amazing
What are people's thoughts on open software projects like this eating into github licensing money? I feel guilty sometimes pushing gitlab since I really like github as a company (and want them to thrive)
I switched to Fossil because of this monoculture. I am sure Github don't mind one less freeloader.
In terms of private repository hosting, I feel that some companies simply prefer self-hosted solutions no matter how good Github is.
Not only prefer but sometimes its required based on compliance and regulations and such.
There were already other options that were very simple to install and upgrade, such as Gitblit and Gitbucket. At work we are using Gitblit. It provides all the functionality you'd expect, and one of the nice advantages is that it can store tickets in an orphan branch, so that you have these in git too.
I've actually rolled up my sleeves and written some login adapters (for internal use) in gitlab, and I'm much more comfortable writing ruby in rails than I would ever be writing Java. Again, this is probably a stupid opinion, but until I see the Java light, I don't think I'll be back to it.
Also, gitblit looks nowhere as good as gitlab (or even gitorious) does. Neither does gitbucket -- they don't have the polish that I see on other solutions... Yeah it's a really fickle point, but I want to reward groups that also prioritize design/visuals in their projects.
I absolutely love the product. The install guide is fantastic, I don't know if that can be any better than it already is. The thing is, I'm a little paranoid about downloading & installing random binaries on our computers at work (I work in a very IP-sensitive company), so I generally go for source-builds.
I've actually been writing a fabric script to automate the entire install, believe it or not (the whole thing might be an exercise in futility, since people could just download the package), and I've installed gitlab enough times that I'm not really worried about it -- so at this point it's not a huge problem.
I favoured gogs because of the ease of deployment. What killed it was the fact that forking public repositories and creating pull requests is not implemented yet.
Since the ease of deployment for gitlab was drastically reduced lately, we settled for gitlab.
So many things you could build with a git-like data store...
Another project I'm aware of that aims to re-implement git in go is https://github.com/kourge/ggit, which looks promising but has been slowing down, activity-wise.
A lot of people mentioned that Gitlab installation is painful, but for me it was rather simple albeit a bit long. Probably the "IKEA effect" makes me love this awesome project even more.
How does this compare feature-wise to GitLab? How does this compare to GitLab regarding updates, i.e. how easy and seamless will update be and how often are they available?
Would be nice if someone could post some first-hand experience :)
1. The blue-on-red contrast is a bit hard on the eyes. Try a softer color palette?
2. Repository languages doesn't include Javascript?
3. Issue sorting and filtering might be important
Once again, kudos on a job well done!
If this can run ok on a modest VM then I think we got a winner!
"System Requirements A cheap Raspberry Pi is powerful enough to match the minimal requirement. 4 CPU Cores and 1GB RAM would be the baseline for teamwork."
It's actually pretty darn great.
Looks great! Good job!