├── .base_platform ├── .github └── workflows │ └── ci.yaml ├── AUTHORS ├── CONTRIBUTORS ├── LICENSE ├── Makefile ├── README.md ├── ballerina ├── Dockerfile ├── README.md ├── deploy └── install ├── buildpack ├── Dockerfile ├── build ├── deploy └── install ├── examples ├── ballerina │ ├── Procfile │ ├── hello_service.bal │ └── tsuru.yml ├── buildpack ├── cordova │ ├── tsuru.yml │ └── www │ │ └── index.html ├── go │ ├── go.mod │ ├── tsuru.yml │ └── web.go ├── java │ ├── pom.xml │ ├── src │ │ └── main │ │ │ └── webapp │ │ │ ├── WEB-INF │ │ │ └── web.xml │ │ │ └── index.jsp │ └── tsuru.yml ├── nodejs │ ├── Procfile │ ├── app.js │ ├── hook.js │ ├── package.json │ └── tsuru.yml ├── perl │ ├── Procfile │ ├── app.pl │ ├── cpanfile │ ├── cpanfile.snapshot │ ├── tsuru.yml │ └── vendor │ │ └── cache │ │ └── authors │ │ └── id │ │ ├── P │ │ └── PE │ │ │ └── PEVANS │ │ │ └── IO-Socket-IP-0.39.tar.gz │ │ └── S │ │ └── SR │ │ └── SRI │ │ └── Mojolicious-7.33.tar.gz ├── php │ ├── index.php │ └── tsuru.yml ├── play │ ├── Procfile │ ├── activator │ ├── activator-launch-1.2.12.jar │ ├── app │ │ └── controllers │ │ │ └── Application.scala │ ├── build.sbt │ ├── conf │ │ ├── application.conf │ │ └── routes │ ├── project │ │ ├── build.properties │ │ └── plugins.sbt │ └── tsuru.yml ├── pypy │ ├── Procfile │ ├── app.py │ ├── hook.py │ ├── requirements.txt │ └── tsuru.yml ├── python │ ├── Procfile │ ├── app.py │ ├── hook.py │ ├── requirements.txt │ └── tsuru.yml ├── python3 │ ├── Procfile │ ├── app.py │ ├── hook.py │ ├── requirements.txt │ └── tsuru.yml ├── resolver │ ├── index.html │ └── tsuru.yml ├── ruby │ ├── Gemfile │ ├── Gemfile.lock │ ├── Procfile │ ├── app.rb │ ├── hook.rb │ └── tsuru.yml ├── static-reactjs │ ├── nginx.conf │ └── tsuru.yml └── static │ ├── index.html │ └── tsuru.yml ├── go ├── Dockerfile ├── Procfile ├── README.md ├── deploy └── install ├── java ├── Dockerfile ├── Procfile ├── README.md ├── install └── start-tomcat ├── lua ├── Dockerfile ├── README.md ├── deploy └── install ├── nodejs ├── Dockerfile ├── README.md ├── deploy └── install ├── perl ├── Dockerfile ├── README.md ├── deploy └── install ├── php ├── Dockerfile ├── README.md ├── __init__.py ├── deploy ├── deploy.py ├── frontend.py ├── frontend │ ├── apache-mod-php │ │ └── vhost.conf │ ├── apache │ │ ├── security.conf │ │ └── vhost.conf │ └── nginx │ │ ├── nginx.conf │ │ └── vhost.conf ├── install ├── interpretor.py ├── interpretor │ └── fpm │ │ ├── php-fpm.conf │ │ └── pool.conf ├── utils.py └── vars.py ├── python ├── Dockerfile ├── README.md ├── deploy └── install ├── ruby ├── Dockerfile ├── README.md ├── deploy └── install ├── scratch ├── Dockerfile ├── README.md └── deploy ├── static ├── Dockerfile ├── Procfile ├── README.md ├── deploy ├── etc │ └── nginx.conf ├── install └── validate-nginx-conf └── tests ├── Dockerfile.template ├── common └── tests.bats ├── go ├── fixtures │ ├── multipleprocesses │ │ ├── Procfile │ │ ├── cmd │ │ │ ├── api │ │ │ │ └── main.go │ │ │ └── worker │ │ │ │ └── main.go │ │ └── go.mod │ ├── nonrootmain │ │ ├── cmd │ │ │ └── main.go │ │ └── go.mod │ ├── rootmain │ │ ├── go.mod │ │ └── main.go │ ├── selfreferencing │ │ ├── api │ │ │ └── api.go │ │ ├── go.mod │ │ └── main.go │ ├── selfreferencingnonroot │ │ ├── api │ │ │ └── api.go │ │ ├── cmd │ │ │ └── main.go │ │ └── go.mod │ └── vendored │ │ ├── go.mod │ │ ├── go.sum │ │ ├── main.go │ │ └── vendor │ │ ├── golang.org │ │ └── x │ │ │ └── net │ │ │ ├── AUTHORS │ │ │ ├── CONTRIBUTORS │ │ │ ├── LICENSE │ │ │ ├── PATENTS │ │ │ └── netutil │ │ │ └── listen.go │ │ └── modules.txt └── tests.bats ├── java └── tests.bats ├── lua └── tests.bats ├── nodejs ├── fixtures │ ├── package-lock.json │ ├── package.json │ └── yarn.lock └── tests.bats ├── perl └── tests.bats ├── php └── tests.bats ├── platforms.sh ├── python ├── Pipfile ├── Pipfile.lock └── tests.bats ├── ruby └── tests.bats ├── run.sh └── static └── tests.bats /.base_platform: -------------------------------------------------------------------------------- 1 | 1539609841 2 | -------------------------------------------------------------------------------- /.github/workflows/ci.yaml: -------------------------------------------------------------------------------- 1 | name: CI 2 | on: [push, pull_request] 3 | jobs: 4 | test: 5 | strategy: 6 | fail-fast: false 7 | matrix: 8 | platform: 9 | - ballerina 10 | - buildpack 11 | - go 12 | - java 13 | - lua 14 | - nodejs 15 | - perl 16 | - php 17 | - python 18 | - ruby 19 | - scratch 20 | - static 21 | runs-on: ubuntu-latest 22 | steps: 23 | - uses: actions/checkout@v4 24 | - name: run tests 25 | run: make test platform=${{ matrix.platform }} 26 | shell: bash 27 | publish: 28 | if: github.repository == 'tsuru/platforms' && github.event_name != 'pull_request' 29 | needs: test 30 | runs-on: ubuntu-latest 31 | strategy: 32 | fail-fast: false 33 | matrix: 34 | platform: 35 | - ballerina 36 | - buildpack 37 | - go 38 | - java 39 | - lua 40 | - nodejs 41 | - perl 42 | - php 43 | - python 44 | - ruby 45 | - scratch 46 | - static 47 | steps: 48 | - uses: actions/checkout@v4 49 | - uses: docker/login-action@v3 50 | if: github.event_name != 'pull_request' 51 | with: 52 | username: ${{ secrets.DOCKERHUB_USERNAME }} 53 | password: ${{ secrets.DOCKERHUB_PASSWORD }} 54 | - run: | 55 | ref="${GITHUB_REF##*/}" 56 | img="tsuru/${{ matrix.platform }}" 57 | tags="${img}:${ref}" 58 | if [[ ${ref} == "master" ]] || [[ ${ref} == "main" ]]; then 59 | tags="${img}:latest" 60 | elif [[ ${ref} =~ ${{ matrix.platform }}-([0-9.]+) ]]; then 61 | tags=${img}:${BASH_REMATCH[1]},${img}:latest 62 | fi 63 | echo "::set-output name=tag::${tags}" 64 | if: github.event_name != 'pull_request' 65 | id: tags 66 | shell: bash 67 | - name: Set up QEMU 68 | uses: docker/setup-qemu-action@v3 69 | - name: Set up Docker Buildx 70 | uses: docker/setup-buildx-action@v3 71 | - uses: docker/build-push-action@v5 72 | if: github.event_name != 'pull_request' && steps.tags.outputs.tag != '' 73 | with: 74 | context: ./${{ matrix.platform }} 75 | push: true 76 | tags: ${{ steps.tags.outputs.tag }} 77 | platforms: linux/amd64 78 | -------------------------------------------------------------------------------- /AUTHORS: -------------------------------------------------------------------------------- 1 | # This source code refers to tsuru authors for copyright purposes. 2 | # The master list of authors is in the main tsuru distribution, 3 | # visible at https://github.com/tsuru/tsuru/blob/master/AUTHORS. 4 | -------------------------------------------------------------------------------- /CONTRIBUTORS: -------------------------------------------------------------------------------- 1 | # This source code was written by the tsuru contributors. 2 | # The master list of contributors is in the main tsuru distribution, 3 | # visible at https://github.com/tsuru/tsuru/blob/master/CONTRIBUTORS. 4 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2016, tsuru authors. All rights reserved. 2 | 3 | Redistribution and use in source and binary forms, with or without 4 | modification, are permitted provided that the following conditions are met: 5 | 6 | * Redistributions of source code must retain the above copyright 7 | notice, this list of conditions and the following disclaimer. 8 | * Redistributions in binary form must reproduce the above copyright 9 | notice, this list of conditions and the following disclaimer in the 10 | documentation and/or other materials provided with the distribution. 11 | * Neither the name of the Globo.com nor the names of its contributors 12 | may be used to endorse or promote products derived from this software without 13 | specific prior written permission. 14 | 15 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 16 | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 17 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 18 | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 19 | OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 20 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 21 | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 22 | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 23 | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 25 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | # Copyright 2016 tsuru authors. All rights reserved. 2 | # Use of this source code is governed by a BSD-style 3 | # license that can be found in the LICENSE file. 4 | 5 | test: 6 | ./tests/run.sh $(platform) $(no_rebuild) 7 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | platforms 2 | ========= 3 | 4 | [![Actions Status](https://github.com/tsuru/platforms/workflows/CI/badge.svg)](https://github.com/tsuru/platforms/actions) 5 | 6 | Source for official Docker images of tsuru platforms. 7 | 8 | All platforms are available in Docker Hub: 9 | 10 | * tsuru/ballerina: https://hub.docker.com/r/tsuru/ballerina/ 11 | * tsuru/buildpack: https://hub.docker.com/r/tsuru/buildpack/ 12 | * tsuru/cordova: https://hub.docker.com/r/tsuru/cordova/ 13 | * tsuru/go: https://hub.docker.com/r/tsuru/go/ 14 | * tsuru/java: https://hub.docker.com/r/tsuru/java/ 15 | * tsuru/lua: https://hub.docker.com/r/tsuru/lua/ 16 | * tsuru/nodejs: https://hub.docker.com/r/tsuru/nodejs/ 17 | * tsuru/php: https://hub.docker.com/r/tsuru/php/ 18 | * tsuru/play: https://hub.docker.com/r/tsuru/play/ 19 | * tsuru/python: https://hub.docker.com/r/tsuru/python/ 20 | * tsuru/pypy: https://hub.docker.com/r/tsuru/pypy/ 21 | * tsuru/ruby: https://hub.docker.com/r/tsuru/ruby/ 22 | * tsuru/static: https://hub.docker.com/r/tsuru/static/ 23 | 24 | Installing platforms 25 | -------------------- 26 | 27 | In order to use one of the platforms provided here, you need to have 28 | tsuru-admin installed and run ``tsuru-admin platform-add``: 29 | 30 | ```bash 31 | % tsuru-admin platform-add 32 | ``` 33 | 34 | Prior to version 0.13.0, tsurud didn't accept prebuilt images in 35 | platform-add/platform-update, so in order to add a platform from this 36 | repository, you need to create a Dockerfile with a single line (``FROM 37 | ``). 38 | 39 | Dockerfiles are provided in the basebuilder repository, so in order to add a 40 | platform, it's as simple as running ``tsuru-admin platform-add``. For example, 41 | for the Java platform: 42 | 43 | ```bash 44 | % tsuru-admin platform-add java -d https://raw.github.com/tsuru/basebuilder/master/java/Dockerfile 45 | ``` 46 | 47 | Replace "java" with any other platform and you're good to go! 48 | 49 | Creating new platforms 50 | ---------------------- 51 | 52 | tsuru requires only a single executable for platforms: 53 | ``/var/lib/tsuru/deploy``. It also expects the 54 | [deploy-agent](http://github.com/tsuru/deploy-agent) to be installed. This 55 | script will receive two parameters: the deployment type (which is always 56 | "archive" in latest release) and the URL for the archive. 57 | 58 | We provide a base image which platform developers can use to build upon: 59 | [base-platform](https://github.com/tsuru/base-platform). This platform provides 60 | a base deployment script, which handles package downloading and extraction in 61 | proper path, along with operating system package management. For more details, 62 | check the README of base-platform. 63 | -------------------------------------------------------------------------------- /ballerina/Dockerfile: -------------------------------------------------------------------------------- 1 | # Copyright 2019 tsuru authors. All rights reserved. 2 | # Use of this source code is governed by a BSD-style 3 | # license that can be found in the LICENSE file. 4 | 5 | FROM tsuru/base-platform:22.04 6 | COPY . /var/lib/tsuru/ballerina 7 | RUN set -ex \ 8 | && sudo cp /var/lib/tsuru/ballerina/deploy /var/lib/tsuru \ 9 | && sudo /var/lib/tsuru/ballerina/install \ 10 | && sudo rm -rf /var/lib/apt/lists/* 11 | -------------------------------------------------------------------------------- /ballerina/README.md: -------------------------------------------------------------------------------- 1 | # Ballerina Platform 2 | 3 | The Ballerian platform uses Ballerian 0.991.0 and latest available. 4 | 5 | https://ballerina.io/ 6 | -------------------------------------------------------------------------------- /ballerina/deploy: -------------------------------------------------------------------------------- 1 | #!/bin/bash -le 2 | 3 | # Copyright 2019 tsuru authors. All rights reserved. 4 | # Use of this source code is governed by a BSD-style 5 | # license that can be found in the LICENSE file. 6 | 7 | SOURCE_DIR=/var/lib/tsuru 8 | source ${SOURCE_DIR}/base/deploy 9 | source ${SOURCE_DIR}/base/rc/config 10 | -------------------------------------------------------------------------------- /ballerina/install: -------------------------------------------------------------------------------- 1 | #!/bin/bash -el 2 | 3 | # Copyright 2019 tsuru authors. All rights reserved. 4 | # Use of this source code is governed by a BSD-style 5 | # license that can be found in the LICENSE file. 6 | set -eu -o pipefail 7 | 8 | curl -fsSL -o /tmp/ballerina.deb https://dist.ballerina.io/downloads/2201.0.3/ballerina-2201.0.3-swan-lake-linux-x64.deb 9 | dpkg -i /tmp/ballerina.deb 10 | rm -f /tmp/ballerina.deb 11 | -------------------------------------------------------------------------------- /buildpack/Dockerfile: -------------------------------------------------------------------------------- 1 | # Copyright 2015 tsuru authors. All rights reserved. 2 | # Use of this source code is governed by a BSD-style 3 | # license that can be found in the LICENSE file. 4 | 5 | FROM progrium/buildstep 6 | RUN locale-gen en_US.UTF-8 7 | ENV LANG=en_US.UTF-8 LANGUAGE=en_US:en LC_ALL=en_US.UTF-8 DEBIAN_FRONTEND=noninteractive 8 | RUN mkdir -p /var/lib/tsuru/base 9 | ADD . /var/lib/tsuru/buildpack 10 | RUN cp /var/lib/tsuru/buildpack/deploy /var/lib/tsuru 11 | RUN apt-get update && apt-get install -y --no-install-recommends \ 12 | curl \ 13 | sudo \ 14 | && rm -rf /var/lib/apt/lists/* 15 | RUN curl -sLo base-platform.tar.gz https://github.com/tsuru/base-platform/tarball/master; \ 16 | tar -xvf base-platform.tar.gz -C /var/lib/tsuru/base --strip 1; \ 17 | rm -rf base-platform.tar.gz 18 | RUN set -ex; \ 19 | sudo /var/lib/tsuru/buildpack/install; \ 20 | sudo rm -rf /var/lib/apt/lists/* 21 | USER ubuntu 22 | -------------------------------------------------------------------------------- /buildpack/build: -------------------------------------------------------------------------------- 1 | #!/bin/bash -el 2 | 3 | # Copyright 2015 tsuru authors. All rights reserved. 4 | # Use of this source code is governed by a BSD-style 5 | # license that can be found in the LICENSE file. 6 | 7 | SOURCE_DIR=/var/lib/tsuru 8 | 9 | source ${SOURCE_DIR}/base/rc/config 10 | export USER 11 | herokuish buildpack build 12 | -------------------------------------------------------------------------------- /buildpack/deploy: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Copyright 2015 tsuru authors. All rights reserved. 4 | # Use of this source code is governed by a BSD-style 5 | # license that can be found in the LICENSE file. 6 | 7 | SOURCE_DIR=/var/lib/tsuru 8 | 9 | if [[ -f ${SOURCE_DIR}/base/deploy ]]; then 10 | source ${SOURCE_DIR}/base/deploy 11 | fi 12 | 13 | if [[ -f ${SOURCE_DIR}/base/rc/config ]]; then 14 | source ${SOURCE_DIR}/base/rc/config 15 | fi 16 | 17 | echo "BUILDPACK: $BUILDPACK_URL" 18 | 19 | cd $CURRENT_DIR 20 | sudo /bin/sh -c "rm -rf /app && mkdir /app && cp -a . /app" 21 | sudo -E ${SOURCE_DIR}/buildpack/build 22 | sudo chown -R ${USER}:${USER} /app 23 | echo "export PORT=8888" | tee /app/.profile.d/tsuru.sh >/dev/null 24 | echo 'export PYTHONPATH=${PYTHONPATH}:/usr/lib/python2.7/dist-packages:/usr/local/lib/python2.7/dist-packages' | tee -a /app/.profile.d/tsuru.sh >/dev/null 25 | 26 | LC_ALL=C perl -lne '/^(.*?):/ && print "$1: /start $1"' /app/Procfile | sudo tee /Procfile >/dev/null 27 | -------------------------------------------------------------------------------- /buildpack/install: -------------------------------------------------------------------------------- 1 | #!/bin/bash -e 2 | 3 | # Copyright 2015 tsuru authors. All rights reserved. 4 | # Use of this source code is governed by a BSD-style 5 | # license that can be found in the LICENSE file. 6 | 7 | SOURCE_DIR=/var/lib/tsuru 8 | 9 | cat >> /etc/profile <respond(response); 19 | 20 | } 21 | 22 | } 23 | -------------------------------------------------------------------------------- /examples/ballerina/tsuru.yml: -------------------------------------------------------------------------------- 1 | healthcheck: 2 | path: /hello/sayHello 3 | -------------------------------------------------------------------------------- /examples/buildpack: -------------------------------------------------------------------------------- 1 | python -------------------------------------------------------------------------------- /examples/cordova/tsuru.yml: -------------------------------------------------------------------------------- 1 | healthcheck: 2 | path: / 3 | -------------------------------------------------------------------------------- /examples/cordova/www/index.html: -------------------------------------------------------------------------------- 1 | Hello world from tsuru 2 | -------------------------------------------------------------------------------- /examples/go/go.mod: -------------------------------------------------------------------------------- 1 | module go-example 2 | 3 | go 1.16 4 | -------------------------------------------------------------------------------- /examples/go/tsuru.yml: -------------------------------------------------------------------------------- 1 | healthcheck: 2 | path: / 3 | -------------------------------------------------------------------------------- /examples/go/web.go: -------------------------------------------------------------------------------- 1 | // Copyright 2016 tsuru authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package main 6 | 7 | import ( 8 | "flag" 9 | "net/http" 10 | "os" 11 | ) 12 | 13 | var hook bool 14 | 15 | func init() { 16 | flag.BoolVar(&hook, "h", false, "run hook") 17 | } 18 | 19 | func main() { 20 | flag.Parse() 21 | if hook { 22 | println("hello") 23 | return 24 | } 25 | http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { 26 | w.Write([]byte("Hello world from tsuru")) 27 | }) 28 | port := os.Getenv("PORT") 29 | if port == "" { 30 | port = "5000" 31 | } 32 | http.ListenAndServe(":"+port, nil) 33 | } 34 | -------------------------------------------------------------------------------- /examples/java/pom.xml: -------------------------------------------------------------------------------- 1 | 3 | 4.0.0 4 | io.tsuru.sample 5 | helloweb 6 | war 7 | 1.0-SNAPSHOT 8 | helloweb Maven Webapp 9 | http://maven.apache.org 10 | 11 | 12 | junit 13 | junit 14 | 4.13.1 15 | test 16 | 17 | 18 | 19 | ROOT 20 | 21 | 22 | -------------------------------------------------------------------------------- /examples/java/src/main/webapp/WEB-INF/web.xml: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | Archetype Created Web Application 7 | 8 | -------------------------------------------------------------------------------- /examples/java/src/main/webapp/index.jsp: -------------------------------------------------------------------------------- 1 | Hello world from tsuru 2 | -------------------------------------------------------------------------------- /examples/java/tsuru.yml: -------------------------------------------------------------------------------- 1 | hooks: 2 | build: 3 | - mvn package 4 | - mv target/ROOT.war . 5 | healthcheck: 6 | path: / 7 | -------------------------------------------------------------------------------- /examples/nodejs/Procfile: -------------------------------------------------------------------------------- 1 | web: node app.js 2 | -------------------------------------------------------------------------------- /examples/nodejs/app.js: -------------------------------------------------------------------------------- 1 | // Copyright 2016 tsuru authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | var express = require('express'); 6 | var app = express(); 7 | 8 | app.get('/', function(req, res){ 9 | res.send('Hello world from tsuru'); 10 | }); 11 | 12 | var server = app.listen(process.env.PORT || 5000); 13 | -------------------------------------------------------------------------------- /examples/nodejs/hook.js: -------------------------------------------------------------------------------- 1 | console.log("Hello"); 2 | -------------------------------------------------------------------------------- /examples/nodejs/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "hello-world", 3 | "description": "hello world test on tsuru", 4 | "version": "0.0.1", 5 | "private": true, 6 | "dependencies": { 7 | "express": "3.x" 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /examples/nodejs/tsuru.yml: -------------------------------------------------------------------------------- 1 | hooks: 2 | build: 3 | - node hook.js 4 | healthcheck: 5 | path: / 6 | -------------------------------------------------------------------------------- /examples/perl/Procfile: -------------------------------------------------------------------------------- 1 | web: carton exec hypnotoad app.pl -f 2 | -------------------------------------------------------------------------------- /examples/perl/app.pl: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env perl 2 | ############################################################################### 3 | # 4 | # Simple API for testing support for perl using carton 5 | # 6 | ############################################################################### 7 | use strict; 8 | use warnings; 9 | use Mojolicious::Lite; 10 | 11 | get '/' => { text => 'Hello world from tsuru' }; 12 | 13 | app->config(hypnotoad => { 14 | listen => [ 15 | "http://*:$ENV{PORT}", 16 | ], 17 | }); 18 | app->start; 19 | -------------------------------------------------------------------------------- /examples/perl/cpanfile: -------------------------------------------------------------------------------- 1 | requires 'Mojolicious'; 2 | -------------------------------------------------------------------------------- /examples/perl/cpanfile.snapshot: -------------------------------------------------------------------------------- 1 | # carton snapshot format: version 1.0 2 | DISTRIBUTIONS 3 | IO-Socket-IP-0.39 4 | pathname: P/PE/PEVANS/IO-Socket-IP-0.39.tar.gz 5 | provides: 6 | IO::Socket::IP 0.39 7 | requirements: 8 | IO::Socket 0 9 | Socket 1.97 10 | Test::More 0.88 11 | Mojolicious-7.33 12 | pathname: S/SR/SRI/Mojolicious-7.33.tar.gz 13 | provides: 14 | Mojo undef 15 | Mojo::Asset undef 16 | Mojo::Asset::File undef 17 | Mojo::Asset::Memory undef 18 | Mojo::Base undef 19 | Mojo::ByteStream undef 20 | Mojo::Cache undef 21 | Mojo::Collection undef 22 | Mojo::Content undef 23 | Mojo::Content::MultiPart undef 24 | Mojo::Content::Single undef 25 | Mojo::Cookie undef 26 | Mojo::Cookie::Request undef 27 | Mojo::Cookie::Response undef 28 | Mojo::DOM undef 29 | Mojo::DOM::CSS undef 30 | Mojo::DOM::HTML undef 31 | Mojo::Date undef 32 | Mojo::EventEmitter undef 33 | Mojo::Exception undef 34 | Mojo::File undef 35 | Mojo::Headers undef 36 | Mojo::HelloWorld undef 37 | Mojo::Home undef 38 | Mojo::IOLoop undef 39 | Mojo::IOLoop::Client undef 40 | Mojo::IOLoop::Delay undef 41 | Mojo::IOLoop::Server undef 42 | Mojo::IOLoop::Stream undef 43 | Mojo::IOLoop::Subprocess undef 44 | Mojo::IOLoop::TLS undef 45 | Mojo::JSON undef 46 | Mojo::JSON::Pointer undef 47 | Mojo::Loader undef 48 | Mojo::Log undef 49 | Mojo::Message undef 50 | Mojo::Message::Request undef 51 | Mojo::Message::Response undef 52 | Mojo::Parameters undef 53 | Mojo::Path undef 54 | Mojo::Reactor undef 55 | Mojo::Reactor::EV undef 56 | Mojo::Reactor::Poll undef 57 | Mojo::Server undef 58 | Mojo::Server::CGI undef 59 | Mojo::Server::Daemon undef 60 | Mojo::Server::Hypnotoad undef 61 | Mojo::Server::Morbo undef 62 | Mojo::Server::Morbo::Backend undef 63 | Mojo::Server::Morbo::Backend::Poll undef 64 | Mojo::Server::PSGI undef 65 | Mojo::Server::PSGI::_IO undef 66 | Mojo::Server::Prefork undef 67 | Mojo::Template undef 68 | Mojo::Transaction undef 69 | Mojo::Transaction::HTTP undef 70 | Mojo::Transaction::WebSocket undef 71 | Mojo::URL undef 72 | Mojo::Upload undef 73 | Mojo::UserAgent undef 74 | Mojo::UserAgent::CookieJar undef 75 | Mojo::UserAgent::Proxy undef 76 | Mojo::UserAgent::Server undef 77 | Mojo::UserAgent::Transactor undef 78 | Mojo::Util undef 79 | Mojo::WebSocket undef 80 | Mojolicious 7.33 81 | Mojolicious::Command undef 82 | Mojolicious::Command::cgi undef 83 | Mojolicious::Command::cpanify undef 84 | Mojolicious::Command::daemon undef 85 | Mojolicious::Command::eval undef 86 | Mojolicious::Command::generate undef 87 | Mojolicious::Command::generate::app undef 88 | Mojolicious::Command::generate::lite_app undef 89 | Mojolicious::Command::generate::makefile undef 90 | Mojolicious::Command::generate::plugin undef 91 | Mojolicious::Command::get undef 92 | Mojolicious::Command::inflate undef 93 | Mojolicious::Command::prefork undef 94 | Mojolicious::Command::psgi undef 95 | Mojolicious::Command::routes undef 96 | Mojolicious::Command::test undef 97 | Mojolicious::Command::version undef 98 | Mojolicious::Commands undef 99 | Mojolicious::Controller undef 100 | Mojolicious::Lite undef 101 | Mojolicious::Plugin undef 102 | Mojolicious::Plugin::Config undef 103 | Mojolicious::Plugin::Config::Sandbox undef 104 | Mojolicious::Plugin::DefaultHelpers undef 105 | Mojolicious::Plugin::EPLRenderer undef 106 | Mojolicious::Plugin::EPRenderer undef 107 | Mojolicious::Plugin::HeaderCondition undef 108 | Mojolicious::Plugin::JSONConfig undef 109 | Mojolicious::Plugin::Mount undef 110 | Mojolicious::Plugin::PODRenderer undef 111 | Mojolicious::Plugin::TagHelpers undef 112 | Mojolicious::Plugins undef 113 | Mojolicious::Renderer undef 114 | Mojolicious::Routes undef 115 | Mojolicious::Routes::Match undef 116 | Mojolicious::Routes::Pattern undef 117 | Mojolicious::Routes::Route undef 118 | Mojolicious::Sessions undef 119 | Mojolicious::Static undef 120 | Mojolicious::Types undef 121 | Mojolicious::Validator undef 122 | Mojolicious::Validator::Validation undef 123 | Test::Mojo undef 124 | ojo undef 125 | requirements: 126 | ExtUtils::MakeMaker 0 127 | IO::Socket::IP 0.37 128 | JSON::PP 2.27103 129 | Pod::Simple 3.09 130 | Time::Local 1.2 131 | -------------------------------------------------------------------------------- /examples/perl/tsuru.yml: -------------------------------------------------------------------------------- 1 | healthcheck: 2 | path: / 3 | -------------------------------------------------------------------------------- /examples/perl/vendor/cache/authors/id/P/PE/PEVANS/IO-Socket-IP-0.39.tar.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tsuru/platforms/8552eab6474b194c571fc82a29e00d94cded5337/examples/perl/vendor/cache/authors/id/P/PE/PEVANS/IO-Socket-IP-0.39.tar.gz -------------------------------------------------------------------------------- /examples/perl/vendor/cache/authors/id/S/SR/SRI/Mojolicious-7.33.tar.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tsuru/platforms/8552eab6474b194c571fc82a29e00d94cded5337/examples/perl/vendor/cache/authors/id/S/SR/SRI/Mojolicious-7.33.tar.gz -------------------------------------------------------------------------------- /examples/php/index.php: -------------------------------------------------------------------------------- 1 | 4 | -------------------------------------------------------------------------------- /examples/php/tsuru.yml: -------------------------------------------------------------------------------- 1 | healthcheck: 2 | path: / 3 | -------------------------------------------------------------------------------- /examples/play/Procfile: -------------------------------------------------------------------------------- 1 | web: target/universal/stage/bin/play -Dhttp.port=${PORT} -------------------------------------------------------------------------------- /examples/play/activator: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | ### ------------------------------- ### 4 | ### Helper methods for BASH scripts ### 5 | ### ------------------------------- ### 6 | 7 | realpath () { 8 | ( 9 | TARGET_FILE="$1" 10 | 11 | cd $(dirname "$TARGET_FILE") 12 | TARGET_FILE=$(basename "$TARGET_FILE") 13 | 14 | COUNT=0 15 | while [ -L "$TARGET_FILE" -a $COUNT -lt 100 ] 16 | do 17 | TARGET_FILE=$(readlink "$TARGET_FILE") 18 | cd $(dirname "$TARGET_FILE") 19 | TARGET_FILE=$(basename "$TARGET_FILE") 20 | COUNT=$(($COUNT + 1)) 21 | done 22 | 23 | if [ "$TARGET_FILE" == "." -o "$TARGET_FILE" == ".." ]; then 24 | cd "$TARGET_FILE" 25 | TARGET_FILEPATH= 26 | else 27 | TARGET_FILEPATH=/$TARGET_FILE 28 | fi 29 | 30 | # make sure we grab the actual windows path, instead of cygwin's path. 31 | if ! is_cygwin; then 32 | echo "$(pwd -P)/$TARGET_FILE" 33 | else 34 | echo $(cygwinpath "$(pwd -P)/$TARGET_FILE") 35 | fi 36 | ) 37 | } 38 | 39 | # TODO - Do we need to detect msys? 40 | 41 | # Uses uname to detect if we're in the odd cygwin environment. 42 | is_cygwin() { 43 | local os=$(uname -s) 44 | case "$os" in 45 | CYGWIN*) return 0 ;; 46 | *) return 1 ;; 47 | esac 48 | } 49 | 50 | # This can fix cygwin style /cygdrive paths so we get the 51 | # windows style paths. 52 | cygwinpath() { 53 | local file="$1" 54 | if is_cygwin; then 55 | echo $(cygpath -w $file) 56 | else 57 | echo $file 58 | fi 59 | } 60 | 61 | # Make something URI friendly 62 | make_url() { 63 | url="$1" 64 | local nospaces=${url// /%20} 65 | if is_cygwin; then 66 | echo "/${nospaces//\\//}" 67 | else 68 | echo "$nospaces" 69 | fi 70 | } 71 | 72 | # Detect if we should use JAVA_HOME or just try PATH. 73 | get_java_cmd() { 74 | if [[ -n "$JAVA_HOME" ]] && [[ -x "$JAVA_HOME/bin/java" ]]; then 75 | echo "$JAVA_HOME/bin/java" 76 | else 77 | echo "java" 78 | fi 79 | } 80 | 81 | echoerr () { 82 | echo 1>&2 "$@" 83 | } 84 | vlog () { 85 | [[ $verbose || $debug ]] && echoerr "$@" 86 | } 87 | dlog () { 88 | [[ $debug ]] && echoerr "$@" 89 | } 90 | execRunner () { 91 | # print the arguments one to a line, quoting any containing spaces 92 | [[ $verbose || $debug ]] && echo "# Executing command line:" && { 93 | for arg; do 94 | if printf "%s\n" "$arg" | grep -q ' '; then 95 | printf "\"%s\"\n" "$arg" 96 | else 97 | printf "%s\n" "$arg" 98 | fi 99 | done 100 | echo "" 101 | } 102 | 103 | exec "$@" 104 | } 105 | addJava () { 106 | dlog "[addJava] arg = '$1'" 107 | java_args=( "${java_args[@]}" "$1" ) 108 | } 109 | addApp () { 110 | dlog "[addApp] arg = '$1'" 111 | sbt_commands=( "${app_commands[@]}" "$1" ) 112 | } 113 | addResidual () { 114 | dlog "[residual] arg = '$1'" 115 | residual_args=( "${residual_args[@]}" "$1" ) 116 | } 117 | addDebugger () { 118 | addJava "-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=n,address=$1" 119 | } 120 | addConfigOpts () { 121 | dlog "[addConfigOpts] arg = '$*'" 122 | for item in $* 123 | do 124 | addJava "$item" 125 | done 126 | } 127 | # a ham-fisted attempt to move some memory settings in concert 128 | # so they need not be messed around with individually. 129 | get_mem_opts () { 130 | local mem=${1:-1024} 131 | local meta=$(( $mem / 4 )) 132 | (( $meta > 256 )) || meta=256 133 | (( $meta < 1024 )) || meta=1024 134 | 135 | # default is to set memory options but this can be overridden by code section below 136 | memopts="-Xms${mem}m -Xmx${mem}m" 137 | if [[ "${java_version}" > "1.8" ]]; then 138 | extmemopts="-XX:MetaspaceSize=64m -XX:MaxMetaspaceSize=${meta}m" 139 | else 140 | extmemopts="-XX:PermSize=64m -XX:MaxPermSize=${meta}m" 141 | fi 142 | 143 | if [[ "${java_opts}" == *-Xmx* ]] || [[ "${java_opts}" == *-Xms* ]] || [[ "${java_opts}" == *-XX:MaxPermSize* ]] || [[ "${java_opts}" == *-XX:ReservedCodeCacheSize* ]] || [[ "${java_opts}" == *-XX:MaxMetaspaceSize* ]]; then 144 | # if we detect any of these settings in ${java_opts} we need to NOT output our settings. 145 | # The reason is the Xms/Xmx, if they don't line up, cause errors. 146 | memopts="" 147 | extmemopts="" 148 | fi 149 | 150 | echo "${memopts} ${extmemopts}" 151 | } 152 | require_arg () { 153 | local type="$1" 154 | local opt="$2" 155 | local arg="$3" 156 | if [[ -z "$arg" ]] || [[ "${arg:0:1}" == "-" ]]; then 157 | die "$opt requires <$type> argument" 158 | fi 159 | } 160 | is_function_defined() { 161 | declare -f "$1" > /dev/null 162 | } 163 | 164 | # If we're *not* running in a terminal, and we don't have any arguments, then we need to add the 'ui' parameter 165 | detect_terminal_for_ui() { 166 | [[ ! -t 0 ]] && [[ "${#residual_args}" == "0" ]] && { 167 | addResidual "ui" 168 | } 169 | # SPECIAL TEST FOR MAC 170 | [[ "$(uname)" == "Darwin" ]] && [[ "$HOME" == "$PWD" ]] && [[ "${#residual_args}" == "0" ]] && { 171 | echo "Detected MAC OSX launched script...." 172 | echo "Swapping to UI" 173 | addResidual "ui" 174 | } 175 | } 176 | 177 | # Processes incoming arguments and places them in appropriate global variables. called by the run method. 178 | process_args () { 179 | while [[ $# -gt 0 ]]; do 180 | case "$1" in 181 | -h|-help) usage; exit 1 ;; 182 | -v|-verbose) verbose=1 && shift ;; 183 | -d|-debug) debug=1 && shift ;; 184 | -mem) require_arg integer "$1" "$2" && app_mem="$2" && shift 2 ;; 185 | -jvm-debug) 186 | if echo "$2" | grep -E ^[0-9]+$ > /dev/null; then 187 | addDebugger "$2" && shift 188 | else 189 | addDebugger 9999 190 | fi 191 | shift ;; 192 | -java-home) require_arg path "$1" "$2" && java_cmd="$2/bin/java" && shift 2 ;; 193 | -D*) addJava "$1" && shift ;; 194 | -J*) addJava "${1:2}" && shift ;; 195 | *) addResidual "$1" && shift ;; 196 | esac 197 | done 198 | 199 | is_function_defined process_my_args && { 200 | myargs=("${residual_args[@]}") 201 | residual_args=() 202 | process_my_args "${myargs[@]}" 203 | } 204 | } 205 | 206 | # Actually runs the script. 207 | run() { 208 | # TODO - check for sane environment 209 | 210 | # process the combined args, then reset "$@" to the residuals 211 | process_args "$@" 212 | detect_terminal_for_ui 213 | set -- "${residual_args[@]}" 214 | argumentCount=$# 215 | 216 | #check for jline terminal fixes on cygwin 217 | if is_cygwin; then 218 | stty -icanon min 1 -echo > /dev/null 2>&1 219 | addJava "-Djline.terminal=jline.UnixTerminal" 220 | addJava "-Dsbt.cygwin=true" 221 | fi 222 | 223 | # run sbt 224 | execRunner "$java_cmd" \ 225 | "-Dactivator.home=$(make_url "$activator_home")" \ 226 | $(get_mem_opts $app_mem) \ 227 | ${java_opts[@]} \ 228 | ${java_args[@]} \ 229 | -jar "$app_launcher" \ 230 | "${app_commands[@]}" \ 231 | "${residual_args[@]}" 232 | 233 | local exit_code=$? 234 | if is_cygwin; then 235 | stty icanon echo > /dev/null 2>&1 236 | fi 237 | exit $exit_code 238 | } 239 | 240 | # Loads a configuration file full of default command line options for this script. 241 | loadConfigFile() { 242 | cat "$1" | sed '/^\#/d' 243 | } 244 | 245 | ### ------------------------------- ### 246 | ### Start of customized settings ### 247 | ### ------------------------------- ### 248 | usage() { 249 | cat < [options] 251 | 252 | Command: 253 | ui Start the Activator UI 254 | new [name] [template-id] Create a new project with [name] using template [template-id] 255 | list-templates Print all available template names 256 | -h | -help Print this message 257 | 258 | Options: 259 | -v | -verbose Make this runner chattier 260 | -d | -debug Set sbt log level to debug 261 | -mem Set memory options (default: $sbt_mem, which is $(get_mem_opts $sbt_mem)) 262 | -jvm-debug Turn on JVM debugging, open at the given port. 263 | 264 | # java version (default: java from PATH, currently $(java -version 2>&1 | grep version)) 265 | -java-home Alternate JAVA_HOME 266 | 267 | # jvm options and output control 268 | -Dkey=val Pass -Dkey=val directly to the java runtime 269 | -J-X Pass option -X directly to the java runtime 270 | (-J is stripped) 271 | 272 | # environment variables (read from context) 273 | JAVA_OPTS Environment variable, if unset uses "" 274 | SBT_OPTS Environment variable, if unset uses "" 275 | ACTIVATOR_OPTS Environment variable, if unset uses "" 276 | 277 | In the case of duplicated or conflicting options, the order above 278 | shows precedence: environment variables lowest, command line options highest. 279 | EOM 280 | } 281 | 282 | ### ------------------------------- ### 283 | ### Main script ### 284 | ### ------------------------------- ### 285 | 286 | declare -a residual_args 287 | declare -a java_args 288 | declare -a app_commands 289 | declare -r real_script_path="$(realpath "$0")" 290 | declare -r activator_home="$(realpath "$(dirname "$real_script_path")")" 291 | declare -r app_version="1.2.12" 292 | 293 | declare -r app_launcher="${activator_home}/activator-launch-${app_version}.jar" 294 | declare -r script_name=activator 295 | declare -r java_cmd=$(get_java_cmd) 296 | declare -r java_opts=( "${ACTIVATOR_OPTS[@]}" "${SBT_OPTS[@]}" "${JAVA_OPTS[@]}" "${java_opts[@]}" ) 297 | userhome="$HOME" 298 | if is_cygwin; then 299 | # cygwin sets home to something f-d up, set to real windows homedir 300 | userhome="$USERPROFILE" 301 | fi 302 | declare -r activator_user_home_dir="${userhome}/.activator" 303 | declare -r java_opts_config_home="${activator_user_home_dir}/activatorconfig.txt" 304 | declare -r java_opts_config_version="${activator_user_home_dir}/${app_version}/activatorconfig.txt" 305 | 306 | # Now check to see if it's a good enough version 307 | declare -r java_version=$("$java_cmd" -version 2>&1 | awk -F '"' '/version/ {print $2}') 308 | if [[ "$java_version" == "" ]]; then 309 | echo 310 | echo No java installations was detected. 311 | echo Please go to http://www.java.com/getjava/ and download 312 | echo 313 | exit 1 314 | elif [[ ! "$java_version" > "1.6" ]]; then 315 | echo 316 | echo The java installation you have is not up to date 317 | echo Activator requires at least version 1.6+, you have 318 | echo version $java_version 319 | echo 320 | echo Please go to http://www.java.com/getjava/ and download 321 | echo a valid Java Runtime and install before running Activator. 322 | echo 323 | exit 1 324 | fi 325 | 326 | # if configuration files exist, prepend their contents to the java args so it can be processed by this runner 327 | # a "versioned" config trumps one on the top level 328 | if [[ -f "$java_opts_config_version" ]]; then 329 | addConfigOpts $(loadConfigFile "$java_opts_config_version") 330 | elif [[ -f "$java_opts_config_home" ]]; then 331 | addConfigOpts $(loadConfigFile "$java_opts_config_home") 332 | fi 333 | 334 | run "$@" 335 | -------------------------------------------------------------------------------- /examples/play/activator-launch-1.2.12.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tsuru/platforms/8552eab6474b194c571fc82a29e00d94cded5337/examples/play/activator-launch-1.2.12.jar -------------------------------------------------------------------------------- /examples/play/app/controllers/Application.scala: -------------------------------------------------------------------------------- 1 | // Copyright 2016 tsuru authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package controllers 6 | 7 | import play.api.mvc._ 8 | 9 | object Application extends Controller { 10 | 11 | def index = Action { 12 | Ok("Hello world from tsuru") 13 | } 14 | 15 | } 16 | -------------------------------------------------------------------------------- /examples/play/build.sbt: -------------------------------------------------------------------------------- 1 | name := """play""" 2 | 3 | version := "1.0-SNAPSHOT" 4 | 5 | lazy val root = (project in file(".")).enablePlugins(PlayScala) 6 | 7 | scalaVersion := "2.11.1" -------------------------------------------------------------------------------- /examples/play/conf/application.conf: -------------------------------------------------------------------------------- 1 | # This is the main configuration file for the application. 2 | # ~~~~~ 3 | 4 | # Secret key 5 | # ~~~~~ 6 | # The secret key is used to secure cryptographics functions. 7 | # 8 | # This must be changed for production, but we recommend not changing it in this file. 9 | # 10 | # See http://www.playframework.com/documentation/latest/ApplicationSecret for more details. 11 | application.secret="i/Yx?0A8^<7[3F5xXj3bvks32OhaW>DDKn= 2.0.2" 8 | -------------------------------------------------------------------------------- /examples/ruby/Gemfile.lock: -------------------------------------------------------------------------------- 1 | GEM 2 | remote: https://rubygems.org/ 3 | specs: 4 | mustermann (1.0.3) 5 | rack (2.2.3) 6 | rack-protection (2.0.4) 7 | rack 8 | sinatra (2.0.4) 9 | mustermann (~> 1.0) 10 | rack (~> 2.0) 11 | rack-protection (= 2.0.4) 12 | tilt (~> 2.0) 13 | tilt (2.0.8) 14 | 15 | PLATFORMS 16 | ruby 17 | 18 | DEPENDENCIES 19 | sinatra (>= 2.0.2) 20 | 21 | BUNDLED WITH 22 | 1.16.6 23 | -------------------------------------------------------------------------------- /examples/ruby/Procfile: -------------------------------------------------------------------------------- 1 | web: bundle exec ruby app.rb -o 0.0.0.0 -p $PORT 2 | -------------------------------------------------------------------------------- /examples/ruby/app.rb: -------------------------------------------------------------------------------- 1 | # Copyright 2016 tsuru authors. All rights reserved. 2 | # Use of this source code is governed by a BSD-style 3 | # license that can be found in the LICENSE file. 4 | 5 | require 'sinatra' 6 | 7 | get "/" do 8 | "Hello world from tsuru" 9 | end 10 | -------------------------------------------------------------------------------- /examples/ruby/hook.rb: -------------------------------------------------------------------------------- 1 | puts "hello" 2 | -------------------------------------------------------------------------------- /examples/ruby/tsuru.yml: -------------------------------------------------------------------------------- 1 | hooks: 2 | build: 3 | - ruby hook.rb 4 | healthcheck: 5 | path: / 6 | -------------------------------------------------------------------------------- /examples/static-reactjs/nginx.conf: -------------------------------------------------------------------------------- 1 | worker_processes 4; 2 | pid /var/lib/nginx/nginx.pid; 3 | include /etc/nginx/modules-enabled/*.conf; 4 | error_log stderr; 5 | 6 | events { 7 | worker_connections 1024; 8 | } 9 | 10 | http { 11 | include mime.types; 12 | default_type application/octet-stream; 13 | types_hash_max_size 2048; 14 | server_tokens off; 15 | 16 | sendfile on; 17 | 18 | keepalive_timeout 65; 19 | access_log /dev/stdout; 20 | 21 | server { 22 | listen 8888; 23 | server_name localhost; 24 | 25 | port_in_redirect off; 26 | 27 | location / { 28 | root /home/application/current; 29 | index index.html index.htm; 30 | try_files $uri $uri/ $uri.html /index.html; 31 | } 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /examples/static-reactjs/tsuru.yml: -------------------------------------------------------------------------------- 1 | healthcheck: 2 | path: / 3 | -------------------------------------------------------------------------------- /examples/static/index.html: -------------------------------------------------------------------------------- 1 | Hello world from tsuru 2 | -------------------------------------------------------------------------------- /examples/static/tsuru.yml: -------------------------------------------------------------------------------- 1 | healthcheck: 2 | path: / 3 | -------------------------------------------------------------------------------- /go/Dockerfile: -------------------------------------------------------------------------------- 1 | # Copyright 2015 tsuru authors. All rights reserved. 2 | # Use of this source code is governed by a BSD-style 3 | # license that can be found in the LICENSE file. 4 | 5 | FROM tsuru/base-platform:22.04 6 | COPY . /var/lib/tsuru/go 7 | RUN set -ex \ 8 | && sudo /var/lib/tsuru/go/install \ 9 | && sudo rm -rf /var/lib/tsuru/go/install /var/lib/apt/lists/* \ 10 | && sudo ln -sf /var/lib/tsuru/go/deploy /var/lib/tsuru/deploy 11 | -------------------------------------------------------------------------------- /go/Procfile: -------------------------------------------------------------------------------- 1 | web: ./tsuru-app 2 | -------------------------------------------------------------------------------- /go/README.md: -------------------------------------------------------------------------------- 1 | Go platform 2 | =========== 3 | 4 | Official guide: https://tsuru.github.io/docs/user_guides/deploy_go_apps/ 5 | -------------------------------------------------------------------------------- /go/deploy: -------------------------------------------------------------------------------- 1 | #!/bin/bash -el 2 | 3 | # Copyright 2015 tsuru authors. All rights reserved. 4 | # Use of this source code is governed by a BSD-style 5 | # license that can be found in the LICENSE file. 6 | 7 | SOURCE_DIR=/var/lib/tsuru 8 | source ${SOURCE_DIR}/base/deploy 9 | source ${SOURCE_DIR}/base/rc/config 10 | 11 | GO_INSTALL_DIR="/home/application/go" 12 | GO_DOWNLOAD_URL=${GO_DOWNLOAD_URL:-"https://dl.google.com/go"} 13 | GO_RELEASES_URL=${GO_RELEASES_URL:-"https://go.dev/dl/?mode=json&include=all"} 14 | 15 | all_releases=$(curl -m10 -sSf ${GO_RELEASES_URL}) 16 | versions=$(jq -r '.[].version' <<<${all_releases}) 17 | 18 | # Try exact match first and fallback to closest version excluding non stable 19 | # releases. 20 | if grep -xF "go${GO_VERSION}" <<<${versions} >/dev/null; then 21 | version_to_install="go${GO_VERSION}" 22 | version_source="exact match from \$GO_VERSION" 23 | else 24 | escaped_version=$(sed 's/\./\\./g' <<<${GO_VERSION} | sed 's/\\\.x/\(\\..+|$\)/g') 25 | stable_versions=$(egrep 'go[0-9.]+$' <<<${versions}) 26 | version_to_install=$(egrep "go${escaped_version}$" <<<${stable_versions} | sort -rV | head -n 1) 27 | version_source="closest match from \$GO_VERSION=${GO_VERSION}" 28 | fi 29 | 30 | # Install latest version 31 | if [[ ${version_to_install} == "" ]]; then 32 | if [[ $GO_VERSION != "" ]]; then 33 | echo "Unable to find go version matching \$GO_VERSION=${GO_VERSION}." 34 | fi 35 | version_to_install=$(egrep 'go[0-9.]+$' <<<${versions} | sort -rV | head -n 1) 36 | version_source="latest version" 37 | fi 38 | 39 | 40 | echo "Installing Go ${version_to_install} (${version_source})" 41 | 42 | rm -rf ${GO_INSTALL_DIR} 43 | version_dir=${GO_INSTALL_DIR}_${version_to_install} 44 | rm -rf ${version_dir} 45 | mkdir -p ${version_dir} 46 | download_url=${GO_DOWNLOAD_URL}/${version_to_install}.linux-amd64.tar.gz 47 | 48 | if ! (curl -m 120 -sS --retry 3 -L "$download_url" | tar xz -C ${version_dir}); then 49 | echo "ERROR: Unable to download Go from ${download_url}." 50 | exit 1 51 | fi 52 | 53 | rm -rf ${version_dir}/api/ \ 54 | ${version_dir}/blog/ \ 55 | ${version_dir}/doc/ \ 56 | ${version_dir}/test/ \ 57 | ${version_dir}/lib/ \ 58 | ${version_dir}/misc/ 59 | 60 | ln -s ${version_dir}/go ${GO_INSTALL_DIR} 61 | hash -r 62 | 63 | echo "Using Go version: $(go version)" 64 | 65 | if [ -z $(find ${APP_DIR}/current -name "*.go" -print -quit) ]; then 66 | exit 0 67 | fi 68 | 69 | APP_PATH=${APP_DIR}/src/current 70 | 71 | if [ -n "${GO_PKG_PATH}" ] 72 | then 73 | APP_PATH=${APP_DIR}/src/${GO_PKG_PATH} 74 | fi 75 | 76 | mkdir -p ${APP_PATH} 77 | rm -rf ${APP_PATH} 78 | ln -s ${APP_DIR}/current ${APP_PATH} 79 | chown ${USER}:${USER} ${APP_PATH} 80 | 81 | pushd ${APP_PATH} >/dev/null 2>&1 82 | 83 | # do not fail if the application is not go gettable 84 | set +e 85 | go get -d . 86 | set -e 87 | 88 | if [ -f ${APP_DIR}/current/go.mod ] && [ -d ${APP_DIR}/current/vendor ]; then 89 | GO_BUILD_VENDOR="-mod=vendor" 90 | fi 91 | 92 | if [ -f ${APP_DIR}/.default_procfile ] 93 | then 94 | echo "Procfile not found. Using default Procfile" 95 | 96 | echo "go build -o tsuru-app" 97 | go build $GO_BUILD_VENDOR -o tsuru-app 98 | else 99 | go build $GO_BUILD_VENDOR 2>/dev/null || true 100 | go install $GO_BUILD_VENDOR ./... 101 | fi 102 | 103 | go clean -cache 104 | go clean -modcache 105 | 106 | rm -rf ${version_dir} 107 | 108 | popd >/dev/null 2>&1 109 | -------------------------------------------------------------------------------- /go/install: -------------------------------------------------------------------------------- 1 | #!/bin/bash -el 2 | 3 | # Copyright 2015 tsuru authors. All rights reserved. 4 | # Use of this source code is governed by a BSD-style 5 | # license that can be found in the LICENSE file. 6 | 7 | SOURCE_DIR=/var/lib/tsuru 8 | source ${SOURCE_DIR}/base/rc/config 9 | 10 | apt-get update 11 | apt-get install -y --no-install-recommends curl jq git 12 | 13 | cp ${SOURCE_DIR}/go/Procfile ${SOURCE_DIR}/default/Procfile 14 | echo "export GOPATH=${APP_DIR}" | tee -a ${HOME}/.profile /etc/profile >/dev/null 15 | echo "export PATH=${APP_DIR}/bin:/home/application/go/bin:${PATH}" | tee -a ${HOME}/.profile /etc/profile >/dev/null 16 | -------------------------------------------------------------------------------- /java/Dockerfile: -------------------------------------------------------------------------------- 1 | # Copyright 2016 tsuru authors. All rights reserved. 2 | # Use of this source code is governed by a BSD-style 3 | # license that can be found in the LICENSE file. 4 | 5 | FROM tsuru/base-platform:22.04 6 | COPY . /var/lib/tsuru/java 7 | RUN set -ex \ 8 | && sudo /var/lib/tsuru/java/install \ 9 | && sudo rm -rf /var/lib/tsuru/java/install /var/lib/apt/lists/* \ 10 | && sudo ln -sf /var/lib/tsuru/base/deploy /var/lib/tsuru/deploy 11 | -------------------------------------------------------------------------------- /java/Procfile: -------------------------------------------------------------------------------- 1 | web: /var/lib/tsuru/java/start-tomcat 2 | -------------------------------------------------------------------------------- /java/README.md: -------------------------------------------------------------------------------- 1 | # Java platform 2 | 3 | The Java platform supports two kinds of deployment: binary using default tomcat 4 | server or code deployment. 5 | 6 | ## Binary deployment 7 | 8 | You can send a jar file, and java platform will run it with default Procfile 9 | and tomcat7. Default procfile starts with: 10 | 11 | % cat Procfile 12 | web: /var/lib/tsuru/java/start-tomcat 13 | 14 | You can set ``JAVA_MAX_MEMORY`` enviroment variable to set amount memory to run 15 | tomcat, if you don't it will start with 128MB. 16 | 17 | 18 | ## Code deployment 19 | 20 | If you just run a ``tsuru app-deploy`` of your code, 21 | tsuru will try to download all of your dependencies using ``maven`` 22 | and build your application. 23 | -------------------------------------------------------------------------------- /java/install: -------------------------------------------------------------------------------- 1 | #!/bin/bash -e 2 | 3 | # Copyright 2016 tsuru authors. All rights reserved. 4 | # Use of this source code is governed by a BSD-style 5 | # license that can be found in the LICENSE file. 6 | 7 | SOURCE_DIR=/var/lib/tsuru 8 | source ${SOURCE_DIR}/base/rc/config 9 | 10 | apt-get update 11 | apt-get install -y --no-install-recommends \ 12 | openjdk-11-jdk \ 13 | maven \ 14 | tomcat9 15 | 16 | cp $SOURCE_DIR/java/Procfile $SOURCE_DIR/default/Procfile 17 | 18 | rm -rf /var/lib/tomcat9/webapps 19 | ln -s ${CURRENT_DIR} /var/lib/tomcat9/webapps 20 | mkdir -p /usr/share/tomcat9/common/classes /usr/share/tomcat9/server/classes /usr/share/tomcat9/shared/classes 21 | chown -R ${USER}:${USER} /etc/tomcat9 /var/lib/tomcat9 /var/cache/tomcat9 /var/log/tomcat9 /usr/share/tomcat9 22 | sed -i 's/8080/8888/' /etc/tomcat9/server.xml 23 | -------------------------------------------------------------------------------- /java/start-tomcat: -------------------------------------------------------------------------------- 1 | #!/bin/bash -e 2 | 3 | # Copyright 2016 tsuru authors. All rights reserved. 4 | # Use of this source code is governed by a BSD-style 5 | # license that can be found in the LICENSE file. 6 | 7 | XMX=${JAVA_MAX_MEMORY-128} 8 | 9 | mkdir -p /tmp/tomcat9-tomcat9-tmp 10 | java -Djava.util.logging.config.file=/var/lib/tomcat9/conf/logging.properties -Djava.util.logging.manager=org.apache.juli.ClassLoaderLogManager -Djava.awt.headless=true -Xmx${XMX}m -XX:+UseConcMarkSweepGC -classpath /usr/share/tomcat9/bin/bootstrap.jar:/usr/share/tomcat9/bin/tomcat-juli.jar -Dcatalina.base=/var/lib/tomcat9 -Dcatalina.home=/usr/share/tomcat9 -Djava.io.tmpdir=/tmp/tomcat9-tomcat9-tmp org.apache.catalina.startup.Bootstrap start 11 | -------------------------------------------------------------------------------- /lua/Dockerfile: -------------------------------------------------------------------------------- 1 | # Copyright 2016 tsuru authors. All rights reserved. 2 | # Use of this source code is governed by a BSD-style 3 | # license that can be found in the LICENSE file. 4 | 5 | FROM tsuru/base-platform:22.04 6 | COPY . /var/lib/tsuru/lua 7 | RUN set -ex \ 8 | && sudo /var/lib/tsuru/lua/install \ 9 | && sudo rm -rf /var/lib/tsuru/lua/install /var/lib/apt/lists/* \ 10 | && sudo ln -sf /var/lib/tsuru/lua/deploy /var/lib/tsuru/deploy 11 | -------------------------------------------------------------------------------- /lua/README.md: -------------------------------------------------------------------------------- 1 | # Lua Platform 2 | 3 | The Lua platform uses Lua 5.3 and latest LuaRocks available. 4 | 5 | ## Code deployment with dependencies 6 | 7 | We're using Luarocks to manage packages for Lua, and tsuru will expect 8 | for a file called `tsuru-1.0-1.rockspec` for dependencies definitions. 9 | -------------------------------------------------------------------------------- /lua/deploy: -------------------------------------------------------------------------------- 1 | #!/bin/bash -le 2 | 3 | # Copyright 2016 tsuru authors. All rights reserved. 4 | # Use of this source code is governed by a BSD-style 5 | # license that can be found in the LICENSE file. 6 | 7 | SOURCE_DIR=/var/lib/tsuru 8 | source ${SOURCE_DIR}/base/deploy 9 | source ${SOURCE_DIR}/base/rc/config 10 | 11 | if [ -f ${CURRENT_DIR}/tsuru-1.0-1.rockspec ]; then 12 | pushd ${CURRENT_DIR} >/dev/null 2>&1 13 | sudo luarocks install tsuru-1.0-1.rockspec 14 | popd >/dev/null 2>&1 15 | fi 16 | -------------------------------------------------------------------------------- /lua/install: -------------------------------------------------------------------------------- 1 | #!/bin/bash -el 2 | 3 | # Copyright 2016 tsuru authors. All rights reserved. 4 | # Use of this source code is governed by a BSD-style 5 | # license that can be found in the LICENSE file. 6 | 7 | SOURCE_DIR=/var/lib/tsuru 8 | source ${SOURCE_DIR}/base/rc/config 9 | 10 | apt-get update 11 | apt-get install -y --no-install-recommends \ 12 | make \ 13 | gcc \ 14 | build-essential \ 15 | libreadline8 \ 16 | libreadline-dev 17 | 18 | 19 | cd /tmp 20 | curl -fsSLO https://www.lua.org/ftp/lua-5.4.4.tar.gz 21 | echo "03c27684b9d5d9783fb79a7c836ba1cdc5f309cd lua-5.4.4.tar.gz" | sha1sum --check 22 | tar -xzvf lua-5.4.4.tar.gz 23 | cd lua-5.4.4 24 | make linux test 25 | mv ./src/lua /usr/bin/lua 26 | mv ./src/luac /usr/bin/luac 27 | rm -rf lua-5.4.4 28 | cd / 29 | 30 | apt-get install -y luarocks git 31 | apt-get remove make gcc -y 32 | apt-get autoremove -y 33 | -------------------------------------------------------------------------------- /nodejs/Dockerfile: -------------------------------------------------------------------------------- 1 | # Copyright 2015 tsuru authors. All rights reserved. 2 | # Use of this source code is governed by a BSD-style 3 | # license that can be found in the LICENSE file. 4 | 5 | FROM tsuru/base-platform:22.04 6 | COPY . /var/lib/tsuru/nodejs 7 | RUN set -ex \ 8 | && /var/lib/tsuru/nodejs/install \ 9 | && sudo rm -rf /var/lib/tsuru/nodejs/install /var/lib/apt/lists/* \ 10 | && sudo ln -sf /var/lib/tsuru/nodejs/deploy /var/lib/tsuru/deploy 11 | -------------------------------------------------------------------------------- /nodejs/README.md: -------------------------------------------------------------------------------- 1 | Node.js platform 2 | =========== 3 | 4 | Official guide: https://tsuru.github.io/docs/user_guides/deploy_nodejs_apps/ 5 | -------------------------------------------------------------------------------- /nodejs/deploy: -------------------------------------------------------------------------------- 1 | #!/bin/bash -le 2 | 3 | # Copyright 2015 tsuru authors. All rights reserved. 4 | # Use of this source code is governed by a BSD-style 5 | # license that can be found in the LICENSE file. 6 | 7 | SOURCE_DIR=/var/lib/tsuru 8 | source ${SOURCE_DIR}/base/rc/config 9 | 10 | function calculate_deps_hash() { 11 | local basepath=$1 12 | set +e 13 | pushd ${basepath} >/dev/null 14 | tail -n +1 \ 15 | ./package.json \ 16 | ./package-lock.json \ 17 | ./yarn.lock \ 18 | 2>/dev/null | sha256sum | awk '{print $1}' 19 | popd >/dev/null 20 | set -e 21 | } 22 | 23 | function archive_deps_hash() { 24 | if [[ ! -f /home/application/archive.tar.gz ]]; then 25 | return 26 | fi 27 | tmpdir=$(mktemp -d) 28 | trap "rm -rf ${tmpdir}" EXIT 29 | set +e 30 | tar -C ${tmpdir} -xzf /home/application/archive.tar.gz package.json package-lock.json yarn.lock 2>/dev/null 31 | set -e 32 | calculate_deps_hash ${tmpdir} 33 | } 34 | 35 | function track_deps() { 36 | mkdir -p /home/application/nodejs 37 | set +e 38 | cp ${CURRENT_DIR}/package.json \ 39 | ${CURRENT_DIR}/package-lock.json \ 40 | ${CURRENT_DIR}/yarn.lock \ 41 | /home/application/nodejs/ \ 42 | 2>/dev/null 43 | set -e 44 | } 45 | 46 | # If dependency files didn't change it's safe for us to protect the 47 | # `node_modules` directory from being removed by rsync. If dependency files 48 | # were updated it's safer to remove node_modules and reinstall everything. 49 | if [[ -d ${CURRENT_DIR}/node_modules ]]; then 50 | old_deps_hash=$(calculate_deps_hash /home/application/nodejs) 51 | new_deps_hash=$(archive_deps_hash) 52 | 53 | if [[ "${old_deps_hash}" == "${new_deps_hash}" ]]; then 54 | keep=1 55 | reason="Dependency files hash match" 56 | elif [[ -n "${KEEP_NODE_MODULES}" ]] ; then 57 | keep=1 58 | reason="Environment variable \$KEEP_NODE_MODULES is set" 59 | fi 60 | if [[ $keep == 1 ]]; then 61 | echo "${reason}, preserving old node_modules directory." 62 | PLATFORM_EXTRA_RSYNC_ARGS='--filter "protect node_modules/"' 63 | fi 64 | fi 65 | 66 | source ${SOURCE_DIR}/base/deploy 67 | 68 | NODE_VERSION=--lts 69 | 70 | if [ -f ${CURRENT_DIR}/.nvmrc ]; then 71 | TMP_VERSION=$(cat ${CURRENT_DIR}/.nvmrc) 72 | elif [ -f ${CURRENT_DIR}/.node-version ]; then 73 | TMP_VERSION=$(cat ${CURRENT_DIR}/.node-version) 74 | elif [ -f ${CURRENT_DIR}/package.json ]; then 75 | TMP_VERSION=$(jq -r '.engines | .node | select(. != null)' ${CURRENT_DIR}/package.json) 76 | fi 77 | 78 | if [ -n "$TMP_VERSION" ]; then 79 | NODE_VERSION=${TMP_VERSION} 80 | fi 81 | 82 | if [ $NPM_REGISTRY ]; then 83 | echo "registry = $NPM_REGISTRY" > ~/.npmrc 84 | fi 85 | 86 | if [ $NVM_IOJS_ORG_MIRROR ] && [[ "$NODE_VERSION" =~ ^(iojs-v|v)?[123](\.[0-9]+)?(\.[0-9]+)? ]]; then 87 | echo "disturl = $NVM_IOJS_ORG_MIRROR" >> ~/.npmrc 88 | elif [ $NVM_NODEJS_ORG_MIRROR ]; then 89 | echo "disturl = $NVM_NODEJS_ORG_MIRROR" >> ~/.npmrc 90 | fi 91 | 92 | export NVM_DIR=${NVM_DIR:-${HOME}/.nvm} 93 | [ ! -e ${NVM_DIR} ] && mkdir -p ${NVM_DIR} 94 | 95 | set +e 96 | . ${NVM_DIR}/nvm.sh 97 | nvm_source_exit_code="$?" 98 | set -e 99 | 100 | if [[ "$nvm_source_exit_code" != "0" ]]; then 101 | echo "WARNING: sourcing nvm.sh returned exit status ${nvm_source_exit_code}. This may not be a problem but report this message if the deploy fails." 102 | fi 103 | 104 | set +e 105 | nvm install "${NODE_VERSION}" 106 | nvm_install_exit_code="$?" 107 | set -e 108 | 109 | if [[ "$nvm_install_exit_code" != "0" ]]; then 110 | echo "ERROR: \`nvm install \"${NODE_VERSION}\"\` returned exit status ${nvm_install_exit_code}." 111 | exit "${nvm_install_exit_code}" 112 | fi 113 | 114 | nvm cache clear 115 | 116 | # removing default alias - fix X.Y.* wildcard bug on subsequents deploys 117 | if [[ -f ~/.nvm/alias/default ]]; then 118 | rm ~/.nvm/alias/default 119 | fi 120 | 121 | rm -f ~/.nvm_bin 122 | ln -s $NVM_BIN ~/.nvm_bin 123 | 124 | # Set --production flag only if NPM_CONFIG_PRODUCTION env var is not set 125 | if [ -z "$NPM_CONFIG_PRODUCTION" ]; then 126 | PRODUCTION_FLAG="--production" 127 | else 128 | PRODUCTION_FLAG="" 129 | fi 130 | 131 | track_deps 132 | 133 | if [ -f "${CURRENT_DIR}/package.json" ] && [ -f "${CURRENT_DIR}/yarn.lock" ]; then 134 | echo "yarn.lock detected, using yarn to install node packages" 135 | YARN_DEFAULT_VERSION="1.21.1" 136 | yarn_bin=${NVM_BIN}/yarn 137 | if [ ! -f $yarn_bin ]; then 138 | package_version=$(node -e " 139 | var pkg = require('${CURRENT_DIR}/package.json'); 140 | var options = ['engines', 'dependencies', 'devDependencies']; 141 | for (var o of options) { 142 | if (pkg[o] && pkg[o].yarn) { 143 | console.log(pkg[o].yarn); 144 | break; 145 | } 146 | }") 147 | YARN_VERSION=${package_version:-$YARN_DEFAULT_VERSION} 148 | npm install -g yarn@${YARN_VERSION} 149 | fi 150 | if [ $NPM_REGISTRY ]; then 151 | echo "registry \"$NPM_REGISTRY\"" > ~/.yarnrc 152 | sed -i -E "s|https?://registry.yarnpkg.com|$NPM_REGISTRY|g" ${CURRENT_DIR}/yarn.lock 153 | sed -i -E "s|https?://registry.npmjs.org|$NPM_REGISTRY|g" ${CURRENT_DIR}/yarn.lock 154 | fi 155 | pushd $CURRENT_DIR 156 | set +e 157 | exec 9>&1 158 | TMPFILE=`mktemp` 159 | YARN_OUTPUT=`${yarn_bin} install ${PRODUCTION_FLAG} --non-interactive 2>&1 | tee /dev/fd/9; echo ${PIPESTATUS[0]} > $TMPFILE` 160 | STATUS=`cat $TMPFILE 2>/dev/null || echo 1` 161 | set -e 162 | if [ $STATUS -ne 0 ]; then 163 | if [[ $YARN_OUTPUT =~ ^.*unknown\ option.*--non-interactive.*$ ]]; then 164 | # If --non-interactive flag is not available (older yarn versions), falls back to the default install command 165 | ${yarn_bin} install ${PRODUCTION_FLAG} 166 | else 167 | exit $STATUS 168 | fi 169 | fi 170 | yarn cache clean || true 171 | popd 172 | elif [ -f ${CURRENT_DIR}/package.json ] ; then 173 | if [ -f "${CURRENT_DIR}/package-lock.json" ]; then 174 | sed -i -E "s|https?://registry.npmjs.org|$NPM_REGISTRY|g" ${CURRENT_DIR}/package-lock.json 175 | fi 176 | pushd $CURRENT_DIR 177 | npm install ${PRODUCTION_FLAG} 178 | npm cache clean --force || true 179 | popd 180 | fi 181 | -------------------------------------------------------------------------------- /nodejs/install: -------------------------------------------------------------------------------- 1 | #!/bin/bash -le 2 | 3 | # Copyright 2015 tsuru authors. All rights reserved. 4 | # Use of this source code is governed by a BSD-style 5 | # license that can be found in the LICENSE file. 6 | set -euf -o pipefail 7 | 8 | SOURCE_DIR=/var/lib/tsuru 9 | source ${SOURCE_DIR}/base/rc/config 10 | 11 | curl -fsSLo- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.7/install.sh | sudo -E -u ${USER} bash 12 | 13 | cat >> ~/.profile <<-EOF 14 | export PATH=${PATH}:${HOME}/.nvm_bin 15 | EOF 16 | -------------------------------------------------------------------------------- /perl/Dockerfile: -------------------------------------------------------------------------------- 1 | # Copyright 2017 tsuru authors. All rights reserved. 2 | # Use of this source code is governed by a BSD-style 3 | # license that can be found in the LICENSE file. 4 | 5 | FROM tsuru/base-platform:22.04 6 | COPY . /var/lib/tsuru/perl 7 | RUN set -ex \ 8 | && sudo /var/lib/tsuru/perl/install \ 9 | && sudo rm -rf /var/lib/tsuru/perl/install /var/lib/apt/lists/* \ 10 | && sudo cp /var/lib/tsuru/perl/deploy /var/lib/tsuru 11 | -------------------------------------------------------------------------------- /perl/README.md: -------------------------------------------------------------------------------- 1 | # Perl platform 2 | 3 | The Perl platform supports Perl 5.18.2 (on Ubuntu 14.04 LTS) or Perl 5.22.1 (on Ubuntu 16.04 LTS). 4 | 5 | ## Code deployment 6 | 7 | If you just run a ``tsuru app deploy`` of your code, tsuru will try 8 | to download all of your depencies using ``cpanfile`` or ``cpanfile.snapshot``. 9 | 10 | ## Code deployment with dependencies 11 | 12 | There are two ways to list the applications dependencies: ``cpanfile`` or ``cpanfile.snapshot``. 13 | The priority order is: ``cpanfile.snapshot`` -> ``cpanfile``. The file should be in the root of deploy files. 14 | 15 | ### Using [carton](https://metacpan.org/pod/Carton) + [cpanfile](https://metacpan.org/pod/cpanfile) 16 | 17 | You can define a file called ``cpanfile`` that list all CPAN dependencies of your application, 18 | each line represents one dependency, here's an example: 19 | 20 | $ cat cpanfile 21 | requires 'Mojolicious'; 22 | 23 | 24 | ### Using [carton](https://metacpan.org/pod/Carton) + cpanfile.snapshot 25 | 26 | After invokin ``tsuru app deploy``, tsuru will receive your code and tell the platform 27 | to install all the depencies using ``carton install --cached --deployment``. 28 | 29 | -------------------------------------------------------------------------------- /perl/deploy: -------------------------------------------------------------------------------- 1 | #!/bin/bash -el 2 | 3 | # Copyright 2017 tsuru authors. All rights reserved. 4 | # Use of this source code is governed by a BSD-style 5 | # license that can be found in the LICENSE file. 6 | 7 | SOURCE_DIR=/var/lib/tsuru 8 | source ${SOURCE_DIR}/base/deploy 9 | source ${SOURCE_DIR}/base/rc/config 10 | 11 | pushd $CURRENT_DIR 12 | if [ -f ${CURRENT_DIR}/cpanfile.snapshot ]; then 13 | if [ -d ${CURRENT_DIR}/vendor ]; then 14 | carton install --cached --deployment 15 | else 16 | carton install --deployment 17 | fi 18 | elif [ -f ${CURRENT_DIR}/cpanfile ]; then 19 | carton install 20 | fi 21 | popd 22 | -------------------------------------------------------------------------------- /perl/install: -------------------------------------------------------------------------------- 1 | #!/bin/bash -e 2 | 3 | # Copyright 2017 tsuru authors. All rights reserved. 4 | # Use of this source code is governed by a BSD-style 5 | # license that can be found in the LICENSE file. 6 | 7 | SOURCE_DIR=/var/lib/tsuru 8 | source ${SOURCE_DIR}/base/rc/config 9 | source ${SOURCE_DIR}/base/rc/os_dependencies 10 | 11 | add_repository ppa:pypy/ppa 12 | apt-get update 13 | apt-get install -y --no-install-recommends carton make 14 | -------------------------------------------------------------------------------- /php/Dockerfile: -------------------------------------------------------------------------------- 1 | # Copyright 2015 tsuru authors. All rights reserved. 2 | # Use of this source code is governed by a BSD-style 3 | # license that can be found in the LICENSE file. 4 | 5 | FROM tsuru/base-platform:22.04 6 | COPY . /var/lib/tsuru/php 7 | RUN set -ex \ 8 | && sudo /var/lib/tsuru/php/install \ 9 | && sudo rm -rf /var/lib/tsuru/php/install /var/lib/apt/lists/* \ 10 | && sudo cp /var/lib/tsuru/php/deploy /var/lib/tsuru 11 | -------------------------------------------------------------------------------- /php/README.md: -------------------------------------------------------------------------------- 1 | # PHP platform 2 | 3 | The PHP platform is built to be able to manage multiple front-end and interpretors. You can manage them in your `tsuru.yml` configuration file. 4 | 5 | ```yml 6 | php: 7 | version: 5.6 8 | frontend: 9 | name: nginx 10 | interpretor: 11 | name: fpm 12 | composer: true 13 | ``` 14 | ## Versions 15 | 16 | Currently, php supported versions are: 17 | - 5.6 18 | - 7.0 19 | - 7.1 20 | - 7.2 21 | - 8.0 22 | - 8.1 23 | - 8.2 24 | - 8.3 25 | 26 | ## Front ends 27 | 28 | The following frontends are currently supported: 29 | - `apache`: Apache 30 | - `nginx`: Nginx 31 | 32 | You can chose between them by setting the `php.frontend.name` parameter: 33 | ```yml 34 | php: 35 | frontend: 36 | name: apache 37 | ``` 38 | 39 | Each frontend supports options that can be set in the `php.frontend.options` parameters. 40 | 41 | All these options are not required, and can be used the following way: 42 | ```yml 43 | php: 44 | frontend: 45 | name: apache 46 | options: 47 | vhost_file: /path/to/vhost.conf 48 | modules: 49 | - rewrite 50 | ``` 51 | 52 | ### Apache options 53 | 54 | - `vhost_file`: The relative path of your Apache virtual host configuration file 55 | - `modules`: An array of module names, such as `rewrite` for instance 56 | 57 | ### Nginx options 58 | 59 | - `vhost_file`: The relative path of your Nginx virtual host configuration file 60 | 61 | ## Interpretors 62 | 63 | The following PHP interpretors are supported: 64 | 65 | - `fpm`: PHP-FPM 66 | 67 | You can chose between them by setting the `php.interpretor.name` parameter: 68 | ```yml 69 | php: 70 | interpretor: 71 | name: fpm 72 | ``` 73 | 74 | These interpretors can also have options configured in the `php.interpretor.options` parameter. 75 | 76 | If you choose `fpm` interpretor, use `extensions` option to install php extensions instead of using `requirements.apt` 77 | 78 | All these options are not required and can be used the following ways 79 | ```yml 80 | php: 81 | interpretor: 82 | name: fpm54 83 | options: 84 | ini_file: /path/to/file.ini 85 | extensions: 86 | - php-mysql 87 | ``` 88 | 89 | ## `fpm` options 90 | 91 | - `ini_file`: The relative path of your `php.ini` file in your project, that will replace the default one 92 | - `extensions`: A list of php extensions you need 93 | 94 | ## General options 95 | 96 | In addition to the `frontend` and `interpretor` options, there's an other one: 97 | 98 | - `composer`: A boolean that is by default to true. If the value is true, it'll run a `composer install` if there's a `composer.json` file at the root of your application. 99 | 100 | ## Backward compatibility 101 | 102 | To keep the backward compatibility, there's also a `apache-mod-php` frontend that is in fact the Apache with modphp enabled, that remove the need of an interpretor. 103 | That's currently the default configuration if no parameter is set along php version 5.6. 104 | 105 | ## Next steps 106 | 107 | With the current implementation, it's quite easy to add another interpretor for instance. 108 | -------------------------------------------------------------------------------- /php/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tsuru/platforms/8552eab6474b194c571fc82a29e00d94cded5337/php/__init__.py -------------------------------------------------------------------------------- /php/deploy: -------------------------------------------------------------------------------- 1 | #!/bin/bash -el 2 | 3 | # Copyright 2015 tsuru authors. All rights reserved. 4 | # Use of this source code is governed by a BSD-style 5 | # license that can be found in the LICENSE file. 6 | 7 | SOURCE_DIR=/var/lib/tsuru 8 | source ${SOURCE_DIR}/base/rc/config 9 | source ${SOURCE_DIR}/base/deploy 10 | 11 | echo "Deploying the PHP application..." 12 | 13 | # Deploying 14 | echo "Starting application configuration" 15 | if [ ! -d "${CURRENT_DIR}" ]; then 16 | mkdir ${CURRENT_DIR} && chown ${USER} ${CURRENT_DIR} 17 | fi 18 | sudo -E python ${SOURCE_DIR}/php/deploy.py install 19 | python ${SOURCE_DIR}/php/deploy.py environment 20 | -------------------------------------------------------------------------------- /php/deploy.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | # Copyright 2015 tsuru authors. All rights reserved. 4 | # Use of this source code is governed by a BSD-style 5 | # license that can be found in the LICENSE file. 6 | 7 | import os 8 | import yaml 9 | import sys 10 | import re 11 | from utils import parse_env 12 | 13 | from interpretor import interpretors 14 | from frontend import frontends 15 | from vars import php_versions, default_version 16 | 17 | 18 | class ConfigurationException(Exception): 19 | pass 20 | 21 | 22 | class InstallationException(Exception): 23 | pass 24 | 25 | 26 | class Manager(object): 27 | 28 | def __init__(self, configuration, application): 29 | self.configuration = configuration 30 | self.application = application 31 | 32 | self.frontend = self.create_frontend() 33 | self.interpretor = self.create_interpretor() 34 | 35 | def install(self): 36 | # Calling pre-install hooks 37 | self.frontend.pre_install() 38 | if self.interpretor is not None: 39 | self.interpretor.pre_install() 40 | 41 | packages_php_extensions = [] 42 | if self.interpretor is not None: 43 | packages_php_extensions = self.interpretor.get_packages_extensions() 44 | 45 | if packages_php_extensions: 46 | print('Installing php extensions..') 47 | packages_to_install = [] 48 | for package in packages_php_extensions: 49 | if "-" in package: 50 | packages_to_install.append(self.prefix_package_version(package.split("-")[1])) 51 | else: 52 | packages_to_install.append(self.prefix_package_version(package)) 53 | try: 54 | if os.system("sudo apt-get install -y --force-yes %s" % (' '.join(packages_to_install))) != 0: 55 | raise InstallationException('An error appeared while installing needed packages') 56 | except InstallationException: 57 | os.system("apt-get update") 58 | if os.system("sudo apt-get install -y --force-yes %s" % (' '.join(packages_to_install))) != 0: 59 | raise InstallationException('An error appeared while installing needed packages') 60 | for package in packages_to_install: 61 | module_name = package.split("-")[1] 62 | if os.system("phpenmod %s" % module_name) != 0: 63 | raise InstallationException('Could not enable %s php module' % module_name) 64 | 65 | # Calling post-install hooks 66 | self.frontend.post_install() 67 | if self.interpretor is not None: 68 | self.interpretor.post_install() 69 | 70 | self.update_alternatives(self.get_php_version()) 71 | 72 | if self.configuration.get('composer', True): 73 | self.install_composer() 74 | 75 | def create_procfile(self): 76 | # If there's no Procfile, create it 77 | procfile_path = os.path.join(self.application.get('directory'), 'Procfile') 78 | procfile_contents = None 79 | if os.path.isfile(procfile_path): 80 | with open(procfile_path, 'r') as f: 81 | web_match = re.search(r"^web:", f.read(), flags=re.MULTILINE) 82 | if web_match is None: 83 | f.seek(0) 84 | procfile_contents = f.read() 85 | 86 | if not os.path.isfile(procfile_path) or procfile_contents: 87 | with open(procfile_path, 'w') as f: 88 | f.write('web: /bin/bash -lc "sudo -E %s' % self.frontend.get_startup_cmd()) 89 | if self.interpretor is not None: 90 | f.write(' && %s' % self.interpretor.get_startup_cmd(self.get_php_version())) 91 | f.write(' "\n') 92 | if procfile_contents: 93 | f.write(procfile_contents) 94 | 95 | def get_php_version(self): 96 | version = str(self.configuration.get('version', default_version)) 97 | if version not in php_versions: 98 | version = default_version 99 | return version 100 | 101 | def prefix_package_version(self, package): 102 | return "php{}-{}".format(self.get_php_version(), package) 103 | 104 | def update_alternatives(self, version): 105 | for app in ['php', 'phar', 'phar.phar']: 106 | os.system('/usr/bin/update-alternatives --set {0} /usr/bin/{0}{1}'.format(app, version)) 107 | 108 | def install_composer(self): 109 | if os.path.isfile(os.path.join(self.application.get('directory'), 'composer.json')): 110 | print('Install composer dependencies') 111 | composer_phar = '/usr/local/bin/composer_phar' 112 | if os.system('cd %s && sudo -u %s %s install' % (self.application.get('directory'), 113 | self.application.get('user'), composer_phar)) != 0: 114 | raise InstallationException('Unable to install composer dependencies') 115 | 116 | def configure(self): 117 | if self.interpretor is not None: 118 | print('Configuring interpretor...') 119 | self.interpretor.configure(self.frontend) 120 | 121 | print('Configuring frontend...') 122 | self.frontend.configure(self.interpretor) 123 | 124 | def setup_environment(self): 125 | self.create_procfile() 126 | if self.interpretor is not None: 127 | self.interpretor.setup_environment() 128 | 129 | self.frontend.setup_environment() 130 | 131 | def create_frontend(self): 132 | interpretor = self.configuration.get('interpretor', None) 133 | if interpretor: 134 | frontend = self.configuration.get('frontend', { 135 | 'name': 'apache' 136 | }) 137 | else: 138 | frontend = self.configuration.get('frontend', { 139 | 'name': 'apache-mod-php' 140 | }) 141 | frontend_options = frontend.get('options', {}) 142 | frontend_options['version'] = self.configuration.get('version', default_version) 143 | return self.get_frontend_by_name(frontend.get('name'))(frontend_options, self.application) 144 | 145 | def create_interpretor(self): 146 | interpretor = self.configuration.get('interpretor', None) 147 | if interpretor is None: 148 | return None 149 | elif 'name' not in interpretor: 150 | raise ConfigurationException('Interpretor name must be set') 151 | 152 | return self.get_interpretor_by_name(interpretor.get('name'))(interpretor.get('options', {}), self.application) 153 | 154 | @staticmethod 155 | def get_interpretor_by_name(name): 156 | if name not in interpretors: 157 | raise ConfigurationException('Interpretor %s is unknown' % name) 158 | 159 | return interpretors.get(name) 160 | 161 | @staticmethod 162 | def get_frontend_by_name(name): 163 | if name not in frontends: 164 | raise ConfigurationException('Frontend %s is unknown' % name) 165 | 166 | return frontends.get(name) 167 | 168 | 169 | def load_file(working_dir="/home/application/current"): 170 | files_name = ["tsuru.yml", "tsuru.yaml", "app.yaml", "app.yml"] 171 | for file_name in files_name: 172 | try: 173 | file_path = os.path.join(working_dir, file_name) 174 | if os.path.exists(file_path) and file_name[0:3] == 'app': 175 | print('[WARNING] The `%s` configuration file name is deprecated' % file_name) 176 | 177 | with open(file_path) as f: 178 | return f.read() 179 | except IOError: 180 | pass 181 | 182 | return "" 183 | 184 | 185 | def load_configuration(): 186 | result = yaml.load(load_file()) 187 | if result: 188 | return result.get('php', {}) 189 | 190 | return {} 191 | 192 | 193 | def print_help(): 194 | print('This have to be called with 1 argument, which is the action') 195 | print() 196 | print('Possible values are:') 197 | print('- install: Install dependencies and configure system') 198 | print('- environment: Setup the environment') 199 | 200 | if __name__ == '__main__': 201 | # Load PHP configuration from `tsuru.yml` 202 | config = load_configuration() 203 | 204 | # Create an application object from environ 205 | application = { 206 | 'directory': '/home/application/current', 207 | 'user': 'ubuntu', 208 | 'source_directory': '/var/lib/tsuru', 209 | 'env': parse_env(config) 210 | } 211 | 212 | # Get the application manager 213 | manager = Manager(config, application) 214 | 215 | # Run installation & configuration 216 | if len(sys.argv) <= 1: 217 | print_help() 218 | elif sys.argv[1] == 'install': 219 | manager.install() 220 | manager.configure() 221 | elif sys.argv[1] == 'environment': 222 | manager.setup_environment() 223 | else: 224 | print('Action "%s" not found\n' % sys.argv[1]) 225 | print_help() 226 | -------------------------------------------------------------------------------- /php/frontend.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | # Copyright 2015 tsuru authors. All rights reserved. 4 | # Use of this source code is governed by a BSD-style 5 | # license that can be found in the LICENSE file. 6 | 7 | import os 8 | import shutil 9 | from utils import replace 10 | from vars import php_versions, default_version 11 | 12 | class Frontend(object): 13 | def __init__(self, configuration, application): 14 | self.configuration = configuration 15 | self.application = application 16 | 17 | def pre_install(self): 18 | pass 19 | 20 | def post_install(self): 21 | pass 22 | 23 | def supports_unix_proxy(self): 24 | return True 25 | 26 | def setup_environment(self): 27 | pass 28 | 29 | class Apache(Frontend): 30 | def supports_unix_proxy(self): 31 | return False 32 | 33 | def post_install(self): 34 | os.system('service apache2 stop') 35 | os.system('update-rc.d apache2 remove') 36 | 37 | def configure(self, interpretor=None): 38 | # Set apache virtual host 39 | vhost_directory = '/etc/apache2/sites-enabled' 40 | confs_directory = '/etc/apache2/conf-available' 41 | list(map(os.unlink, [os.path.join(vhost_directory, f) for f in os.listdir(vhost_directory)])) 42 | vhost_path = os.path.join(vhost_directory, 'tsuru-vhost.conf') 43 | security_dst_file = os.path.join(confs_directory, 'security.conf') 44 | shutil.copyfile(self.get_vhost_filepath(), vhost_path) 45 | security_src_file = os.path.join(self.application.get('source_directory'), 'php', 'frontend', 46 | 'apache', 'security.conf') 47 | shutil.copyfile(security_src_file, security_dst_file) 48 | 49 | # Set interpretor address is there's any 50 | if interpretor is not None: 51 | address = interpretor.get_address() 52 | replace(vhost_path, 'FASTCGI_INTERPRETOR_ADDRESS', address) 53 | os.system('a2enmod proxy_fcgi') 54 | 55 | # Empty `ports.conf` file 56 | open('/etc/apache2/ports.conf', 'w').close() 57 | 58 | # Set Apache environment variables accessible when running though cmd 59 | with open('/etc/profile', 'a') as profile_file: 60 | profile_file.write( 61 | "\n" 62 | "export APACHE_RUN_USER=%s\n" 63 | "export APACHE_RUN_GROUP=%s\n" 64 | "export APACHE_PID_FILE=/var/run/apache2/apache2.pid\n" 65 | "export APACHE_RUN_DIR=/var/run/apache2\n" 66 | "export APACHE_LOCK_DIR=/var/lock/apache2\n" 67 | "export APACHE_LOG_DIR=/var/log/apache2\n" 68 | "sudo chmod 777 /dev/stdout /dev/stderr\n" 69 | % (self.application.get('user'), self.application.get('user')) 70 | ) 71 | 72 | # Create directories 73 | logs_directory = '/var/log/apache2' 74 | directories = [logs_directory, '/var/lock/apache2', '/var/run/apache2'] 75 | for directory in directories: 76 | if not os.path.exists(directory): 77 | os.makedirs(directory) 78 | 79 | list(map(os.unlink, [os.path.join(logs_directory, f) for f in os.listdir(logs_directory)])) 80 | for log_file in ['access.log', 'error.log']: 81 | log_file_path = os.path.join(logs_directory, log_file) 82 | open(log_file_path, 'a').close() 83 | 84 | # Configure modules if needed 85 | for module in self.configuration.get('modules', []): 86 | os.system('a2enmod %s' % module) 87 | 88 | # Fix user rights 89 | os.system('chown -R %s /etc/apache2 /var/run/apache2 /var/log/apache2 /var/lock/apache2' % self.application.get('user')) 90 | 91 | def get_vhost_filepath(self): 92 | if 'vhost_file' in self.configuration: 93 | return os.path.join(self.application.get('directory'), self.configuration.get('vhost_file')) 94 | return self.get_default_vhost_filepath() 95 | 96 | def get_default_vhost_filepath(self): 97 | return os.path.join(self.application.get('source_directory'), 'php', 'frontend', 'apache', 'vhost.conf') 98 | 99 | def get_startup_cmd(self): 100 | return '/usr/sbin/apache2 -d /etc/apache2 -k start' 101 | 102 | 103 | class ApacheModPHP(Apache): 104 | def get_default_vhost_filepath(self): 105 | return os.path.join(self.application.get('source_directory'), 'php', 'frontend', 'apache-mod-php', 'vhost.conf') 106 | 107 | def configure(self, interpretor=None): 108 | super(ApacheModPHP, self).configure(interpretor) 109 | php_version = str(self.configuration.get('version', default_version)) 110 | if php_version not in php_versions: 111 | php_version = default_version 112 | for version in php_versions: 113 | os.system('sudo /usr/sbin/a2dismod php{}'.format(version)) 114 | os.system('sudo /usr/sbin/a2enmod php{}'.format(php_version)) 115 | 116 | def get_startup_cmd(self): 117 | return '/usr/sbin/apache2 -d /etc/apache2 -k start -DNO_DETACH' 118 | 119 | 120 | class Nginx(Frontend): 121 | def post_install(self): 122 | os.system('service nginx stop') 123 | os.system('update-rc.d nginx remove') 124 | 125 | def configure(self, interpretor=None): 126 | # Copy nginx configuration 127 | nginx_config_file = os.path.join(self.application.get('source_directory'), 'php', 'frontend', 'nginx', 'nginx.conf') 128 | shutil.copyfile(nginx_config_file, '/etc/nginx/nginx.conf') 129 | 130 | # Copy vhost configuration 131 | shutil.copyfile(self.get_vhost_filepath(), '/etc/nginx/vhost.conf') 132 | if interpretor is not None: 133 | address = interpretor.get_address() 134 | replace('/etc/nginx/vhost.conf', 'FASTCGI_INTERPRETOR_ADDRESS', address) 135 | 136 | # Clean log files 137 | logs_directory = '/var/log/nginx' 138 | if not os.path.exists(logs_directory): 139 | os.makedirs(logs_directory) 140 | 141 | list(map(os.unlink, [os.path.join(logs_directory, f) for f in os.listdir(logs_directory)])) 142 | for log_file in ['access.log', 'error.log']: 143 | log_file_path = os.path.join(logs_directory, log_file) 144 | open(log_file_path, 'a').close() 145 | 146 | # Fix user rights 147 | open('/run/nginx.pid', 'a').close() 148 | os.system('chown -R %s /etc/nginx /var/log/nginx /var/lib/nginx /run/nginx.pid' % self.application.get('user')) 149 | 150 | def get_vhost_filepath(self): 151 | if 'vhost_file' in self.configuration: 152 | return os.path.join(self.application.get('directory'), self.configuration.get('vhost_file')) 153 | 154 | return os.path.join(self.application.get('source_directory'), 'php', 'frontend', 'nginx', 'vhost.conf') 155 | 156 | def get_startup_cmd(self): 157 | return '/usr/sbin/nginx' 158 | 159 | frontends = { 160 | 'apache-mod-php': ApacheModPHP, 161 | 'apache': Apache, 162 | 'nginx': Nginx 163 | } 164 | -------------------------------------------------------------------------------- /php/frontend/apache-mod-php/vhost.conf: -------------------------------------------------------------------------------- 1 | Listen 8888 2 | ServerName localhost 3 | 4 | 5 | ServerAdmin webmaster@tsuru 6 | 7 | DocumentRoot /home/application/current 8 | 9 | Options FollowSymLinks 10 | AllowOverride None 11 | Require all denied 12 | 13 | 14 | Options Indexes FollowSymLinks MultiViews 15 | AllowOverride None 16 | Order allow,deny 17 | Allow from all 18 | Require all granted 19 | 20 | 21 | LogLevel warn 22 | ErrorLog /dev/stderr 23 | CustomLog /dev/stdout combined 24 | 25 | -------------------------------------------------------------------------------- /php/frontend/apache/security.conf: -------------------------------------------------------------------------------- 1 | # 2 | # Disable access to the entire file system except for the directories that 3 | # are explicitly allowed later. 4 | # 5 | # This currently breaks the configurations that come with some web application 6 | # Debian packages. 7 | # 8 | # 9 | # AllowOverride None 10 | # Order Deny,Allow 11 | # Deny from all 12 | # 13 | 14 | 15 | # Changing the following options will not really affect the security of the 16 | # server, but might make attacks slightly more difficult in some cases. 17 | 18 | # 19 | # ServerTokens 20 | # This directive configures what you return as the Server HTTP response 21 | # Header. The default is 'Full' which sends information about the OS-Type 22 | # and compiled in modules. 23 | # Set to one of: Full | OS | Minimal | Minor | Major | Prod 24 | # where Full conveys the most information, and Prod the least. 25 | ServerTokens Prod 26 | 27 | # 28 | # Optionally add a line containing the server version and virtual host 29 | # name to server-generated pages (internal error documents, FTP directory 30 | # listings, mod_status and mod_info output etc., but not CGI generated 31 | # documents or custom error documents). 32 | # Set to "EMail" to also include a mailto: link to the ServerAdmin. 33 | # Set to one of: On | Off | EMail 34 | ServerSignature Off 35 | 36 | # 37 | # Allow TRACE method 38 | # 39 | # Set to "extended" to also reflect the request body (only for testing and 40 | # diagnostic purposes). 41 | # 42 | # Set to one of: On | Off | extended 43 | TraceEnable Off 44 | 45 | # 46 | # Forbid access to version control directories 47 | # 48 | # If you use version control systems in your document root, you should 49 | # probably deny access to their directories. For example, for subversion: 50 | # 51 | # 52 | # Require all denied 53 | # 54 | 55 | # 56 | # Setting this header will prevent MSIE from interpreting files as something 57 | # else than declared by the content type in the HTTP headers. 58 | # Requires mod_headers to be enabled. 59 | # 60 | #Header set X-Content-Type-Options: "nosniff" 61 | 62 | # 63 | # Setting this header will prevent other sites from embedding pages from this 64 | # site as frames. This defends against clickjacking attacks. 65 | # Requires mod_headers to be enabled. 66 | # 67 | #Header set X-Frame-Options: "sameorigin" 68 | 69 | 70 | # vim: syntax=apache ts=4 sw=4 sts=4 sr noet 71 | -------------------------------------------------------------------------------- /php/frontend/apache/vhost.conf: -------------------------------------------------------------------------------- 1 | Listen 8888 2 | ServerName localhost 3 | 4 | 5 | ServerAdmin webmaster@tsuru 6 | 7 | DocumentRoot /home/application/current 8 | 9 | Options FollowSymLinks 10 | AllowOverride None 11 | Require all denied 12 | 13 | 14 | Options Indexes FollowSymLinks MultiViews 15 | AllowOverride None 16 | Order allow,deny 17 | Allow from all 18 | Require all granted 19 | 20 | 21 | ProxyPassMatch ^/(.+\.php(/.*)?)$ fcgi://FASTCGI_INTERPRETOR_ADDRESS/home/application/current/$1 22 | 23 | LogLevel warn 24 | ErrorLog /dev/stderr 25 | CustomLog /dev/stdout combined 26 | 27 | -------------------------------------------------------------------------------- /php/frontend/nginx/nginx.conf: -------------------------------------------------------------------------------- 1 | worker_processes 4; 2 | daemon on; 3 | error_log stderr; 4 | user ubuntu; 5 | 6 | events { 7 | worker_connections 1024; 8 | } 9 | 10 | http { 11 | include mime.types; 12 | default_type application/octet-stream; 13 | access_log /dev/stdout; 14 | 15 | sendfile on; 16 | keepalive_timeout 65; 17 | 18 | include vhost.conf; 19 | } 20 | -------------------------------------------------------------------------------- /php/frontend/nginx/vhost.conf: -------------------------------------------------------------------------------- 1 | server { 2 | listen 8888 default_server; 3 | listen [::]:8888 default_server ipv6only=on; 4 | 5 | root /home/application/current; 6 | index index.php index.html index.htm; 7 | 8 | server_name localhost; 9 | 10 | location / { 11 | try_files $uri $uri/ =404; 12 | } 13 | 14 | location ~ \.php$ { 15 | try_files $uri =404; 16 | fastcgi_split_path_info ^(.+\.php)(/.+)$; 17 | fastcgi_pass FASTCGI_INTERPRETOR_ADDRESS; 18 | fastcgi_index index.php; 19 | fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; 20 | include fastcgi_params; 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /php/install: -------------------------------------------------------------------------------- 1 | #!/bin/bash -e 2 | 3 | # Copyright 2022 tsuru authors. All rights reserved. 4 | # Use of this source code is governed by a BSD-style 5 | # license that can be found in the LICENSE file. 6 | set -eu -o pipefail 7 | 8 | SOURCE_DIR=/var/lib/tsuru 9 | source ${SOURCE_DIR}/base/rc/config 10 | source ${SOURCE_DIR}/base/rc/os_dependencies 11 | 12 | PHP_VERSIONS="5.6 7.0 7.1 7.2 8.0 8.1 8.2 8.3" 13 | 14 | add_repository ppa:ondrej/php 15 | 16 | packages=("nginx-core" "python3" "python3-yaml" "git" "apache2" "python-is-python3") 17 | for version in $PHP_VERSIONS 18 | do 19 | packages+=("php${version}" "php${version}-fpm" "libapache2-mod-php${version}") 20 | done 21 | 22 | export DEBIAN_FRONTEND=noninteractive 23 | 24 | apt-get update 25 | apt-get install -y --force-yes "${packages[@]}" 26 | 27 | # Pinning composer on 2.2.x as composer 2.3+ dropped support for < PHP 7.2.5. 28 | # See more: https://github.com/composer/composer/blob/main/CHANGELOG.md 29 | COMPOSER_VERSION=2.2.12 30 | curl -fsSL "https://getcomposer.org/download/${COMPOSER_VERSION}/composer.phar" -o /usr/local/bin/composer_phar 31 | chmod +x /usr/local/bin/composer_phar 32 | -------------------------------------------------------------------------------- /php/interpretor.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | # Copyright 2015 tsuru authors. All rights reserved. 4 | # Use of this source code is governed by a BSD-style 5 | # license that can be found in the LICENSE file. 6 | 7 | import os 8 | import shutil 9 | import subprocess 10 | from utils import replace 11 | from vars import php_versions 12 | 13 | class Interpretor(object): 14 | def __init__(self, configuration, application): 15 | self.configuration = configuration 16 | self.application = application 17 | self.socket_address = None 18 | 19 | def configure(self, frontend): 20 | # If frontend supports unix sockets, use them by default 21 | self.socket_address = 'unix:/var/run/php/fpm.sock' 22 | if not frontend.supports_unix_proxy(): 23 | self.socket_address = '127.0.0.1:9000' 24 | 25 | # Clear pre-configured pools 26 | for version in php_versions: 27 | removed_fpm_files = [] 28 | for f in os.listdir('/etc/php/{}/fpm/pool.d'.format(version)): 29 | removed_fpm_files.append(os.path.join('/etc/php/{}/fpm/pool.d'.format(version), f)) 30 | list(map(os.unlink, removed_fpm_files)) 31 | templates_mapping = { 32 | 'pool.conf': '/etc/php/{}/fpm/pool.d/tsuru.conf', 33 | 'php-fpm.conf': '/etc/php/{}/fpm/php-fpm.conf' 34 | } 35 | 36 | for template, target in templates_mapping.items(): 37 | shutil.copyfile( 38 | os.path.join(self.application.get('source_directory'), 'php', 'interpretor', 'fpm', 39 | template.format(version)), 40 | target.format(version) 41 | ) 42 | 43 | # Replace pool listen address 44 | listen_address = self.socket_address 45 | if listen_address[0:5] == 'unix:': 46 | listen_address = listen_address[5:] 47 | 48 | replace(templates_mapping['pool.conf'].format(version), '_FPM_POOL_LISTEN_', listen_address) 49 | replace(templates_mapping['php-fpm.conf'].format(version), '_PHP_VERSION_', version) 50 | 51 | # Fix user rights 52 | run_directory = '/var/run/php' 53 | if not os.path.exists(run_directory): 54 | os.makedirs(run_directory) 55 | os.system('chown -R {} /etc/php/{}/fpm /var/run/php'.format(self.application.get('user'), version)) 56 | 57 | # Clean and touch some files 58 | for file_path in ['/var/log/php-fpm.log', '/etc/php/{}/fpm/environment.conf'.format(version)]: 59 | open(file_path, 'a').close() 60 | os.system('chown %s %s' % (self.application.get('user'), file_path)) 61 | 62 | if 'ini_file' in self.configuration: 63 | shutil.copyfile( 64 | os.path.join(self.application.get('directory'), self.configuration.get('ini_file')), 65 | '/etc/php/{}/fpm/php.ini'.format(version) 66 | ) 67 | 68 | def get_address(self): 69 | return self.socket_address 70 | 71 | def setup_environment(self): 72 | target = '/etc/php/{}/fpm/environment.conf' 73 | for version in php_versions: 74 | with open(target.format(version), 'w') as f: 75 | for (k, v) in list(self.application.get('env', {}).items()): 76 | if v: 77 | f.write('env[%s] = %s\n' % (k, v)) 78 | 79 | def get_startup_cmd(self, version): 80 | return '/usr/sbin/php-fpm{0} --fpm-config /etc/php/{0}/fpm/php-fpm.conf'.format(version) 81 | 82 | def get_packages_extensions(self): 83 | packages = [] 84 | if 'extensions' in self.configuration: 85 | for extension in self.configuration.get('extensions'): 86 | packages.append(extension.join(['', self.phpversion])) 87 | return packages 88 | 89 | def pre_install(self): 90 | pass 91 | 92 | class FPM(Interpretor): 93 | def __init__(self, configuration, application): 94 | self.phpversion = '' 95 | super(FPM, self).__init__(configuration, application) 96 | 97 | def post_install(self): 98 | # Remove autostart 99 | for version in php_versions: 100 | os.system('service php{}-fpm stop'.format(version)) 101 | 102 | interpretors = { 103 | 'fpm': FPM, 104 | 'fpm54': FPM, 105 | 'fpm55': FPM, 106 | } 107 | -------------------------------------------------------------------------------- /php/interpretor/fpm/php-fpm.conf: -------------------------------------------------------------------------------- 1 | ;;;;;;;;;;;;;;;;;;;; 2 | ; FPM Configuration ; 3 | ;;;;;;;;;;;;;;;;;;;;; 4 | 5 | 6 | 7 | ;;;;;;;;;;;;;;;;;; 8 | ; Global Options ; 9 | ;;;;;;;;;;;;;;;;;; 10 | 11 | [global] 12 | pid = /var/run/php/fpm.pid 13 | error_log = /dev/stdout 14 | daemonize = no 15 | 16 | ;;;;;;;;;;;;;;;;;;;; 17 | ; Pool Definitions ; 18 | ;;;;;;;;;;;;;;;;;;;; 19 | 20 | include=/etc/php/_PHP_VERSION_/fpm/pool.d/*.conf 21 | -------------------------------------------------------------------------------- /php/interpretor/fpm/pool.conf: -------------------------------------------------------------------------------- 1 | [tsuru] 2 | user = ubuntu 3 | group = ubuntu 4 | listen = _FPM_POOL_LISTEN_ 5 | listen.allowed_clients = 127.0.0.1 6 | pm = dynamic 7 | pm.max_children = 4 8 | pm.start_servers = 2 9 | pm.min_spare_servers = 2 10 | pm.max_spare_servers = 3 11 | ;pm.process_idle_timeout = 10s; 12 | ;pm.max_requests = 500 13 | chdir = / 14 | security.limit_extensions = .php .php4 .php5 .php7 15 | catch_workers_output = yes 16 | clear_env = no 17 | -------------------------------------------------------------------------------- /php/utils.py: -------------------------------------------------------------------------------- 1 | # Copyright 2015 tsuru authors. All rights reserved. 2 | # Use of this source code is governed by a BSD-style 3 | # license that can be found in the LICENSE file. 4 | 5 | import codecs 6 | 7 | from tempfile import mkstemp 8 | from shutil import move 9 | import os 10 | 11 | 12 | def replace(source_file_path, pattern, substring): 13 | fh, target_file_path = mkstemp() 14 | 15 | with codecs.open(target_file_path, 'w', 'utf-8') as target_file: 16 | with codecs.open(source_file_path, 'r', 'utf-8') as source_file: 17 | for line in source_file: 18 | target_file.write(line.replace(pattern, substring)) 19 | os.remove(source_file_path) 20 | move(target_file_path, source_file_path) 21 | 22 | 23 | def parse_env(configuration): 24 | return dict( 25 | list(os.environ.items()) + 26 | list(parse_envs_from_configuration(configuration).items()) 27 | ) 28 | 29 | 30 | def parse_envs_from_configuration(configuration): 31 | return configuration.get('envs', {}) 32 | -------------------------------------------------------------------------------- /php/vars.py: -------------------------------------------------------------------------------- 1 | version_alias = { 2 | 'php5': 'php5.6', 3 | 'php7': 'php7.1' 4 | } 5 | php_versions = ['5.6', '7.0', '7.1', '7.2', '8.0', '8.1', '8.2', '8.3'] 6 | default_version = '5.6' 7 | -------------------------------------------------------------------------------- /python/Dockerfile: -------------------------------------------------------------------------------- 1 | # Copyright 2015 tsuru authors. All rights reserved. 2 | # Use of this source code is governed by a BSD-style 3 | # license that can be found in the LICENSE file. 4 | 5 | FROM tsuru/base-platform:22.04 6 | COPY ./ /var/lib/tsuru/python/ 7 | RUN set -ex \ 8 | && sudo /var/lib/tsuru/python/install \ 9 | && sudo rm -rf /var/lib/tsuru/python/install /var/lib/apt/lists/* \ 10 | && sudo cp /var/lib/tsuru/python/deploy /var/lib/tsuru 11 | ENV PYENV_ROOT="/var/lib/pyenv" \ 12 | PATH="$PYENV_ROOT/bin:$PYENV_ROOT/shims:$PATH" 13 | -------------------------------------------------------------------------------- /python/README.md: -------------------------------------------------------------------------------- 1 | # Python platform 2 | 3 | The Python platform uses python `3.11.3` by default and get your dependencies 4 | with pip, either by `Pipfile.lock`, `requirements.txt` or `setup.py`. 5 | 6 | You can define which python version you want using `.python-version`, always 7 | use full versions. 8 | 9 | ex: 10 | ``` 11 | 3.11.3 12 | ``` 13 | 14 | Available python versions: 15 | - 2.7.14 16 | - 3.5.10 17 | - 3.6.15 18 | - 3.7.16 19 | - 3.8.16 20 | - 3.9.16 21 | - 3.10.11 22 | - 3.11.3 23 | - pypy2.7-7.3.2 24 | - pypy3.6-7.3.2 25 | 26 | when adding new releases, we will retain previous version on the series to 27 | allow time for users update their apps. e,g: when 3.6.3 is released, we will 28 | remove 3.6.1. 29 | 30 | ## Setting pip version 31 | 32 | By default, the latest pip version will be installed. If you want to use a 33 | specific version, set a `PYTHON_PIP_VERSION` environment variable. It accepts 34 | a specific version (`PYTHON_PIP_VERSION=7.1.2`) or a 35 | [requirement specifier](https://pip.pypa.io/en/stable/reference/pip_install/#requirement-specifiers) 36 | (`PYTHON_PIP_VERSION="<10"`). 37 | 38 | ## Code deployment 39 | 40 | If you just run a `tsuru app deploy` of your code, tsuru will try to download 41 | all of your depencies using `requirements.txt` or `setup script`. You can 42 | customize this behavior, see the next section for more details. 43 | 44 | ## Code deployment with dependencies 45 | 46 | There are two ways to list the applications dependencies: `requirements.txt` 47 | or ``setup.py``. The priority order is: requirements -> setup. The file should 48 | be in the root of deploy files. 49 | 50 | ### Using Pipfile.lock 51 | 52 | If you have a `Pipfile.lock` file, tsuru will use pipenv to install the 53 | dependencies of your application. 54 | 55 | ### Using requirements.txt 56 | 57 | You can define a file called `requirements.txt` that list all pip 58 | dependencies of your application, each line represents one dependency, here's 59 | an example: 60 | 61 | $ cat requirements.txt 62 | ``` 63 | Flask==0.10.1 64 | gunicorn==19.3.0 65 | ``` 66 | 67 | ### Using setup script 68 | 69 | You can also define the setup script to list your dependencies, here's an 70 | example: 71 | 72 | $ cat setup.py 73 | ```python 74 | from setuptools import setup, find_packages 75 | setup( 76 | name="app-name", 77 | packages=find_packages(), 78 | description="example", 79 | include_package_data=True, 80 | install_requires=[ 81 | "Flask==0.10.1", 82 | "gunicorn==19.3.0", 83 | ], 84 | ) 85 | ``` 86 | 87 | After invoking `tsuru app-deploy`, tsuru will receive your code and tell the 88 | platform to install all the dependencies using `pipenv install --system 89 | --deploy`, `pip install -r requirements.txt` or `pip instal -e ./`. 90 | -------------------------------------------------------------------------------- /python/deploy: -------------------------------------------------------------------------------- 1 | #!/bin/bash -el 2 | 3 | # Copyright 2015 tsuru authors. All rights reserved. 4 | # Use of this source code is governed by a BSD-style 5 | # license that can be found in the LICENSE file. 6 | 7 | SOURCE_DIR=/var/lib/tsuru 8 | source ${SOURCE_DIR}/base/deploy 9 | source ${SOURCE_DIR}/base/rc/config 10 | 11 | PYTHON_REPO=${PYTHON_REPO:-https://heroku-buildpack-python.s3.amazonaws.com/heroku-22/runtimes} 12 | GET_PIP_URL=${GET_PIP_URL:-https://bootstrap.pypa.io/get-pip.py} 13 | GET_PIP_VERSION_URL=${GET_PIP_VERSION_URL:-https://bootstrap.pypa.io/pip/@VERSION@/get-pip.py} 14 | 15 | LATEST_312="3.12.0" 16 | LATEST_311="3.11.3" 17 | LATEST_310="3.10.11" 18 | LATEST_39="3.9.16" 19 | LATEST_38="3.8.16" 20 | LATEST_37="3.7.16" 21 | LATEST_36="3.6.15" 22 | LATEST_35="3.5.10" 23 | LATEST_PYTHON_VERSIONS=(${LATEST_312} ${LATEST_311} ${LATEST_310} ${LATEST_39} ${LATEST_38} ${LATEST_37} ${LATEST_36} ${LATEST_35}) 24 | PYTHON_VERSION_DEFAULT="${PYTHON_VERSION_DEFAULT:-${LATEST_312}}" 25 | VERSION_ORIGIN="default" 26 | PYTHON_BASE_DIR="/home/application/python" 27 | INSTALLED_PYTHON_FILE="${PYTHON_BASE_DIR}/.installed-version" 28 | 29 | if [ -n "${PYTHON_VERSION}" ]; then 30 | VERSION_ORIGIN="PYTHON_VERSION environment variable" 31 | else 32 | PYTHON_VERSION="${PYTHON_VERSION_DEFAULT}" 33 | fi 34 | 35 | if [ -f "${CURRENT_DIR}/.python-version" ]; then 36 | tmp_version=$(cat "${CURRENT_DIR}/.python-version") 37 | if [ -n "${tmp_version}" ]; then 38 | PYTHON_VERSION=${tmp_version} 39 | VERSION_ORIGIN=".python-version file" 40 | fi 41 | fi 42 | 43 | INSTALL_PYTHON=1 44 | if [[ -f ${PYTHON_BASE_DIR}/bin/python ]] && [[ -f ${INSTALLED_PYTHON_FILE} ]]; then 45 | INSTALLED_VERSION=$(cat ${INSTALLED_PYTHON_FILE}) 46 | if [[ ${INSTALLED_VERSION} == ${PYTHON_VERSION} ]]; then 47 | echo "-- Using already installed python version: ${INSTALLED_VERSION} --" 48 | INSTALL_PYTHON=0 49 | fi 50 | fi 51 | 52 | function choose_closest_python() { 53 | IFS=$'\n' 54 | local VERSIONS=$(sort -rV <<<"${LATEST_PYTHON_VERSIONS[*]}") 55 | unset IFS 56 | local TRY_PYTHON_VERSION="$1" 57 | local CHOSEN_PYTHON_VERSION="" 58 | local LAST_PYTHON_VERSION="" 59 | while [[ "${LAST_PYTHON_VERSION}" != "${TRY_PYTHON_VERSION}" ]]; do 60 | if echo "${VERSIONS}" | grep "^${TRY_PYTHON_VERSION}" >/dev/null; then 61 | CHOSEN_PYTHON_VERSION=$(echo "${VERSIONS}" | grep "^${TRY_PYTHON_VERSION}" | head -1) 62 | break 63 | fi 64 | LAST_PYTHON_VERSION="${TRY_PYTHON_VERSION}" 65 | TRY_PYTHON_VERSION=$(echo ${TRY_PYTHON_VERSION} | sed -E 's/(.*)(\.|-)[^\.]*$/\1/g') 66 | done 67 | echo "${CHOSEN_PYTHON_VERSION}" 68 | } 69 | 70 | function install_python() { 71 | DOWNLOAD_VERSION=${PYTHON_VERSION} 72 | if [[ ${DOWNLOAD_VERSION} =~ ^[0-9]\..* ]]; then 73 | DOWNLOAD_VERSION="python-${DOWNLOAD_VERSION}" 74 | fi 75 | 76 | DOWNLOAD_URL="${PYTHON_REPO}/${DOWNLOAD_VERSION}.tar.gz" 77 | if ! curl -m 10 -o/dev/null -ILfs $DOWNLOAD_URL; then 78 | # The exact requested version returned an http error so it's probably 79 | # not available, let's try finding the closest one. 80 | NEW_PYTHON_VERSION=$(choose_closest_python $PYTHON_VERSION) 81 | 82 | if [[ "${NEW_PYTHON_VERSION}" == "" ]]; then 83 | echo "Python version '${PYTHON_VERSION}' (${VERSION_ORIGIN}) is not supported." 84 | PYTHON_VERSION="${PYTHON_VERSION_DEFAULT}" 85 | VERSION_ORIGIN="default" 86 | elif [[ "${NEW_PYTHON_VERSION}" != "${PYTHON_VERSION}" ]]; then 87 | echo "Exact python version '${PYTHON_VERSION}' (${VERSION_ORIGIN}) is not supported." 88 | echo "Closest version is '${NEW_PYTHON_VERSION}'." 89 | PYTHON_VERSION="${NEW_PYTHON_VERSION}" 90 | VERSION_ORIGIN="${VERSION_ORIGIN} (closest)" 91 | fi 92 | fi 93 | 94 | if [[ ${INSTALLED_VERSION} == ${PYTHON_VERSION} ]]; then 95 | echo "-- Using already installed python version: ${INSTALLED_VERSION} --" 96 | return 97 | fi 98 | 99 | DOWNLOAD_VERSION=${PYTHON_VERSION} 100 | if [[ ${DOWNLOAD_VERSION} =~ ^[0-9]\..* ]]; then 101 | DOWNLOAD_VERSION="python-${DOWNLOAD_VERSION}" 102 | fi 103 | DOWNLOAD_URL="${PYTHON_REPO}/${DOWNLOAD_VERSION}.tar.gz" 104 | 105 | # install python binaries 106 | rm -rf "${PYTHON_BASE_DIR}" 107 | mkdir -p "${PYTHON_BASE_DIR}" 108 | echo "-- Using python version: ${PYTHON_VERSION} (${VERSION_ORIGIN}) from $DOWNLOAD_URL --" 109 | if ! (curl -m 120 -sS --retry 3 -L "$DOWNLOAD_URL" | tar xz -C "${PYTHON_BASE_DIR}"); then 110 | echo "ERROR: python version $PYTHON_VERSION is not supported." 111 | exit 1 112 | fi 113 | 114 | sudo ldconfig 115 | hash -r 116 | 117 | major_minor="" 118 | if [[ ${PYTHON_VERSION} =~ [0-9]+\.[0-9]+ ]]; then 119 | major_minor=${BASH_REMATCH[0]} 120 | 121 | GET_PIP_VERSION_URL=${GET_PIP_VERSION_URL/@VERSION@/${major_minor}} 122 | if curl -m 10 -o/dev/null -ILfs $GET_PIP_VERSION_URL; then 123 | GET_PIP_URL=$GET_PIP_VERSION_URL 124 | fi 125 | fi 126 | 127 | # install pip 128 | if [[ "${PYTHON_PIP_VERSION}" ]]; then 129 | PIP_VERSION_SPEC="${PYTHON_PIP_VERSION}" 130 | if [[ "$PYTHON_PIP_VERSION" =~ ^[0-9] ]]; then 131 | if [[ ${PYTHON_PIP_VERSION/.*/} -lt 19 ]]; then 132 | PIP_EXTRA_OPTS="--process-dependency-links" 133 | fi 134 | PIP_VERSION_SPEC="==${PYTHON_PIP_VERSION}" 135 | fi 136 | echo "Using pip version ${PIP_VERSION_SPEC}" 137 | curl -m 120 -LsS ${GET_PIP_URL} | python - "pip${PIP_VERSION_SPEC}" 138 | else 139 | echo "Using default pip version" 140 | curl -m 120 -LsS ${GET_PIP_URL} | python 141 | fi 142 | 143 | echo ${PYTHON_VERSION} >${INSTALLED_PYTHON_FILE} 144 | } 145 | 146 | if [[ ${INSTALL_PYTHON} == 1 ]]; then 147 | install_python 148 | fi 149 | 150 | # install project deps with pipenv or pip 151 | pushd "$CURRENT_DIR" 152 | if [ -f "${CURRENT_DIR}/Pipfile.lock" ]; then 153 | echo "Pipfile.lock detected, using 'pipenv install --system --deploy' to install dependencies" 154 | PIPENV_VERSION_SPEC="" 155 | if [[ "${PYTHON_PIPENV_VERSION}" != "" ]]; then 156 | PIPENV_VERSION_SPEC="${PYTHON_PIPENV_VERSION}" 157 | if [[ "$PYTHON_PIPENV_VERSION" =~ ^[0-9] ]]; then 158 | PIPENV_VERSION_SPEC="==${PYTHON_PIPENV_VERSION}" 159 | fi 160 | echo "Using pipenv version ${PIPENV_VERSION_SPEC}" 161 | else 162 | echo "Using latest pipenv version" 163 | fi 164 | pip install pipenv${PIPENV_VERSION_SPEC} 165 | pipenv install --system --deploy 166 | elif [ -f "${CURRENT_DIR}/requirements.txt" ]; then 167 | echo "requirements.txt detected, using 'pip install -r ./requirements.txt' to install dependencies" 168 | pip install -r ./requirements.txt 169 | elif [ -f "${CURRENT_DIR}/setup.py" ]; then 170 | echo "setup.py detected, using 'pip install -e .' to install dependencies" 171 | pip install ${PIP_EXTRA_OPTS:-} -e . 172 | fi 173 | popd 174 | -------------------------------------------------------------------------------- /python/install: -------------------------------------------------------------------------------- 1 | #!/bin/bash -e 2 | 3 | # Copyright 2015 tsuru authors. All rights reserved. 4 | # Use of this source code is governed by a BSD-style 5 | # license that can be found in the LICENSE file. 6 | 7 | SOURCE_DIR=/var/lib/tsuru 8 | source ${SOURCE_DIR}/base/rc/config 9 | 10 | export DEBIAN_FRONTEND=noninteractive 11 | 12 | apt-get update 13 | 14 | apt-get install -y --no-install-recommends \ 15 | curl \ 16 | libssl3 \ 17 | zlib1g \ 18 | libbz2-1.0 \ 19 | libsqlite3-0 \ 20 | libncurses5 \ 21 | libncursesw5 \ 22 | libreadline8 \ 23 | libexpat1 \ 24 | make \ 25 | build-essential 26 | 27 | mkdir -p /app/.heroku 28 | ln -s /home/application/python /app/.heroku/python 29 | 30 | echo "export PATH=/home/application/python/bin:${PATH}" | tee -a ${HOME}/.profile /etc/profile >/dev/null 31 | echo "/home/application/python/lib" | tee -a /etc/ld.so.conf.d/python.conf 32 | -------------------------------------------------------------------------------- /ruby/Dockerfile: -------------------------------------------------------------------------------- 1 | # Copyright 2015 tsuru authors. All rights reserved. 2 | # Use of this source code is governed by a BSD-style 3 | # license that can be found in the LICENSE file. 4 | 5 | FROM tsuru/base-platform:22.04 6 | COPY . /var/lib/tsuru/ruby 7 | RUN set -ex \ 8 | && sudo /var/lib/tsuru/ruby/install \ 9 | && sudo rm -rf /var/lib/tsuru/ruby/install /var/lib/apt/lists/* \ 10 | && sudo cp /var/lib/tsuru/ruby/deploy /var/lib/tsuru 11 | ENV GEM_PATH=/home/application/ruby \ 12 | GEM_HOME=/home/application/ruby \ 13 | BUNDLE_APP_CONFIG=/home/application/ruby/.bundle/config 14 | -------------------------------------------------------------------------------- /ruby/README.md: -------------------------------------------------------------------------------- 1 | # Ruby platform 2 | 3 | The Ruby platform uses ruby 2.2.3 by default and get your dependencies from 4 | ``Gemfile``. 5 | 6 | You can define what ruby version you want to with two ways: 7 | 8 | * set ruby version in ``Gemfile``: 9 | $ cat Gemfile 10 | ... 11 | ruby 2.2 12 | ... 13 | 14 | * ``.ruby-version`` file: 15 | $ cat .ruby-version 16 | 2.2 17 | 18 | ## Configure custom ruby repository 19 | 20 | The platform downloads ruby from a remote uri and you can define an environment variable `RUBY_REPO` to customize where from it will be downloaded. The platform will download ruby from: `$RUBY_REPO/ruby-$RUBY_VERSION.tgz`, where `RUBY_VERSION` is the ruby version figured out by the last step. 21 | 22 | ## Configure custom Gem source 23 | 24 | You can configure a custom source to be used for your gems using the environment variable `GEM_SOURCE`, this will be passed to the `gem install --source` argument. 25 | -------------------------------------------------------------------------------- /ruby/deploy: -------------------------------------------------------------------------------- 1 | #!/bin/bash -e 2 | 3 | # Copyright 2015 tsuru authors. All rights reserved. 4 | # Use of this source code is governed by a BSD-style 5 | # license that can be found in the LICENSE file. 6 | 7 | SOURCE_DIR=/var/lib/tsuru 8 | source ${SOURCE_DIR}/base/rc/config 9 | 10 | if [ -d ${CURRENT_DIR}/vendor ]; then 11 | PLATFORM_EXTRA_RSYNC_ARGS=${PLATFORM_EXTRA_RSYNC_ARGS---exclude vendor/bundle} 12 | fi 13 | 14 | source ${SOURCE_DIR}/base/deploy 15 | 16 | if [ -f ${CURRENT_DIR}/Gemfile.lock ]; then 17 | RUBY_VERSION=$(awk '/^RUBY VERSION/{getline; gsub(/p[0-9]+/, "", $2); print $2}' ${CURRENT_DIR}/Gemfile.lock || echo "") 18 | fi 19 | 20 | if [ -f ${CURRENT_DIR}/.ruby-version -a "${RUBY_VERSION}" == "" ]; then 21 | RUBY_VERSION=$(cat ${CURRENT_DIR}/.ruby-version) 22 | if [[ "${RUBY_VERSION}" =~ ([0-9\.]+).* ]]; then 23 | RUBY_VERSION=${BASH_REMATCH[1]} 24 | fi 25 | fi 26 | 27 | echo "gem: --no-rdoc --no-ri" > ~/.gemrc 28 | 29 | RUBY_VERSION=${RUBY_VERSION:-3.1.6} 30 | 31 | echo "-- Using ruby version: $RUBY_VERSION --" 32 | 33 | RUBY_REPO=${RUBY_REPO:-https://heroku-buildpack-ruby.s3.amazonaws.com/heroku-22} 34 | 35 | RUBY_TARGET="$RUBY_REPO/ruby-$RUBY_VERSION.tgz" 36 | 37 | # Install Ruby 38 | INSTALL_RUBY=1 39 | if [ -f /home/application/ruby/bin/ruby ]; then 40 | RUBY_INSTALLED_VERSION=$(/home/application/ruby/bin/ruby -e 'puts RUBY_VERSION') 41 | if [ "${RUBY_INSTALLED_VERSION}" != "${RUBY_VERSION}" ]; then 42 | INSTALL_RUBY=1 43 | else 44 | INSTALL_RUBY=0 45 | fi 46 | fi 47 | 48 | function get_bundler_version() { 49 | ruby_version=$1 50 | if [ -f ${CURRENT_DIR}/Gemfile.lock ]; then 51 | bundler_version=$(cat ${CURRENT_DIR}/Gemfile.lock | grep -A1 "BUNDLED WITH" | grep -v "BUNDLED WITH" | tr -d " ") 52 | if [ "$bundler_version" != "" ]; then 53 | echo $bundler_version 54 | return 55 | fi 56 | fi 57 | if [ "$(printf "%s\n%s" "$ruby_version" "2.6.0" | sort -V | head -n 1)" = "2.6.0" ]; then 58 | echo "" 59 | return 60 | fi 61 | echo ">2" 62 | } 63 | 64 | if [ "$INSTALL_RUBY" == "1" ]; then 65 | mkdir -p "/home/application/ruby" 66 | echo "-- Fetching ruby from: $RUBY_TARGET --" 67 | if ! (curl -s --retry 3 -L "$RUBY_TARGET" | tar xz -C "/home/application/ruby"); then 68 | echo "ERROR: ruby version $RUBY_VERSION is not supported." 69 | if [ ! -z "$SUPPORTED_VERSIONS" ]; then 70 | echo "Supported versions are: $SUPPORTED_VERSIONS" 71 | fi 72 | exit 1 73 | fi 74 | fi 75 | 76 | BUNDLER_VERSION=$(get_bundler_version $RUBY_VERSION) 77 | if [ "$BUNDLER_VERSION" != "" ]; then 78 | if [ -z "$GEM_SOURCE" ]; then 79 | gem install bundler --force -v "$BUNDLER_VERSION" 80 | else 81 | echo "-- Using $GEM_SOURCE as remote gem source --" 82 | gem install --clear-sources --force --source=$GEM_SOURCE bundler -v "$BUNDLER_VERSION" 83 | fi 84 | fi 85 | 86 | if [ -f ${CURRENT_DIR}/Gemfile ]; then 87 | if [ ! -z "$GEM_SOURCE" ]; then 88 | sed -i "s,https\?://rubygems.org/\?,$GEM_SOURCE," ${CURRENT_DIR}/Gemfile 89 | if [ -f ${CURRENT_DIR}/Gemfile.lock ]; then 90 | sed -i "s,https\?://rubygems.org/\?,$GEM_SOURCE," ${CURRENT_DIR}/Gemfile.lock 91 | fi 92 | fi 93 | pushd $CURRENT_DIR && bundle install --deployment --without ${BUNDLE_WITHOUT-development:test} 94 | popd 95 | fi 96 | -------------------------------------------------------------------------------- /ruby/install: -------------------------------------------------------------------------------- 1 | #!/bin/bash -le 2 | 3 | # Copyright 2015 tsuru authors. All rights reserved. 4 | # Use of this source code is governed by a BSD-style 5 | # license that can be found in the LICENSE file. 6 | 7 | SOURCE_DIR=/var/lib/tsuru 8 | source ${SOURCE_DIR}/base/rc/config 9 | 10 | # Install Essential Packages 11 | apt-get update 12 | apt-get install -y --no-install-recommends \ 13 | nodejs \ 14 | libgmp-dev \ 15 | libgmp3-dev \ 16 | zlib1g-dev \ 17 | build-essential \ 18 | libssl-dev \ 19 | libreadline-dev \ 20 | libyaml-dev \ 21 | libsqlite3-dev \ 22 | sqlite3 \ 23 | libxml2-dev \ 24 | libxslt1-dev \ 25 | libcurl4-openssl-dev \ 26 | libffi-dev 27 | 28 | mkdir /home/application/ruby 29 | chown ${USER}:${USER} /home/application/ruby 30 | 31 | echo "export PATH=/home/application/ruby/bin:${PATH}" | tee -a ${HOME}/.profile /etc/profile >/dev/null 32 | -------------------------------------------------------------------------------- /scratch/Dockerfile: -------------------------------------------------------------------------------- 1 | # Copyright 2020 tsuru authors. All rights reserved. 2 | # Use of this source code is governed by a BSD-style 3 | # license that can be found in the LICENSE file. 4 | 5 | FROM tsuru/base-platform:22.04 6 | COPY . /var/lib/tsuru/scratch 7 | RUN set -ex \ 8 | && sudo rm -rf /var/lib/apt/lists/* \ 9 | && sudo cp /var/lib/tsuru/scratch/deploy /var/lib/tsuru 10 | -------------------------------------------------------------------------------- /scratch/README.md: -------------------------------------------------------------------------------- 1 | Scratch platform 2 | ================ 3 | 4 | Simple platform based on tsuru-base image useful for deploy binaries. 5 | -------------------------------------------------------------------------------- /scratch/deploy: -------------------------------------------------------------------------------- 1 | #!/bin/bash -el 2 | 3 | # Copyright 2020 tsuru authors. All rights reserved. 4 | # Use of this source code is governed by a BSD-style 5 | # license that can be found in the LICENSE file. 6 | 7 | SOURCE_DIR=/var/lib/tsuru 8 | source ${SOURCE_DIR}/base/rc/config 9 | source ${SOURCE_DIR}/base/deploy 10 | -------------------------------------------------------------------------------- /static/Dockerfile: -------------------------------------------------------------------------------- 1 | # Copyright 2015 tsuru authors. All rights reserved. 2 | # Use of this source code is governed by a BSD-style 3 | # license that can be found in the LICENSE file. 4 | 5 | FROM tsuru/base-platform:22.04 6 | COPY . /var/lib/tsuru/static 7 | RUN set -ex \ 8 | && sudo /var/lib/tsuru/static/install \ 9 | && sudo rm -rf /var/lib/tsuru/static/install /var/lib/apt/lists/* \ 10 | && sudo cp /var/lib/tsuru/static/deploy /var/lib/tsuru 11 | -------------------------------------------------------------------------------- /static/Procfile: -------------------------------------------------------------------------------- 1 | web: /usr/sbin/nginx -g "daemon off;" 2 | -------------------------------------------------------------------------------- /static/README.md: -------------------------------------------------------------------------------- 1 | # static platform 2 | 3 | The static platform provides a nginx setup that serves anything that is in the 4 | application directory. A simple application with just an index.html file can be 5 | easily deployed to tsuru. 6 | 7 | ## Using different nginx flavors 8 | 9 | If your setup requires an specific nginx package, like ``nginx-extras``, you can 10 | specify it using the ``NGINX_PKG`` environment variable. Supported packages are: 11 | ``nginx-core``, ``nginx``, ``nginx-full``, ``nginx-light``, ``nginx-extras``. 12 | The desired packaged will be installed at deploy time and doesn't effect the 13 | entire platform. 14 | 15 | ## Customizing nginx configuration 16 | 17 | It's possible to customize nginx configuration by simply placing a file named 18 | nginx.conf in the root of the project. The default configuration file is 19 | [available in this 20 | repository](https://github.com/tsuru/platforms/blob/master/static/etc/nginx.conf). 21 | A common practice is to copy it and then do some customizations, as it contains 22 | some mandatory directives for proper behavior on tsuru (like ``port_in_redirect 23 | off``). 24 | 25 | -------------------------------------------------------------------------------- /static/deploy: -------------------------------------------------------------------------------- 1 | #!/bin/bash -el 2 | 3 | # Copyright 2015 tsuru authors. All rights reserved. 4 | # Use of this source code is governed by a BSD-style 5 | # license that can be found in the LICENSE file. 6 | 7 | SOURCE_DIR=/var/lib/tsuru 8 | 9 | source ${SOURCE_DIR}/base/rc/config 10 | source ${SOURCE_DIR}/base/deploy 11 | 12 | set +e 13 | test -e ${CURRENT_DIR}/nginx.conf && sudo mv ${CURRENT_DIR}/nginx.conf /etc/nginx/nginx.conf 14 | set -e 15 | 16 | NGINX_PKG=${NGINX_PKG:-nginx} 17 | 18 | case "$NGINX_PKG" in 19 | "nginx-core"|"nginx"|"nginx-full"|"nginx-light"|"nginx-extras") 20 | dpkg -s $NGINX_PKG &> /dev/null || (sudo apt-get update && sudo apt-get install -qy $NGINX_PKG) 21 | ;; 22 | *) 23 | echo "ERROR: Invalid nginx package $NGINX_PKG." 24 | echo "Supported values are: nginx, nginx-core, nginx-full, nginx-light, nginx-extras." 25 | exit 1 26 | ;; 27 | esac 28 | 29 | ${SOURCE_DIR}/static/validate-nginx-conf /etc/nginx/nginx.conf 30 | -------------------------------------------------------------------------------- /static/etc/nginx.conf: -------------------------------------------------------------------------------- 1 | worker_processes 4; 2 | pid /var/lib/nginx/nginx.pid; 3 | include /etc/nginx/modules-enabled/*.conf; 4 | error_log stderr; 5 | 6 | events { 7 | worker_connections 1024; 8 | } 9 | 10 | http { 11 | include mime.types; 12 | default_type application/octet-stream; 13 | types_hash_max_size 2048; 14 | client_header_buffer_size 32k; 15 | large_client_header_buffers 32 32k; 16 | server_tokens off; 17 | 18 | sendfile on; 19 | 20 | keepalive_timeout 65; 21 | access_log /dev/stdout; 22 | 23 | server { 24 | listen 8888; 25 | server_name localhost; 26 | 27 | port_in_redirect off; 28 | 29 | location / { 30 | root /home/application/current; 31 | index index.html index.htm; 32 | } 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /static/install: -------------------------------------------------------------------------------- 1 | #!/bin/bash -e 2 | 3 | # Copyright 2015 tsuru authors. All rights reserved. 4 | # Use of this source code is governed by a BSD-style 5 | # license that can be found in the LICENSE file. 6 | 7 | SOURCE_DIR=/var/lib/tsuru 8 | source ${SOURCE_DIR}/base/rc/config 9 | 10 | apt-get update 11 | apt-get install -y --no-install-recommends software-properties-common 12 | apt-get update 13 | apt-get install -y --no-install-recommends nginx 14 | 15 | rm -rf /var/log/nginx /var/lib/nginx 16 | mkdir -p /var/log/nginx /var/lib/nginx 17 | chown -R ${USER}:${USER} /var/lib/nginx /var/log/nginx 18 | 19 | cp ${SOURCE_DIR}/static/Procfile ${SOURCE_DIR}/default/Procfile 20 | cp ${SOURCE_DIR}/static/etc/nginx.conf /etc/nginx/nginx.conf 21 | echo "sudo chmod 777 /dev/stdout" >> /etc/profile 22 | -------------------------------------------------------------------------------- /static/validate-nginx-conf: -------------------------------------------------------------------------------- 1 | #!/bin/bash -e 2 | 3 | nginx_config_file=$1 4 | 5 | echo "Validating nginx configuration..." 6 | 7 | [ -f /var/lib/nginx/nginx.pid ] && rm /var/lib/nginx/nginx.pid 8 | nginx -c ${nginx_config_file} -t 9 | 10 | grep -q "port_in_redirect\s\+off;" ${nginx_config_file} || echo "'port_in_redirect off' is mandatory on nginx.conf" 11 | -------------------------------------------------------------------------------- /tests/Dockerfile.template: -------------------------------------------------------------------------------- 1 | # Copyright 2016 tsuru authors. All rights reserved. 2 | # Use of this source code is governed by a BSD-style 3 | # license that can be found in the LICENSE file. 4 | 5 | FROM platform-{PLATFORM} 6 | WORKDIR /tests 7 | ADD . /tests 8 | ADD common/* /tests/common/ 9 | # These RUN true lines are an ugly hack due to 10 | # https://github.com/moby/moby/issues/37965 and 11 | # https://github.community/t/attempting-to-build-docker-image-with-copy-from-on-actions/16715 12 | RUN true 13 | ADD https://github.com/bats-core/bats-core/archive/master.tar.gz ./bats.tar.gz 14 | RUN true 15 | ADD https://github.com/bats-core/bats-support/archive/master.tar.gz ./bats-support.tar.gz 16 | RUN true 17 | ADD https://github.com/bats-core/bats-assert/archive/master.tar.gz ./bats-assert.tar.gz 18 | RUN sudo mkdir ./bin && \ 19 | sudo tar -zxf bats.tar.gz && \ 20 | sudo tar -zxf bats-support.tar.gz && \ 21 | sudo tar -zxf bats-assert.tar.gz && \ 22 | sudo ./bats-core-master/install.sh . 23 | RUN echo "echo 'ran base deploy'" | sudo tee /var/lib/tsuru/base/deploy 24 | RUN bin/bats common && bin/bats . 25 | -------------------------------------------------------------------------------- /tests/common/tests.bats: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bats 2 | 3 | # Copyright 2016 tsuru authors. All rights reserved. 4 | # Use of this source code is governed by a BSD-style 5 | # license that can be found in the LICENSE file. 6 | 7 | setup() { 8 | rm -rf /home/application/current && mkdir /home/application/current 9 | chown ubuntu /home/application/current 10 | export CURRENT_DIR=/home/application/current 11 | } 12 | 13 | load '../bats-support-master/load' 14 | load '../bats-assert-master/load' 15 | 16 | @test "has runnable deploy script" { 17 | [ -x "/var/lib/tsuru/deploy" ] 18 | } 19 | 20 | @test "deploy script uses the base scripts" { 21 | run /var/lib/tsuru/deploy 22 | assert_success 23 | [[ "$output" == *"ran base deploy"* ]] 24 | } 25 | -------------------------------------------------------------------------------- /tests/go/fixtures/multipleprocesses/Procfile: -------------------------------------------------------------------------------- 1 | api: api 2 | worker: worker -------------------------------------------------------------------------------- /tests/go/fixtures/multipleprocesses/cmd/api/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "net/http" 6 | "os" 7 | ) 8 | 9 | func main() { 10 | http.HandleFunc("/", hello) 11 | http.HandleFunc("/healthcheck", healthcheck) 12 | 13 | 14 | port := os.Getenv("PORT") 15 | if port == "" { 16 | port = "8888" 17 | } 18 | 19 | err := http.ListenAndServe(":" + port, nil) 20 | if err != nil { 21 | panic(err) 22 | } 23 | } 24 | 25 | func hello(res http.ResponseWriter, req *http.Request) { 26 | fmt.Fprintln(res, "hello, world!") 27 | } 28 | 29 | func healthcheck(res http.ResponseWriter, req *http.Request) { 30 | fmt.Fprintln(res, "WORKING") 31 | } 32 | -------------------------------------------------------------------------------- /tests/go/fixtures/multipleprocesses/cmd/worker/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | 4 | import ( 5 | "fmt" 6 | "time" 7 | ) 8 | 9 | func main() { 10 | for { 11 | fmt.Println("worker") 12 | time.Sleep(time.Minute) 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /tests/go/fixtures/multipleprocesses/go.mod: -------------------------------------------------------------------------------- 1 | module multipleprocesses 2 | 3 | go 1.22.2 4 | -------------------------------------------------------------------------------- /tests/go/fixtures/nonrootmain/cmd/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | func main() { 4 | println("ok") 5 | } 6 | -------------------------------------------------------------------------------- /tests/go/fixtures/nonrootmain/go.mod: -------------------------------------------------------------------------------- 1 | module github.com/tsuru/nonrootmain 2 | -------------------------------------------------------------------------------- /tests/go/fixtures/rootmain/go.mod: -------------------------------------------------------------------------------- 1 | module github.com/tsuru/go/rootmain 2 | -------------------------------------------------------------------------------- /tests/go/fixtures/rootmain/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | func main() { 4 | println("ok") 5 | } 6 | -------------------------------------------------------------------------------- /tests/go/fixtures/selfreferencing/api/api.go: -------------------------------------------------------------------------------- 1 | package api 2 | 3 | func X() { 4 | println("ok") 5 | } 6 | -------------------------------------------------------------------------------- /tests/go/fixtures/selfreferencing/go.mod: -------------------------------------------------------------------------------- 1 | module github.com/tsuru/foo 2 | -------------------------------------------------------------------------------- /tests/go/fixtures/selfreferencing/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "github.com/tsuru/foo/api" 5 | ) 6 | 7 | func main() { 8 | api.X() 9 | } 10 | -------------------------------------------------------------------------------- /tests/go/fixtures/selfreferencingnonroot/api/api.go: -------------------------------------------------------------------------------- 1 | package api 2 | 3 | func X() { 4 | println("ok") 5 | } 6 | -------------------------------------------------------------------------------- /tests/go/fixtures/selfreferencingnonroot/cmd/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "github.com/tsuru/foo/api" 5 | ) 6 | 7 | func main() { 8 | api.X() 9 | } 10 | -------------------------------------------------------------------------------- /tests/go/fixtures/selfreferencingnonroot/go.mod: -------------------------------------------------------------------------------- 1 | module github.com/tsuru/foo 2 | -------------------------------------------------------------------------------- /tests/go/fixtures/vendored/go.mod: -------------------------------------------------------------------------------- 1 | module github.com/tsuru/blah 2 | 3 | go 1.19 4 | 5 | require golang.org/x/net v0.0.0-20191105084925-a882066a44e0 6 | -------------------------------------------------------------------------------- /tests/go/fixtures/vendored/go.sum: -------------------------------------------------------------------------------- 1 | golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= 2 | golang.org/x/net v0.0.0-20191105084925-a882066a44e0 h1:QPlSTtPE2k6PZPasQUbzuK3p9JbS+vMXYVto8g/yrsg= 3 | golang.org/x/net v0.0.0-20191105084925-a882066a44e0/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= 4 | golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 5 | golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= 6 | -------------------------------------------------------------------------------- /tests/go/fixtures/vendored/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "golang.org/x/net/netutil" 5 | ) 6 | 7 | func main() { 8 | netutil.Bla() 9 | } 10 | -------------------------------------------------------------------------------- /tests/go/fixtures/vendored/vendor/golang.org/x/net/AUTHORS: -------------------------------------------------------------------------------- 1 | # This source code refers to The Go Authors for copyright purposes. 2 | # The master list of authors is in the main Go distribution, 3 | # visible at http://tip.golang.org/AUTHORS. 4 | -------------------------------------------------------------------------------- /tests/go/fixtures/vendored/vendor/golang.org/x/net/CONTRIBUTORS: -------------------------------------------------------------------------------- 1 | # This source code was written by the Go contributors. 2 | # The master list of contributors is in the main Go distribution, 3 | # visible at http://tip.golang.org/CONTRIBUTORS. 4 | -------------------------------------------------------------------------------- /tests/go/fixtures/vendored/vendor/golang.org/x/net/LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2009 The Go Authors. All rights reserved. 2 | 3 | Redistribution and use in source and binary forms, with or without 4 | modification, are permitted provided that the following conditions are 5 | met: 6 | 7 | * Redistributions of source code must retain the above copyright 8 | notice, this list of conditions and the following disclaimer. 9 | * Redistributions in binary form must reproduce the above 10 | copyright notice, this list of conditions and the following disclaimer 11 | in the documentation and/or other materials provided with the 12 | distribution. 13 | * Neither the name of Google Inc. nor the names of its 14 | contributors may be used to endorse or promote products derived from 15 | this software without specific prior written permission. 16 | 17 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 18 | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 19 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 20 | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 21 | OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 22 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 23 | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 24 | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 25 | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 27 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 | -------------------------------------------------------------------------------- /tests/go/fixtures/vendored/vendor/golang.org/x/net/PATENTS: -------------------------------------------------------------------------------- 1 | Additional IP Rights Grant (Patents) 2 | 3 | "This implementation" means the copyrightable works distributed by 4 | Google as part of the Go project. 5 | 6 | Google hereby grants to You a perpetual, worldwide, non-exclusive, 7 | no-charge, royalty-free, irrevocable (except as stated in this section) 8 | patent license to make, have made, use, offer to sell, sell, import, 9 | transfer and otherwise run, modify and propagate the contents of this 10 | implementation of Go, where such license applies only to those patent 11 | claims, both currently owned or controlled by Google and acquired in 12 | the future, licensable by Google that are necessarily infringed by this 13 | implementation of Go. This grant does not include claims that would be 14 | infringed only as a consequence of further modification of this 15 | implementation. If you or your agent or exclusive licensee institute or 16 | order or agree to the institution of patent litigation against any 17 | entity (including a cross-claim or counterclaim in a lawsuit) alleging 18 | that this implementation of Go or any code incorporated within this 19 | implementation of Go constitutes direct or contributory patent 20 | infringement, or inducement of patent infringement, then any patent 21 | rights granted to you under this License for this implementation of Go 22 | shall terminate as of the date such litigation is filed. 23 | -------------------------------------------------------------------------------- /tests/go/fixtures/vendored/vendor/golang.org/x/net/netutil/listen.go: -------------------------------------------------------------------------------- 1 | // Copyright 2013 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | // Package netutil provides network utility functions, complementing the more 6 | // common ones in the net package. 7 | package netutil // import "golang.org/x/net/netutil" 8 | 9 | func Bla() { 10 | println("compiled using vendor") 11 | } 12 | -------------------------------------------------------------------------------- /tests/go/fixtures/vendored/vendor/modules.txt: -------------------------------------------------------------------------------- 1 | # golang.org/x/net v0.0.0-20191105084925-a882066a44e0 2 | ## explicit; go 1.11 3 | golang.org/x/net/netutil 4 | -------------------------------------------------------------------------------- /tests/go/tests.bats: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bats 2 | 3 | # Copyright 2017 tsuru authors. All rights reserved. 4 | # Use of this source code is governed by a BSD-style 5 | # license that can be found in the LICENSE file. 6 | 7 | latest=$(curl -sS -f https://go.dev/dl/?mode=json | jq -r '.[0].version') 8 | 9 | setup() { 10 | rm -rf /home/application/current && mkdir /home/application/current 11 | rm -f /home/application/.default_procfile 12 | chown ubuntu /home/application/current 13 | export CURRENT_DIR=/home/application/current 14 | export PATH=/home/application/go/bin:${PATH} 15 | rm -rf /home/application/go 16 | } 17 | 18 | load 'bats-support-master/load' 19 | load 'bats-assert-master/load' 20 | 21 | @test "use latest Go version as default" { 22 | run /var/lib/tsuru/deploy 23 | assert_success 24 | [[ "$output" == *"Installing Go ${latest} (latest version)"* ]] 25 | [[ "$output" == *"Using Go version: go version ${latest} linux/amd64"* ]] 26 | 27 | run go version 28 | assert_success 29 | [[ "$output" == *"go version ${latest} linux/amd64"* ]] 30 | } 31 | 32 | @test "use Go version from GO_VERSION" { 33 | export GO_VERSION=1.10 34 | run /var/lib/tsuru/deploy 35 | assert_success 36 | [[ "$output" == *"Installing Go go1.10 (exact match from \$GO_VERSION)"* ]] 37 | [[ "$output" == *"Using Go version: go version go1.10 linux/amd64"* ]] 38 | 39 | run go version 40 | assert_success 41 | [[ "$output" == *"go1.10"* ]] 42 | unset GO_VERSION 43 | } 44 | 45 | @test "use Go version from GO_VERSION with .x as patch" { 46 | export GO_VERSION=1.10.x 47 | run /var/lib/tsuru/deploy 48 | assert_success 49 | [[ "$output" == *"Installing Go go1.10.8 (closest match from \$GO_VERSION=1.10.x)"* ]] 50 | [[ "$output" == *"Using Go version: go version go1.10.8 linux/amd64"* ]] 51 | 52 | run go version 53 | assert_success 54 | [[ "$output" == *"go1.10.8"* ]] 55 | unset GO_VERSION 56 | } 57 | 58 | @test "use latest Go version from GO_VERSION with .x as minor" { 59 | export GO_VERSION=1.x 60 | run /var/lib/tsuru/deploy 61 | assert_success 62 | [[ "$output" == *"Installing Go ${latest} (closest match from \$GO_VERSION=1.x)"* ]] 63 | [[ "$output" == *"Using Go version: go version ${latest} linux/amd64"* ]] 64 | 65 | run go version 66 | assert_success 67 | [[ "$output" == *"${latest}"* ]] 68 | unset GO_VERSION 69 | } 70 | 71 | 72 | @test "test project rootmain default procfile" { 73 | cp -a ./fixtures/rootmain/* ${CURRENT_DIR}/ 74 | touch /home/application/.default_procfile 75 | run /var/lib/tsuru/deploy 76 | assert_success 77 | 78 | [ -x ${CURRENT_DIR}/tsuru-app ] 79 | run ${CURRENT_DIR}/tsuru-app 80 | assert_success 81 | [[ "$output" == *"ok"* ]] 82 | } 83 | 84 | @test "test project rootmain custom procfile" { 85 | cp -a ./fixtures/rootmain/* ${CURRENT_DIR}/ 86 | run /var/lib/tsuru/deploy 87 | assert_success 88 | 89 | [ -x ${CURRENT_DIR}/rootmain ] 90 | run ${CURRENT_DIR}/rootmain 91 | assert_success 92 | [[ "$output" == *"ok"* ]] 93 | 94 | [ -x /home/application/bin/rootmain ] 95 | run /home/application/bin/rootmain 96 | assert_success 97 | [[ "$output" == *"ok"* ]] 98 | } 99 | 100 | @test "test project selfreferencing default procfile" { 101 | cp -a ./fixtures/selfreferencing/* ${CURRENT_DIR}/ 102 | # Making sure that Go module is not going to match the internal package name "github.com/tsuru/foo" 103 | echo "module foo" > ${CURRENT_DIR}/go.mod 104 | 105 | touch /home/application/.default_procfile 106 | run /var/lib/tsuru/deploy 107 | [ "$status" -eq 1 ] 108 | [[ "$output" == *"no required module provides package github.com/tsuru/foo/api"* ]] 109 | } 110 | 111 | @test "test project selfreferencing default procfile with GO_PKG_PATH" { 112 | export GO_PKG_PATH="github.com/tsuru/foo" 113 | cp -a ./fixtures/selfreferencing/* ${CURRENT_DIR}/ 114 | touch /home/application/.default_procfile 115 | run /var/lib/tsuru/deploy 116 | assert_success 117 | 118 | [ -x ${CURRENT_DIR}/tsuru-app ] 119 | run ${CURRENT_DIR}/tsuru-app 120 | assert_success 121 | [[ "$output" == *"ok"* ]] 122 | 123 | unset GO_PKG_PATH 124 | } 125 | 126 | @test "test project selfreferencing custom procfile with GO_PKG_PATH" { 127 | export GO_PKG_PATH="github.com/tsuru/foo" 128 | cp -a ./fixtures/selfreferencing/* ${CURRENT_DIR}/ 129 | run /var/lib/tsuru/deploy 130 | assert_success 131 | 132 | [ -x ${CURRENT_DIR}/foo ] 133 | run ${CURRENT_DIR}/foo 134 | assert_success 135 | [[ "$output" == *"ok"* ]] 136 | 137 | [ -x /home/application/bin/foo ] 138 | run /home/application/bin/foo 139 | assert_success 140 | [[ "$output" == *"ok"* ]] 141 | 142 | unset GO_PKG_PATH 143 | } 144 | 145 | @test "test project nonrootmain default procfile" { 146 | cp -a ./fixtures/nonrootmain/* ${CURRENT_DIR}/ 147 | touch /home/application/.default_procfile 148 | run /var/lib/tsuru/deploy 149 | [ "$status" -eq 1 ] 150 | [[ "$output" == *"no Go files"* ]] 151 | } 152 | 153 | @test "test project nonrootmain custom procfile" { 154 | cp -a ./fixtures/nonrootmain/* ${CURRENT_DIR}/ 155 | run /var/lib/tsuru/deploy 156 | assert_success 157 | 158 | [ -x /home/application/bin/cmd ] 159 | run /home/application/bin/cmd 160 | assert_success 161 | [[ "$output" == *"ok"* ]] 162 | } 163 | 164 | @test "test project selfreferencingnonroot custom procfile with GO_PKG_PATH" { 165 | export GO_PKG_PATH="github.com/tsuru/foo" 166 | cp -a ./fixtures/selfreferencingnonroot/* ${CURRENT_DIR}/ 167 | run /var/lib/tsuru/deploy 168 | assert_success 169 | 170 | [ -x /home/application/bin/cmd ] 171 | run /home/application/bin/cmd 172 | assert_success 173 | [[ "$output" == *"ok"* ]] 174 | unset GO_PKG_PATH 175 | } 176 | 177 | @test "test using vendor and go mod for go >= 1.13" { 178 | cp -a ./fixtures/vendored/* ${CURRENT_DIR}/ 179 | run /var/lib/tsuru/deploy 180 | assert_success 181 | 182 | [ -x /home/application/bin/blah ] 183 | run /home/application/bin/blah 184 | assert_success 185 | [[ "$output" == *"compiled using vendor"* ]] 186 | } 187 | 188 | 189 | @test "test project with multiple processes" { 190 | cp -a ./fixtures/multipleprocesses/* ${CURRENT_DIR}/ 191 | run /var/lib/tsuru/deploy 192 | assert_success 193 | 194 | [ -f /home/application/bin/api ] 195 | [ -s /home/application/bin/api ] 196 | 197 | [ -f /home/application/bin/worker ] 198 | [ -s /home/application/bin/worker ] 199 | } -------------------------------------------------------------------------------- /tests/java/tests.bats: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /tests/lua/tests.bats: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bats 2 | 3 | # Copyright 2016 tsuru authors. All rights reserved. 4 | # Use of this source code is governed by a BSD-style 5 | # license that can be found in the LICENSE file. 6 | 7 | load 'bats-support-master/load' 8 | load 'bats-assert-master/load' 9 | 10 | @test "installs lua" { 11 | run /usr/bin/lua -v 12 | assert_success 13 | [[ "$output" == *"Lua 5.4"* ]] 14 | } 15 | 16 | @test "install luarocks" { 17 | luarocks --help | grep LuaRocks | grep "the Lua package manager" 18 | } 19 | -------------------------------------------------------------------------------- /tests/nodejs/fixtures/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "hello-world", 3 | "description": "hello world test on tsuru", 4 | "version": "0.0.1", 5 | "private": true, 6 | "dependencies": { 7 | "express": "3.x" 8 | } 9 | } -------------------------------------------------------------------------------- /tests/nodejs/fixtures/yarn.lock: -------------------------------------------------------------------------------- 1 | # THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. 2 | # yarn lockfile v1 3 | 4 | 5 | accepts@~1.2.12, accepts@~1.2.13: 6 | version "1.2.13" 7 | resolved "https://registry.yarnpkg.com/accepts/-/accepts-1.2.13.tgz#e5f1f3928c6d95fd96558c36ec3d9d0de4a6ecea" 8 | integrity sha1-5fHzkoxtlf2WVYw27D2dDeSm7Oo= 9 | dependencies: 10 | mime-types "~2.1.6" 11 | negotiator "0.5.3" 12 | 13 | accepts@~1.3.0: 14 | version "1.3.7" 15 | resolved "https://registry.yarnpkg.com/accepts/-/accepts-1.3.7.tgz#531bc726517a3b2b41f850021c6cc15eaab507cd" 16 | integrity sha512-Il80Qs2WjYlJIBNzNkK6KYqlVMTbZLXgHx2oT0pU/fjRHyEp+PEfEPY0R3WCwAGVOtauxh1hOxNgIf5bv7dQpA== 17 | dependencies: 18 | mime-types "~2.1.24" 19 | negotiator "0.6.2" 20 | 21 | base64-url@1.2.1: 22 | version "1.2.1" 23 | resolved "https://registry.yarnpkg.com/base64-url/-/base64-url-1.2.1.tgz#199fd661702a0e7b7dcae6e0698bb089c52f6d78" 24 | integrity sha1-GZ/WYXAqDnt9yubgaYuwicUvbXg= 25 | 26 | basic-auth-connect@1.0.0: 27 | version "1.0.0" 28 | resolved "https://registry.yarnpkg.com/basic-auth-connect/-/basic-auth-connect-1.0.0.tgz#fdb0b43962ca7b40456a7c2bb48fe173da2d2122" 29 | integrity sha1-/bC0OWLKe0BFanwrtI/hc9otISI= 30 | 31 | basic-auth@~1.0.3: 32 | version "1.0.4" 33 | resolved "https://registry.yarnpkg.com/basic-auth/-/basic-auth-1.0.4.tgz#030935b01de7c9b94a824b29f3fccb750d3a5290" 34 | integrity sha1-Awk1sB3nyblKgksp8/zLdQ06UpA= 35 | 36 | batch@0.5.3: 37 | version "0.5.3" 38 | resolved "https://registry.yarnpkg.com/batch/-/batch-0.5.3.tgz#3f3414f380321743bfc1042f9a83ff1d5824d464" 39 | integrity sha1-PzQU84AyF0O/wQQvmoP/HVgk1GQ= 40 | 41 | body-parser@~1.13.3: 42 | version "1.13.3" 43 | resolved "https://registry.yarnpkg.com/body-parser/-/body-parser-1.13.3.tgz#c08cf330c3358e151016a05746f13f029c97fa97" 44 | integrity sha1-wIzzMMM1jhUQFqBXRvE/ApyX+pc= 45 | dependencies: 46 | bytes "2.1.0" 47 | content-type "~1.0.1" 48 | debug "~2.2.0" 49 | depd "~1.0.1" 50 | http-errors "~1.3.1" 51 | iconv-lite "0.4.11" 52 | on-finished "~2.3.0" 53 | qs "4.0.0" 54 | raw-body "~2.1.2" 55 | type-is "~1.6.6" 56 | 57 | bytes@2.1.0: 58 | version "2.1.0" 59 | resolved "https://registry.yarnpkg.com/bytes/-/bytes-2.1.0.tgz#ac93c410e2ffc9cc7cf4b464b38289067f5e47b4" 60 | integrity sha1-rJPEEOL/ycx89LRks4KJBn9eR7Q= 61 | 62 | bytes@2.4.0: 63 | version "2.4.0" 64 | resolved "https://registry.yarnpkg.com/bytes/-/bytes-2.4.0.tgz#7d97196f9d5baf7f6935e25985549edd2a6c2339" 65 | integrity sha1-fZcZb51br39pNeJZhVSe3SpsIzk= 66 | 67 | commander@2.6.0: 68 | version "2.6.0" 69 | resolved "https://registry.yarnpkg.com/commander/-/commander-2.6.0.tgz#9df7e52fb2a0cb0fb89058ee80c3104225f37e1d" 70 | integrity sha1-nfflL7Kgyw+4kFjugMMQQiXzfh0= 71 | 72 | compressible@~2.0.5: 73 | version "2.0.18" 74 | resolved "https://registry.yarnpkg.com/compressible/-/compressible-2.0.18.tgz#af53cca6b070d4c3c0750fbd77286a6d7cc46fba" 75 | integrity sha512-AF3r7P5dWxL8MxyITRMlORQNaOA2IkAFaTr4k7BUumjPtRpGDTZpl0Pb1XCO6JeDCBdp126Cgs9sMxqSjgYyRg== 76 | dependencies: 77 | mime-db ">= 1.43.0 < 2" 78 | 79 | compression@~1.5.2: 80 | version "1.5.2" 81 | resolved "https://registry.yarnpkg.com/compression/-/compression-1.5.2.tgz#b03b8d86e6f8ad29683cba8df91ddc6ffc77b395" 82 | integrity sha1-sDuNhub4rSloPLqN+R3cb/x3s5U= 83 | dependencies: 84 | accepts "~1.2.12" 85 | bytes "2.1.0" 86 | compressible "~2.0.5" 87 | debug "~2.2.0" 88 | on-headers "~1.0.0" 89 | vary "~1.0.1" 90 | 91 | connect-timeout@~1.6.2: 92 | version "1.6.2" 93 | resolved "https://registry.yarnpkg.com/connect-timeout/-/connect-timeout-1.6.2.tgz#de9a5ec61e33a12b6edaab7b5f062e98c599b88e" 94 | integrity sha1-3ppexh4zoStu2qt7XwYumMWZuI4= 95 | dependencies: 96 | debug "~2.2.0" 97 | http-errors "~1.3.1" 98 | ms "0.7.1" 99 | on-headers "~1.0.0" 100 | 101 | connect@2.30.2: 102 | version "2.30.2" 103 | resolved "https://registry.yarnpkg.com/connect/-/connect-2.30.2.tgz#8da9bcbe8a054d3d318d74dfec903b5c39a1b609" 104 | integrity sha1-jam8vooFTT0xjXTf7JA7XDmhtgk= 105 | dependencies: 106 | basic-auth-connect "1.0.0" 107 | body-parser "~1.13.3" 108 | bytes "2.1.0" 109 | compression "~1.5.2" 110 | connect-timeout "~1.6.2" 111 | content-type "~1.0.1" 112 | cookie "0.1.3" 113 | cookie-parser "~1.3.5" 114 | cookie-signature "1.0.6" 115 | csurf "~1.8.3" 116 | debug "~2.2.0" 117 | depd "~1.0.1" 118 | errorhandler "~1.4.2" 119 | express-session "~1.11.3" 120 | finalhandler "0.4.0" 121 | fresh "0.3.0" 122 | http-errors "~1.3.1" 123 | method-override "~2.3.5" 124 | morgan "~1.6.1" 125 | multiparty "3.3.2" 126 | on-headers "~1.0.0" 127 | parseurl "~1.3.0" 128 | pause "0.1.0" 129 | qs "4.0.0" 130 | response-time "~2.3.1" 131 | serve-favicon "~2.3.0" 132 | serve-index "~1.7.2" 133 | serve-static "~1.10.0" 134 | type-is "~1.6.6" 135 | utils-merge "1.0.0" 136 | vhost "~3.0.1" 137 | 138 | content-disposition@0.5.0: 139 | version "0.5.0" 140 | resolved "https://registry.yarnpkg.com/content-disposition/-/content-disposition-0.5.0.tgz#4284fe6ae0630874639e44e80a418c2934135e9e" 141 | integrity sha1-QoT+auBjCHRjnkToCkGMKTQTXp4= 142 | 143 | content-type@~1.0.1: 144 | version "1.0.4" 145 | resolved "https://registry.yarnpkg.com/content-type/-/content-type-1.0.4.tgz#e138cc75e040c727b1966fe5e5f8c9aee256fe3b" 146 | integrity sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA== 147 | 148 | cookie-parser@~1.3.5: 149 | version "1.3.5" 150 | resolved "https://registry.yarnpkg.com/cookie-parser/-/cookie-parser-1.3.5.tgz#9d755570fb5d17890771227a02314d9be7cf8356" 151 | integrity sha1-nXVVcPtdF4kHcSJ6AjFNm+fPg1Y= 152 | dependencies: 153 | cookie "0.1.3" 154 | cookie-signature "1.0.6" 155 | 156 | cookie-signature@1.0.6: 157 | version "1.0.6" 158 | resolved "https://registry.yarnpkg.com/cookie-signature/-/cookie-signature-1.0.6.tgz#e303a882b342cc3ee8ca513a79999734dab3ae2c" 159 | integrity sha1-4wOogrNCzD7oylE6eZmXNNqzriw= 160 | 161 | cookie@0.1.3: 162 | version "0.1.3" 163 | resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.1.3.tgz#e734a5c1417fce472d5aef82c381cabb64d1a435" 164 | integrity sha1-5zSlwUF/zkctWu+Cw4HKu2TRpDU= 165 | 166 | core-util-is@~1.0.0: 167 | version "1.0.2" 168 | resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7" 169 | integrity sha1-tf1UIgqivFq1eqtxQMlAdUUDwac= 170 | 171 | crc@3.3.0: 172 | version "3.3.0" 173 | resolved "https://registry.yarnpkg.com/crc/-/crc-3.3.0.tgz#fa622e1bc388bf257309082d6b65200ce67090ba" 174 | integrity sha1-+mIuG8OIvyVzCQgta2UgDOZwkLo= 175 | 176 | csrf@~3.0.0: 177 | version "3.0.6" 178 | resolved "https://registry.yarnpkg.com/csrf/-/csrf-3.0.6.tgz#b61120ddceeafc91e76ed5313bb5c0b2667b710a" 179 | integrity sha1-thEg3c7q/JHnbtUxO7XAsmZ7cQo= 180 | dependencies: 181 | rndm "1.2.0" 182 | tsscmp "1.0.5" 183 | uid-safe "2.1.4" 184 | 185 | csurf@~1.8.3: 186 | version "1.8.3" 187 | resolved "https://registry.yarnpkg.com/csurf/-/csurf-1.8.3.tgz#23f2a13bf1d8fce1d0c996588394442cba86a56a" 188 | integrity sha1-I/KhO/HY/OHQyZZYg5RELLqGpWo= 189 | dependencies: 190 | cookie "0.1.3" 191 | cookie-signature "1.0.6" 192 | csrf "~3.0.0" 193 | http-errors "~1.3.1" 194 | 195 | debug@2.6.9: 196 | version "2.6.9" 197 | resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f" 198 | integrity sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA== 199 | dependencies: 200 | ms "2.0.0" 201 | 202 | debug@~2.2.0: 203 | version "2.2.0" 204 | resolved "https://registry.yarnpkg.com/debug/-/debug-2.2.0.tgz#f87057e995b1a1f6ae6a4960664137bc56f039da" 205 | integrity sha1-+HBX6ZWxofauaklgZkE3vFbwOdo= 206 | dependencies: 207 | ms "0.7.1" 208 | 209 | depd@~1.0.1: 210 | version "1.0.1" 211 | resolved "https://registry.yarnpkg.com/depd/-/depd-1.0.1.tgz#80aec64c9d6d97e65cc2a9caa93c0aa6abf73aaa" 212 | integrity sha1-gK7GTJ1tl+ZcwqnKqTwKpqv3Oqo= 213 | 214 | depd@~1.1.0: 215 | version "1.1.2" 216 | resolved "https://registry.yarnpkg.com/depd/-/depd-1.1.2.tgz#9bcd52e14c097763e749b274c4346ed2e560b5a9" 217 | integrity sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak= 218 | 219 | destroy@1.0.3: 220 | version "1.0.3" 221 | resolved "https://registry.yarnpkg.com/destroy/-/destroy-1.0.3.tgz#b433b4724e71fd8551d9885174851c5fc377e2c9" 222 | integrity sha1-tDO0ck5x/YVR2YhRdIUcX8N34sk= 223 | 224 | destroy@~1.0.4: 225 | version "1.0.4" 226 | resolved "https://registry.yarnpkg.com/destroy/-/destroy-1.0.4.tgz#978857442c44749e4206613e37946205826abd80" 227 | integrity sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA= 228 | 229 | ee-first@1.1.1: 230 | version "1.1.1" 231 | resolved "https://registry.yarnpkg.com/ee-first/-/ee-first-1.1.1.tgz#590c61156b0ae2f4f0255732a158b266bc56b21d" 232 | integrity sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0= 233 | 234 | errorhandler@~1.4.2: 235 | version "1.4.3" 236 | resolved "https://registry.yarnpkg.com/errorhandler/-/errorhandler-1.4.3.tgz#b7b70ed8f359e9db88092f2d20c0f831420ad83f" 237 | integrity sha1-t7cO2PNZ6duICS8tIMD4MUIK2D8= 238 | dependencies: 239 | accepts "~1.3.0" 240 | escape-html "~1.0.3" 241 | 242 | escape-html@1.0.2: 243 | version "1.0.2" 244 | resolved "https://registry.yarnpkg.com/escape-html/-/escape-html-1.0.2.tgz#d77d32fa98e38c2f41ae85e9278e0e0e6ba1022c" 245 | integrity sha1-130y+pjjjC9BroXpJ44ODmuhAiw= 246 | 247 | escape-html@~1.0.3: 248 | version "1.0.3" 249 | resolved "https://registry.yarnpkg.com/escape-html/-/escape-html-1.0.3.tgz#0258eae4d3d0c0974de1c169188ef0051d1d1988" 250 | integrity sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg= 251 | 252 | etag@~1.7.0: 253 | version "1.7.0" 254 | resolved "https://registry.yarnpkg.com/etag/-/etag-1.7.0.tgz#03d30b5f67dd6e632d2945d30d6652731a34d5d8" 255 | integrity sha1-A9MLX2fdbmMtKUXTDWZScxo01dg= 256 | 257 | express-session@~1.11.3: 258 | version "1.11.3" 259 | resolved "https://registry.yarnpkg.com/express-session/-/express-session-1.11.3.tgz#5cc98f3f5ff84ed835f91cbf0aabd0c7107400af" 260 | integrity sha1-XMmPP1/4Ttg1+Ry/CqvQxxB0AK8= 261 | dependencies: 262 | cookie "0.1.3" 263 | cookie-signature "1.0.6" 264 | crc "3.3.0" 265 | debug "~2.2.0" 266 | depd "~1.0.1" 267 | on-headers "~1.0.0" 268 | parseurl "~1.3.0" 269 | uid-safe "~2.0.0" 270 | utils-merge "1.0.0" 271 | 272 | express@3.x: 273 | version "3.21.2" 274 | resolved "https://registry.yarnpkg.com/express/-/express-3.21.2.tgz#0c2903ee5c54e63d65a96170764703550665a3de" 275 | integrity sha1-DCkD7lxU5j1lqWFwdkcDVQZlo94= 276 | dependencies: 277 | basic-auth "~1.0.3" 278 | commander "2.6.0" 279 | connect "2.30.2" 280 | content-disposition "0.5.0" 281 | content-type "~1.0.1" 282 | cookie "0.1.3" 283 | cookie-signature "1.0.6" 284 | debug "~2.2.0" 285 | depd "~1.0.1" 286 | escape-html "1.0.2" 287 | etag "~1.7.0" 288 | fresh "0.3.0" 289 | merge-descriptors "1.0.0" 290 | methods "~1.1.1" 291 | mkdirp "0.5.1" 292 | parseurl "~1.3.0" 293 | proxy-addr "~1.0.8" 294 | range-parser "~1.0.2" 295 | send "0.13.0" 296 | utils-merge "1.0.0" 297 | vary "~1.0.1" 298 | 299 | finalhandler@0.4.0: 300 | version "0.4.0" 301 | resolved "https://registry.yarnpkg.com/finalhandler/-/finalhandler-0.4.0.tgz#965a52d9e8d05d2b857548541fb89b53a2497d9b" 302 | integrity sha1-llpS2ejQXSuFdUhUH7ibU6JJfZs= 303 | dependencies: 304 | debug "~2.2.0" 305 | escape-html "1.0.2" 306 | on-finished "~2.3.0" 307 | unpipe "~1.0.0" 308 | 309 | forwarded@~0.1.0: 310 | version "0.1.2" 311 | resolved "https://registry.yarnpkg.com/forwarded/-/forwarded-0.1.2.tgz#98c23dab1175657b8c0573e8ceccd91b0ff18c84" 312 | integrity sha1-mMI9qxF1ZXuMBXPozszZGw/xjIQ= 313 | 314 | fresh@0.3.0: 315 | version "0.3.0" 316 | resolved "https://registry.yarnpkg.com/fresh/-/fresh-0.3.0.tgz#651f838e22424e7566de161d8358caa199f83d4f" 317 | integrity sha1-ZR+DjiJCTnVm3hYdg1jKoZn4PU8= 318 | 319 | http-errors@~1.3.1: 320 | version "1.3.1" 321 | resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-1.3.1.tgz#197e22cdebd4198585e8694ef6786197b91ed942" 322 | integrity sha1-GX4izevUGYWF6GlO9nhhl7ke2UI= 323 | dependencies: 324 | inherits "~2.0.1" 325 | statuses "1" 326 | 327 | iconv-lite@0.4.11: 328 | version "0.4.11" 329 | resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.11.tgz#2ecb42fd294744922209a2e7c404dac8793d8ade" 330 | integrity sha1-LstC/SlHRJIiCaLnxATayHk9it4= 331 | 332 | iconv-lite@0.4.13: 333 | version "0.4.13" 334 | resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.13.tgz#1f88aba4ab0b1508e8312acc39345f36e992e2f2" 335 | integrity sha1-H4irpKsLFQjoMSrMOTRfNumS4vI= 336 | 337 | inherits@~2.0.1: 338 | version "2.0.4" 339 | resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" 340 | integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== 341 | 342 | ipaddr.js@1.0.5: 343 | version "1.0.5" 344 | resolved "https://registry.yarnpkg.com/ipaddr.js/-/ipaddr.js-1.0.5.tgz#5fa78cf301b825c78abc3042d812723049ea23c7" 345 | integrity sha1-X6eM8wG4JceKvDBC2BJyMEnqI8c= 346 | 347 | isarray@0.0.1: 348 | version "0.0.1" 349 | resolved "https://registry.yarnpkg.com/isarray/-/isarray-0.0.1.tgz#8a18acfca9a8f4177e09abfc6038939b05d1eedf" 350 | integrity sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8= 351 | 352 | media-typer@0.3.0: 353 | version "0.3.0" 354 | resolved "https://registry.yarnpkg.com/media-typer/-/media-typer-0.3.0.tgz#8710d7af0aa626f8fffa1ce00168545263255748" 355 | integrity sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g= 356 | 357 | merge-descriptors@1.0.0: 358 | version "1.0.0" 359 | resolved "https://registry.yarnpkg.com/merge-descriptors/-/merge-descriptors-1.0.0.tgz#2169cf7538e1b0cc87fb88e1502d8474bbf79864" 360 | integrity sha1-IWnPdTjhsMyH+4jhUC2EdLv3mGQ= 361 | 362 | method-override@~2.3.5: 363 | version "2.3.10" 364 | resolved "https://registry.yarnpkg.com/method-override/-/method-override-2.3.10.tgz#e3daf8d5dee10dd2dce7d4ae88d62bbee77476b4" 365 | integrity sha1-49r41d7hDdLc59SuiNYrvud0drQ= 366 | dependencies: 367 | debug "2.6.9" 368 | methods "~1.1.2" 369 | parseurl "~1.3.2" 370 | vary "~1.1.2" 371 | 372 | methods@~1.1.1, methods@~1.1.2: 373 | version "1.1.2" 374 | resolved "https://registry.yarnpkg.com/methods/-/methods-1.1.2.tgz#5529a4d67654134edcc5266656835b0f851afcee" 375 | integrity sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4= 376 | 377 | mime-db@1.45.0, "mime-db@>= 1.43.0 < 2": 378 | version "1.45.0" 379 | resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.45.0.tgz#cceeda21ccd7c3a745eba2decd55d4b73e7879ea" 380 | integrity sha512-CkqLUxUk15hofLoLyljJSrukZi8mAtgd+yE5uO4tqRZsdsAJKv0O+rFMhVDRJgozy+yG6md5KwuXhD4ocIoP+w== 381 | 382 | mime-types@~2.1.24, mime-types@~2.1.6, mime-types@~2.1.9: 383 | version "2.1.28" 384 | resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.28.tgz#1160c4757eab2c5363888e005273ecf79d2a0ecd" 385 | integrity sha512-0TO2yJ5YHYr7M2zzT7gDU1tbwHxEUWBCLt0lscSNpcdAfFyJOVEpRYNS7EXVcTLNj/25QO8gulHC5JtTzSE2UQ== 386 | dependencies: 387 | mime-db "1.45.0" 388 | 389 | mime@1.3.4: 390 | version "1.3.4" 391 | resolved "https://registry.yarnpkg.com/mime/-/mime-1.3.4.tgz#115f9e3b6b3daf2959983cb38f149a2d40eb5d53" 392 | integrity sha1-EV+eO2s9rylZmDyzjxSaLUDrXVM= 393 | 394 | minimist@0.0.8: 395 | version "0.0.8" 396 | resolved "https://registry.yarnpkg.com/minimist/-/minimist-0.0.8.tgz#857fcabfc3397d2625b8228262e86aa7a011b05d" 397 | integrity sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0= 398 | 399 | mkdirp@0.5.1: 400 | version "0.5.1" 401 | resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.1.tgz#30057438eac6cf7f8c4767f38648d6697d75c903" 402 | integrity sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM= 403 | dependencies: 404 | minimist "0.0.8" 405 | 406 | morgan@~1.6.1: 407 | version "1.6.1" 408 | resolved "https://registry.yarnpkg.com/morgan/-/morgan-1.6.1.tgz#5fd818398c6819cba28a7cd6664f292fe1c0bbf2" 409 | integrity sha1-X9gYOYxoGcuiinzWZk8pL+HAu/I= 410 | dependencies: 411 | basic-auth "~1.0.3" 412 | debug "~2.2.0" 413 | depd "~1.0.1" 414 | on-finished "~2.3.0" 415 | on-headers "~1.0.0" 416 | 417 | ms@0.7.1: 418 | version "0.7.1" 419 | resolved "https://registry.yarnpkg.com/ms/-/ms-0.7.1.tgz#9cd13c03adbff25b65effde7ce864ee952017098" 420 | integrity sha1-nNE8A62/8ltl7/3nzoZO6VIBcJg= 421 | 422 | ms@0.7.2: 423 | version "0.7.2" 424 | resolved "https://registry.yarnpkg.com/ms/-/ms-0.7.2.tgz#ae25cf2512b3885a1d95d7f037868d8431124765" 425 | integrity sha1-riXPJRKziFodldfwN4aNhDESR2U= 426 | 427 | ms@2.0.0: 428 | version "2.0.0" 429 | resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8" 430 | integrity sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g= 431 | 432 | multiparty@3.3.2: 433 | version "3.3.2" 434 | resolved "https://registry.yarnpkg.com/multiparty/-/multiparty-3.3.2.tgz#35de6804dc19643e5249f3d3e3bdc6c8ce301d3f" 435 | integrity sha1-Nd5oBNwZZD5SSfPT473GyM4wHT8= 436 | dependencies: 437 | readable-stream "~1.1.9" 438 | stream-counter "~0.2.0" 439 | 440 | negotiator@0.5.3: 441 | version "0.5.3" 442 | resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-0.5.3.tgz#269d5c476810ec92edbe7b6c2f28316384f9a7e8" 443 | integrity sha1-Jp1cR2gQ7JLtvntsLygxY4T5p+g= 444 | 445 | negotiator@0.6.2: 446 | version "0.6.2" 447 | resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-0.6.2.tgz#feacf7ccf525a77ae9634436a64883ffeca346fb" 448 | integrity sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw== 449 | 450 | on-finished@~2.3.0: 451 | version "2.3.0" 452 | resolved "https://registry.yarnpkg.com/on-finished/-/on-finished-2.3.0.tgz#20f1336481b083cd75337992a16971aa2d906947" 453 | integrity sha1-IPEzZIGwg811M3mSoWlxqi2QaUc= 454 | dependencies: 455 | ee-first "1.1.1" 456 | 457 | on-headers@~1.0.0, on-headers@~1.0.1: 458 | version "1.0.2" 459 | resolved "https://registry.yarnpkg.com/on-headers/-/on-headers-1.0.2.tgz#772b0ae6aaa525c399e489adfad90c403eb3c28f" 460 | integrity sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA== 461 | 462 | parseurl@~1.3.0, parseurl@~1.3.1, parseurl@~1.3.2: 463 | version "1.3.3" 464 | resolved "https://registry.yarnpkg.com/parseurl/-/parseurl-1.3.3.tgz#9da19e7bee8d12dff0513ed5b76957793bc2e8d4" 465 | integrity sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ== 466 | 467 | pause@0.1.0: 468 | version "0.1.0" 469 | resolved "https://registry.yarnpkg.com/pause/-/pause-0.1.0.tgz#ebc8a4a8619ff0b8a81ac1513c3434ff469fdb74" 470 | integrity sha1-68ikqGGf8LioGsFRPDQ0/0af23Q= 471 | 472 | proxy-addr@~1.0.8: 473 | version "1.0.10" 474 | resolved "https://registry.yarnpkg.com/proxy-addr/-/proxy-addr-1.0.10.tgz#0d40a82f801fc355567d2ecb65efe3f077f121c5" 475 | integrity sha1-DUCoL4Afw1VWfS7LZe/j8HfxIcU= 476 | dependencies: 477 | forwarded "~0.1.0" 478 | ipaddr.js "1.0.5" 479 | 480 | qs@4.0.0: 481 | version "4.0.0" 482 | resolved "https://registry.yarnpkg.com/qs/-/qs-4.0.0.tgz#c31d9b74ec27df75e543a86c78728ed8d4623607" 483 | integrity sha1-wx2bdOwn33XlQ6hseHKO2NRiNgc= 484 | 485 | random-bytes@~1.0.0: 486 | version "1.0.0" 487 | resolved "https://registry.yarnpkg.com/random-bytes/-/random-bytes-1.0.0.tgz#4f68a1dc0ae58bd3fb95848c30324db75d64360b" 488 | integrity sha1-T2ih3Arli9P7lYSMMDJNt11kNgs= 489 | 490 | range-parser@~1.0.2, range-parser@~1.0.3: 491 | version "1.0.3" 492 | resolved "https://registry.yarnpkg.com/range-parser/-/range-parser-1.0.3.tgz#6872823535c692e2c2a0103826afd82c2e0ff175" 493 | integrity sha1-aHKCNTXGkuLCoBA4Jq/YLC4P8XU= 494 | 495 | raw-body@~2.1.2: 496 | version "2.1.7" 497 | resolved "https://registry.yarnpkg.com/raw-body/-/raw-body-2.1.7.tgz#adfeace2e4fb3098058014d08c072dcc59758774" 498 | integrity sha1-rf6s4uT7MJgFgBTQjActzFl1h3Q= 499 | dependencies: 500 | bytes "2.4.0" 501 | iconv-lite "0.4.13" 502 | unpipe "1.0.0" 503 | 504 | readable-stream@~1.1.8, readable-stream@~1.1.9: 505 | version "1.1.14" 506 | resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-1.1.14.tgz#7cf4c54ef648e3813084c636dd2079e166c081d9" 507 | integrity sha1-fPTFTvZI44EwhMY23SB54WbAgdk= 508 | dependencies: 509 | core-util-is "~1.0.0" 510 | inherits "~2.0.1" 511 | isarray "0.0.1" 512 | string_decoder "~0.10.x" 513 | 514 | response-time@~2.3.1: 515 | version "2.3.2" 516 | resolved "https://registry.yarnpkg.com/response-time/-/response-time-2.3.2.tgz#ffa71bab952d62f7c1d49b7434355fbc68dffc5a" 517 | integrity sha1-/6cbq5UtYvfB1Jt0NDVfvGjf/Fo= 518 | dependencies: 519 | depd "~1.1.0" 520 | on-headers "~1.0.1" 521 | 522 | rndm@1.2.0: 523 | version "1.2.0" 524 | resolved "https://registry.yarnpkg.com/rndm/-/rndm-1.2.0.tgz#f33fe9cfb52bbfd520aa18323bc65db110a1b76c" 525 | integrity sha1-8z/pz7Urv9UgqhgyO8ZdsRCht2w= 526 | 527 | send@0.13.0: 528 | version "0.13.0" 529 | resolved "https://registry.yarnpkg.com/send/-/send-0.13.0.tgz#518f921aeb0560aec7dcab2990b14cf6f3cce5de" 530 | integrity sha1-UY+SGusFYK7H3KspkLFM9vPM5d4= 531 | dependencies: 532 | debug "~2.2.0" 533 | depd "~1.0.1" 534 | destroy "1.0.3" 535 | escape-html "1.0.2" 536 | etag "~1.7.0" 537 | fresh "0.3.0" 538 | http-errors "~1.3.1" 539 | mime "1.3.4" 540 | ms "0.7.1" 541 | on-finished "~2.3.0" 542 | range-parser "~1.0.2" 543 | statuses "~1.2.1" 544 | 545 | send@0.13.2: 546 | version "0.13.2" 547 | resolved "https://registry.yarnpkg.com/send/-/send-0.13.2.tgz#765e7607c8055452bba6f0b052595350986036de" 548 | integrity sha1-dl52B8gFVFK7pvCwUllTUJhgNt4= 549 | dependencies: 550 | debug "~2.2.0" 551 | depd "~1.1.0" 552 | destroy "~1.0.4" 553 | escape-html "~1.0.3" 554 | etag "~1.7.0" 555 | fresh "0.3.0" 556 | http-errors "~1.3.1" 557 | mime "1.3.4" 558 | ms "0.7.1" 559 | on-finished "~2.3.0" 560 | range-parser "~1.0.3" 561 | statuses "~1.2.1" 562 | 563 | serve-favicon@~2.3.0: 564 | version "2.3.2" 565 | resolved "https://registry.yarnpkg.com/serve-favicon/-/serve-favicon-2.3.2.tgz#dd419e268de012ab72b319d337f2105013f9381f" 566 | integrity sha1-3UGeJo3gEqtysxnTN/IQUBP5OB8= 567 | dependencies: 568 | etag "~1.7.0" 569 | fresh "0.3.0" 570 | ms "0.7.2" 571 | parseurl "~1.3.1" 572 | 573 | serve-index@~1.7.2: 574 | version "1.7.3" 575 | resolved "https://registry.yarnpkg.com/serve-index/-/serve-index-1.7.3.tgz#7a057fc6ee28dc63f64566e5fa57b111a86aecd2" 576 | integrity sha1-egV/xu4o3GP2RWbl+lexEahq7NI= 577 | dependencies: 578 | accepts "~1.2.13" 579 | batch "0.5.3" 580 | debug "~2.2.0" 581 | escape-html "~1.0.3" 582 | http-errors "~1.3.1" 583 | mime-types "~2.1.9" 584 | parseurl "~1.3.1" 585 | 586 | serve-static@~1.10.0: 587 | version "1.10.3" 588 | resolved "https://registry.yarnpkg.com/serve-static/-/serve-static-1.10.3.tgz#ce5a6ecd3101fed5ec09827dac22a9c29bfb0535" 589 | integrity sha1-zlpuzTEB/tXsCYJ9rCKpwpv7BTU= 590 | dependencies: 591 | escape-html "~1.0.3" 592 | parseurl "~1.3.1" 593 | send "0.13.2" 594 | 595 | statuses@1: 596 | version "1.5.0" 597 | resolved "https://registry.yarnpkg.com/statuses/-/statuses-1.5.0.tgz#161c7dac177659fd9811f43771fa99381478628c" 598 | integrity sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow= 599 | 600 | statuses@~1.2.1: 601 | version "1.2.1" 602 | resolved "https://registry.yarnpkg.com/statuses/-/statuses-1.2.1.tgz#dded45cc18256d51ed40aec142489d5c61026d28" 603 | integrity sha1-3e1FzBglbVHtQK7BQkidXGECbSg= 604 | 605 | stream-counter@~0.2.0: 606 | version "0.2.0" 607 | resolved "https://registry.yarnpkg.com/stream-counter/-/stream-counter-0.2.0.tgz#ded266556319c8b0e222812b9cf3b26fa7d947de" 608 | integrity sha1-3tJmVWMZyLDiIoErnPOyb6fZR94= 609 | dependencies: 610 | readable-stream "~1.1.8" 611 | 612 | string_decoder@~0.10.x: 613 | version "0.10.31" 614 | resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-0.10.31.tgz#62e203bc41766c6c28c9fc84301dab1c5310fa94" 615 | integrity sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ= 616 | 617 | tsscmp@1.0.5: 618 | version "1.0.5" 619 | resolved "https://registry.yarnpkg.com/tsscmp/-/tsscmp-1.0.5.tgz#7dc4a33af71581ab4337da91d85ca5427ebd9a97" 620 | integrity sha1-fcSjOvcVgatDN9qR2FylQn69mpc= 621 | 622 | type-is@~1.6.6: 623 | version "1.6.18" 624 | resolved "https://registry.yarnpkg.com/type-is/-/type-is-1.6.18.tgz#4e552cd05df09467dcbc4ef739de89f2cf37c131" 625 | integrity sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g== 626 | dependencies: 627 | media-typer "0.3.0" 628 | mime-types "~2.1.24" 629 | 630 | uid-safe@2.1.4: 631 | version "2.1.4" 632 | resolved "https://registry.yarnpkg.com/uid-safe/-/uid-safe-2.1.4.tgz#3ad6f38368c6d4c8c75ec17623fb79aa1d071d81" 633 | integrity sha1-Otbzg2jG1MjHXsF2I/t5qh0HHYE= 634 | dependencies: 635 | random-bytes "~1.0.0" 636 | 637 | uid-safe@~2.0.0: 638 | version "2.0.0" 639 | resolved "https://registry.yarnpkg.com/uid-safe/-/uid-safe-2.0.0.tgz#a7f3c6ca64a1f6a5d04ec0ef3e4c3d5367317137" 640 | integrity sha1-p/PGymSh9qXQTsDvPkw9U2cxcTc= 641 | dependencies: 642 | base64-url "1.2.1" 643 | 644 | unpipe@1.0.0, unpipe@~1.0.0: 645 | version "1.0.0" 646 | resolved "https://registry.yarnpkg.com/unpipe/-/unpipe-1.0.0.tgz#b2bf4ee8514aae6165b4817829d21b2ef49904ec" 647 | integrity sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw= 648 | 649 | utils-merge@1.0.0: 650 | version "1.0.0" 651 | resolved "https://registry.yarnpkg.com/utils-merge/-/utils-merge-1.0.0.tgz#0294fb922bb9375153541c4f7096231f287c8af8" 652 | integrity sha1-ApT7kiu5N1FTVBxPcJYjHyh8ivg= 653 | 654 | vary@~1.0.1: 655 | version "1.0.1" 656 | resolved "https://registry.yarnpkg.com/vary/-/vary-1.0.1.tgz#99e4981566a286118dfb2b817357df7993376d10" 657 | integrity sha1-meSYFWaihhGN+yuBc1ffeZM3bRA= 658 | 659 | vary@~1.1.2: 660 | version "1.1.2" 661 | resolved "https://registry.yarnpkg.com/vary/-/vary-1.1.2.tgz#2299f02c6ded30d4a5961b0b9f74524a18f634fc" 662 | integrity sha1-IpnwLG3tMNSllhsLn3RSShj2NPw= 663 | 664 | vhost@~3.0.1: 665 | version "3.0.2" 666 | resolved "https://registry.yarnpkg.com/vhost/-/vhost-3.0.2.tgz#2fb1decd4c466aa88b0f9341af33dc1aff2478d5" 667 | integrity sha1-L7HezUxGaqiLD5NBrzPcGv8keNU= 668 | -------------------------------------------------------------------------------- /tests/nodejs/tests.bats: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bats 2 | 3 | # Copyright 2017 tsuru authors. All rights reserved. 4 | # Use of this source code is governed by a BSD-style 5 | # license that can be found in the LICENSE file. 6 | 7 | setup() { 8 | rm -rf /home/application/current && mkdir -p /home/application/current 9 | chown ubuntu /home/application/current 10 | export CURRENT_DIR=/home/application/current 11 | export PATH=/home/ubuntu/.nvm_bin:$PATH 12 | rm -rf /home/ubuntu/.nvm_bin 13 | rm -rf /home/ubuntu/.nvm/versions 14 | rm -rf /home/ubuntu/.nvm/.cache 15 | rm -rf /home/ubuntu/.nvm/alias 16 | } 17 | 18 | load 'bats-support-master/load' 19 | load 'bats-assert-master/load' 20 | 21 | @test 'ensure NVM version' { 22 | source /home/ubuntu/.nvm/nvm.sh 23 | run nvm --version 24 | assert_success 25 | assert_output '0.39.7' 26 | } 27 | 28 | @test "defaults yarn 1.21.1 if yarn.lock present" { 29 | cat <>${CURRENT_DIR}/package.json 30 | { 31 | "name": "hello-world", 32 | "description": "hello world test on tsuru", 33 | "version": "0.0.1", 34 | "private": true, 35 | "dependencies": { 36 | "express": "3.x" 37 | } 38 | } 39 | EOF 40 | 41 | touch ${CURRENT_DIR}/yarn.lock 42 | run /var/lib/tsuru/deploy 43 | assert_success 44 | [[ "$output" == *"yarn.lock detected, using yarn to install node packages"* ]] 45 | 46 | run /home/ubuntu/.nvm_bin/yarn --version 47 | [[ "$output" == *"1.21.1"* ]] 48 | } 49 | 50 | @test "installs yarn from package.json" { 51 | cat <>${CURRENT_DIR}/package.json 52 | { 53 | "name": "hello-world", 54 | "description": "hello world test on tsuru", 55 | "version": "0.0.1", 56 | "private": true, 57 | "dependencies": { 58 | "express": "3.x" 59 | }, 60 | "engines": { 61 | "yarn": "0.24.6" 62 | } 63 | } 64 | EOF 65 | 66 | touch ${CURRENT_DIR}/yarn.lock 67 | run /var/lib/tsuru/deploy 68 | assert_success 69 | [[ "$output" == *"yarn.lock detected, using yarn to install node packages"* ]] 70 | 71 | run /home/ubuntu/.nvm_bin/yarn --version 72 | [[ "$output" == *"0.24.6"* ]] 73 | } 74 | 75 | @test "installs yarn from dependencies in package.json" { 76 | cat <>${CURRENT_DIR}/package.json 77 | { 78 | "name": "hello-world", 79 | "description": "hello world test on tsuru", 80 | "version": "0.0.1", 81 | "private": true, 82 | "dependencies": { 83 | "express": "3.x", 84 | "yarn": "0.24.6" 85 | } 86 | } 87 | EOF 88 | 89 | touch ${CURRENT_DIR}/yarn.lock 90 | run /var/lib/tsuru/deploy 91 | assert_success 92 | [[ "$output" == *"yarn.lock detected, using yarn to install node packages"* ]] 93 | 94 | run /home/ubuntu/.nvm_bin/yarn --version 95 | [[ "$output" == *"0.24.6"* ]] 96 | } 97 | 98 | @test "breaks with invalid dependencies" { 99 | cat <>${CURRENT_DIR}/package.json 100 | { 101 | "name": "hello-world", 102 | "description": "hello world test on tsuru", 103 | "version": "0.0.1", 104 | "private": true, 105 | "dependencies": { 106 | "express": "999" 107 | }, 108 | "engines": { 109 | "yarn": "0.24.6" 110 | } 111 | } 112 | EOF 113 | 114 | touch ${CURRENT_DIR}/yarn.lock 115 | run /var/lib/tsuru/deploy 116 | [ "$status" -ne 0 ] 117 | [[ "$output" == *"Couldn't find any versions for \"express\" that matches \"999\""* ]] 118 | } 119 | 120 | @test "works with yarn versions without support to --non-interactive flag" { 121 | cat <>${CURRENT_DIR}/package.json 122 | { 123 | "name": "hello-world", 124 | "description": "hello world test on tsuru", 125 | "version": "0.0.1", 126 | "private": true, 127 | "dependencies": { 128 | "express": "3.x" 129 | }, 130 | "engines": { 131 | "yarn": "0.17.0" 132 | } 133 | } 134 | EOF 135 | 136 | touch ${CURRENT_DIR}/yarn.lock 137 | run /var/lib/tsuru/deploy 138 | assert_success 139 | [[ "$output" == *"yarn.lock detected, using yarn to install node packages"* ]] 140 | 141 | run /home/ubuntu/.nvm_bin/yarn --version 142 | [[ "$output" == *"0.17.0"* ]] 143 | } 144 | 145 | @test "reads node version from .nvmrc" { 146 | echo "v8.9.0" >${CURRENT_DIR}/.nvmrc 147 | touch ${CURRENT_DIR}/yarn.lock 148 | run /var/lib/tsuru/deploy 149 | assert_success 150 | run node --version 151 | [[ "$output" == "v8.9.0" ]] 152 | } 153 | 154 | @test "reads node version from .node-version" { 155 | echo "v8.9.1" >${CURRENT_DIR}/.node-version 156 | touch ${CURRENT_DIR}/yarn.lock 157 | run /var/lib/tsuru/deploy 158 | assert_success 159 | run node --version 160 | [[ "$output" == "v8.9.1" ]] 161 | } 162 | 163 | @test "reads node version from package.json" { 164 | cat <>${CURRENT_DIR}/package.json 165 | { 166 | "name": "hello-world", 167 | "description": "hello world test on tsuru", 168 | "version": "0.0.1", 169 | "private": true, 170 | "engines": { 171 | "node": "v8.9.2" 172 | } 173 | } 174 | EOF 175 | touch ${CURRENT_DIR}/yarn.lock 176 | run /var/lib/tsuru/deploy 177 | assert_success 178 | run node --version 179 | [[ "$output" == "v8.9.2" ]] 180 | } 181 | 182 | @test "breaks with invalid node version" { 183 | echo "myinvalidversion" >${CURRENT_DIR}/.node-version 184 | touch ${CURRENT_DIR}/yarn.lock 185 | run /var/lib/tsuru/deploy 186 | [ "$status" -ne 0 ] 187 | [[ "$output" == *"Version 'myinvalidversion' not found"* ]] 188 | [[ "$output" == *"ERROR: \`nvm install \"myinvalidversion\"\` returned exit status"* ]] 189 | } 190 | 191 | @test "doesn't install dev dependencies with npm" { 192 | cat <>${CURRENT_DIR}/package.json 193 | { 194 | "name": "hello-world", 195 | "description": "hello world test on tsuru", 196 | "version": "0.0.1", 197 | "private": true, 198 | "dependencies": { 199 | "is-sorted": "1.x" 200 | }, 201 | "devDependencies": { 202 | "leftpad": "0.0.1" 203 | } 204 | } 205 | EOF 206 | 207 | run /var/lib/tsuru/deploy 208 | assert_success 209 | 210 | [ -d ${CURRENT_DIR}/node_modules/is-sorted ] 211 | [ ! -d ${CURRENT_DIR}/node_modules/leftpad ] 212 | } 213 | 214 | @test "doesn't install dev dependencies with yarn" { 215 | cat <>${CURRENT_DIR}/package.json 216 | { 217 | "name": "hello-world", 218 | "description": "hello world test on tsuru", 219 | "version": "0.0.1", 220 | "private": true, 221 | "dependencies": { 222 | "is-sorted": "1.x" 223 | }, 224 | "devDependencies": { 225 | "leftpad": "0.0.1" 226 | } 227 | } 228 | EOF 229 | 230 | touch ${CURRENT_DIR}/yarn.lock 231 | run /var/lib/tsuru/deploy 232 | assert_success 233 | 234 | [ -d ${CURRENT_DIR}/node_modules/is-sorted ] 235 | [ ! -d ${CURRENT_DIR}/node_modules/leftpad ] 236 | } 237 | 238 | @test "doesn't install dev dependencies with npm and NPM_CONFIG_PRODUCTION=true" { 239 | cat <>${CURRENT_DIR}/package.json 240 | { 241 | "name": "hello-world", 242 | "description": "hello world test on tsuru", 243 | "version": "0.0.1", 244 | "private": true, 245 | "dependencies": { 246 | "is-sorted": "1.x" 247 | }, 248 | "devDependencies": { 249 | "leftpad": "0.0.1" 250 | } 251 | } 252 | EOF 253 | 254 | NPM_CONFIG_PRODUCTION=true run /var/lib/tsuru/deploy 255 | assert_success 256 | 257 | [ -d ${CURRENT_DIR}/node_modules/is-sorted ] 258 | [ ! -d ${CURRENT_DIR}/node_modules/leftpad ] 259 | } 260 | 261 | @test "doesn't install dev dependencies with yarn and NPM_CONFIG_PRODUCTION=true" { 262 | cat <>${CURRENT_DIR}/package.json 263 | { 264 | "name": "hello-world", 265 | "description": "hello world test on tsuru", 266 | "version": "0.0.1", 267 | "private": true, 268 | "dependencies": { 269 | "is-sorted": "1.x" 270 | }, 271 | "devDependencies": { 272 | "leftpad": "0.0.1" 273 | } 274 | } 275 | EOF 276 | 277 | touch ${CURRENT_DIR}/yarn.lock 278 | NPM_CONFIG_PRODUCTION=true run /var/lib/tsuru/deploy 279 | assert_success 280 | 281 | [ -d ${CURRENT_DIR}/node_modules/is-sorted ] 282 | [ ! -d ${CURRENT_DIR}/node_modules/leftpad ] 283 | } 284 | 285 | @test "installs dev dependencies with npm and NPM_CONFIG_PRODUCTION=false" { 286 | cat <>${CURRENT_DIR}/package.json 287 | { 288 | "name": "hello-world", 289 | "description": "hello world test on tsuru", 290 | "version": "0.0.1", 291 | "private": true, 292 | "dependencies": { 293 | "is-sorted": "1.x" 294 | }, 295 | "devDependencies": { 296 | "leftpad": "0.0.1" 297 | } 298 | } 299 | EOF 300 | 301 | NPM_CONFIG_PRODUCTION=false run /var/lib/tsuru/deploy 302 | assert_success 303 | 304 | [ -d ${CURRENT_DIR}/node_modules/is-sorted ] 305 | [ -d ${CURRENT_DIR}/node_modules/leftpad ] 306 | } 307 | 308 | @test "installs dev dependencies with yarn and NPM_CONFIG_PRODUCTION=false" { 309 | cat <>${CURRENT_DIR}/package.json 310 | { 311 | "name": "hello-world", 312 | "description": "hello world test on tsuru", 313 | "version": "0.0.1", 314 | "private": true, 315 | "dependencies": { 316 | "is-sorted": "1.x" 317 | }, 318 | "devDependencies": { 319 | "leftpad": "0.0.1" 320 | } 321 | } 322 | EOF 323 | 324 | touch ${CURRENT_DIR}/yarn.lock 325 | NPM_CONFIG_PRODUCTION=false run /var/lib/tsuru/deploy 326 | assert_success 327 | 328 | [ -d ${CURRENT_DIR}/node_modules/is-sorted ] 329 | [ -d ${CURRENT_DIR}/node_modules/leftpad ] 330 | } 331 | 332 | @test "replaces the default npmjs.org urls with NPM_REGISTRY" { 333 | cp ./fixtures/package.json ${CURRENT_DIR}/package.json 334 | cp ./fixtures/package-lock.json ${CURRENT_DIR}/package-lock.json 335 | 336 | export NPM_REGISTRY=https://yarn.npmjs.org 337 | run /var/lib/tsuru/deploy 338 | assert_success 339 | [[ `cat ${CURRENT_DIR}/package-lock.json` == *"yarn.npmjs.org/express"* ]] 340 | } 341 | 342 | @test "replaces the default yarnpkg.com urls with NPM_REGISTRY" { 343 | cp ./fixtures/package.json ${CURRENT_DIR}/package.json 344 | cp ./fixtures/yarn.lock ${CURRENT_DIR}/yarn.lock 345 | 346 | export NPM_REGISTRY=https://yarn.npmjs.org 347 | run /var/lib/tsuru/deploy 348 | assert_success 349 | [[ `cat ${CURRENT_DIR}/yarn.lock` == *"yarn.npmjs.org/express"* ]] 350 | } 351 | -------------------------------------------------------------------------------- /tests/perl/tests.bats: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bats 2 | 3 | # Copyright 2017 tsuru authors. All rights reserved. 4 | # Use of this source code is governed by a BSD-style 5 | # license that can be found in the LICENSE file. 6 | 7 | setup() { 8 | rm -rf /home/application/current && mkdir /home/application/current 9 | chown ubuntu /home/application/current 10 | export CURRENT_DIR=/home/application/current 11 | } 12 | 13 | load 'bats-support-master/load' 14 | load 'bats-assert-master/load' 15 | 16 | @test "check if carton is installed" { 17 | pushd ${CURRENT_DIR} 18 | run carton -v 19 | popd 20 | 21 | assert_success 22 | [[ "$output" == *"carton v1"* ]] 23 | } 24 | 25 | @test "install from cpanfile" { 26 | echo "requires 'IO::Socket::IP';" > ${CURRENT_DIR}/cpanfile 27 | 28 | run /var/lib/tsuru/deploy 29 | 30 | pushd ${CURRENT_DIR} 31 | run carton install 32 | popd 33 | 34 | assert_success 35 | rm ${CURRENT_DIR}/cpanfile 36 | } 37 | -------------------------------------------------------------------------------- /tests/php/tests.bats: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bats 2 | 3 | # Copyright 2017 tsuru authors. All rights reserved. 4 | # Use of this source code is governed by a BSD-style 5 | # license that can be found in the LICENSE file. 6 | 7 | setup() { 8 | rm -rf /home/application/current && mkdir /home/application/current 9 | chown ubuntu /home/application/current 10 | } 11 | 12 | load 'bats-support-master/load' 13 | load 'bats-assert-master/load' 14 | 15 | @test "ensure composer version" { 16 | run composer_phar --version 17 | assert_success 18 | assert_output --partial "2.2.12" 19 | } 20 | 21 | @test "using default php(5.6) + apache-mod-php" { 22 | run /var/lib/tsuru/deploy 23 | run cat /home/application/current/Procfile 24 | assert_success 25 | [ "$output" == 'web: /bin/bash -lc "sudo -E /usr/sbin/apache2 -d /etc/apache2 -k start -DNO_DETACH "' ] 26 | } 27 | 28 | @test "sets correct ownership for generated Procfile allowing rewrites" { 29 | run /var/lib/tsuru/deploy 30 | assert_success 31 | run cat /home/application/current/Procfile 32 | assert_success 33 | [ "$output" == 'web: /bin/bash -lc "sudo -E /usr/sbin/apache2 -d /etc/apache2 -k start -DNO_DETACH "' ] 34 | run stat -c '%U' /home/application/current/Procfile 35 | assert_success 36 | [[ "$output" == "ubuntu" ]] 37 | } 38 | 39 | @test "using php7.1 + apache-mod-php" { 40 | cat >/home/application/current/tsuru.yaml </home/application/current/tsuru.yaml </home/application/current/tsuru.yaml </home/application/current/tsuru.yaml </home/application/current/tsuru.yaml </home/application/current/tsuru.yaml </home/application/current/composer.json </home/application/current/tsuru.yaml </home/application/current/tsuru.yaml <&2 $msg 59 | exit 1 60 | fi 61 | } 62 | 63 | function tsuru_login { 64 | yes $2 | tsuru login $1 65 | } 66 | 67 | tsuru_login admin@example.com admin123 68 | 69 | platforms=$(ls ../examples/ | cut -f1 -d'/' | cut -f1 -d'@') 70 | 71 | for platform in $platforms 72 | do 73 | add_platform $platform 74 | test_platform $platform 75 | done 76 | -------------------------------------------------------------------------------- /tests/python/Pipfile: -------------------------------------------------------------------------------- 1 | [[source]] 2 | 3 | url = "https://pypi.python.org/simple" 4 | verify_ssl = true 5 | name = "pypi" 6 | 7 | 8 | [dev-packages] 9 | 10 | 11 | 12 | [packages] 13 | 14 | msgpack-python = "==0.5.6" 15 | 16 | 17 | [requires] 18 | 19 | python_version = "3.10" 20 | -------------------------------------------------------------------------------- /tests/python/Pipfile.lock: -------------------------------------------------------------------------------- 1 | { 2 | "_meta": { 3 | "hash": { 4 | "sha256": "ef348bff6d6d7ad54340451eaec5bffa522ed1cebc6af6afd86346e7da69cb9e" 5 | }, 6 | "pipfile-spec": 6, 7 | "requires": { 8 | "python_version": "3.10" 9 | }, 10 | "sources": [ 11 | { 12 | "name": "pypi", 13 | "url": "https://pypi.python.org/simple", 14 | "verify_ssl": true 15 | } 16 | ] 17 | }, 18 | "default": { 19 | "msgpack-python": { 20 | "hashes": [ 21 | "sha256:378cc8a6d3545b532dfd149da715abae4fda2a3adb6d74e525d0d5e51f46909b" 22 | ], 23 | "index": "pypi", 24 | "version": "==0.5.6" 25 | } 26 | }, 27 | "develop": {} 28 | } 29 | -------------------------------------------------------------------------------- /tests/python/tests.bats: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bats 2 | 3 | # Copyright 2017 tsuru authors. All rights reserved. 4 | # Use of this source code is governed by a BSD-style 5 | # license that can be found in the LICENSE file. 6 | 7 | setup() { 8 | rm -rf /home/application/current && mkdir /home/application/current 9 | chown ubuntu /home/application/current 10 | export CURRENT_DIR=/home/application/current 11 | export PATH=/home/application/python/bin:${PATH} 12 | rm -rf /home/application/python/ 13 | } 14 | 15 | load 'bats-support-master/load' 16 | load 'bats-assert-master/load' 17 | 18 | @test "use python version 3.12.0 as default" { 19 | run /var/lib/tsuru/deploy 20 | [[ "$output" == *"Using python version: 3.12.0"* ]] 21 | assert_success 22 | 23 | run python --version 24 | assert_success 25 | [[ "$output" == *"3.12.0"* ]] 26 | 27 | run pip freeze 28 | assert_success 29 | } 30 | 31 | @test "use python version 3.11 as default" { 32 | export PYTHON_VERSION_DEFAULT=3.11.3 33 | run /var/lib/tsuru/deploy 34 | [[ "$output" == *"Using python version: 3.11.3"* ]] 35 | assert_success 36 | 37 | run python --version 38 | assert_success 39 | [[ "$output" == *"3.11.3"* ]] 40 | 41 | run pip freeze 42 | assert_success 43 | } 44 | 45 | @test "set 3.9 as default python version" { 46 | export PYTHON_VERSION_DEFAULT=3.9.15 47 | run /var/lib/tsuru/deploy 48 | [[ "$output" == *"Using python version: 3.9.15"* ]] 49 | assert_success 50 | 51 | run python --version 52 | assert_success 53 | [[ "$output" == *"3.9.15"* ]] 54 | 55 | run pip freeze 56 | assert_success 57 | } 58 | 59 | @test "parse python version from .python-version" { 60 | echo "3.9.15" > ${CURRENT_DIR}/.python-version 61 | run /var/lib/tsuru/deploy 62 | assert_success 63 | [[ "$output" == *"Using python version: 3.9.15"* ]] 64 | 65 | pushd ${CURRENT_DIR} 66 | run python --version 67 | popd 68 | 69 | assert_success 70 | [[ "$output" == *"3.9.15"* ]] 71 | } 72 | 73 | @test "testing python compiled using dynamic shared lib" { 74 | echo "3.11.0" > ${CURRENT_DIR}/.python-version 75 | run /var/lib/tsuru/deploy 76 | assert_success 77 | [[ "$output" == *"Using python version: 3.11.0"* ]] 78 | 79 | pushd ${CURRENT_DIR} 80 | run python --version 81 | popd 82 | 83 | assert_success 84 | [[ "$output" == *"3.11.0"* ]] 85 | } 86 | 87 | 88 | @test "parse python version from PYTHON_VERSION" { 89 | export PYTHON_VERSION=3.9.15 90 | run /var/lib/tsuru/deploy 91 | assert_success 92 | [[ "$output" == *"Using python version: 3.9.15"* ]] 93 | 94 | pushd ${CURRENT_DIR} 95 | run python --version 96 | popd 97 | 98 | assert_success 99 | [[ "$output" == *"3.9.15"* ]] 100 | unset PYTHON_VERSION 101 | } 102 | 103 | @test "use python version 3.12 as default with invalid .python-version" { 104 | export PYTHON_VERSION=3.11.3 105 | echo "xyz" > ${CURRENT_DIR}/.python-version 106 | run /var/lib/tsuru/deploy 107 | assert_success 108 | [[ "$output" == *"Python version 'xyz' (.python-version file) is not supported"* ]] 109 | [[ "$output" == *"Using python version: 3.12.0"* ]] 110 | 111 | pushd ${CURRENT_DIR} 112 | run python --version 113 | popd 114 | 115 | assert_success 116 | [[ "$output" == *"3.12.0"* ]] 117 | } 118 | 119 | @test "use python version 3.12 as default with invalid PYTHON_VERSION" { 120 | export PYTHON_VERSION=abc 121 | run /var/lib/tsuru/deploy 122 | assert_success 123 | [[ "$output" == *"Python version 'abc' (PYTHON_VERSION environment variable) is not supported"* ]] 124 | [[ "$output" == *"Using python version: 3.12.0"* ]] 125 | 126 | pushd ${CURRENT_DIR} 127 | run python --version 128 | popd 129 | 130 | assert_success 131 | [[ "$output" == *"3.12.0"* ]] 132 | unset PYTHON_VERSION 133 | } 134 | 135 | @test "install from setup.py" { 136 | cat <${CURRENT_DIR}/setup.py 137 | from setuptools import setup 138 | setup(name='tsr-deploy-test', install_requires=[ 'alf==0.7.0' ],) 139 | EOF 140 | run /var/lib/tsuru/deploy 141 | assert_success 142 | 143 | pushd ${CURRENT_DIR} 144 | run pip freeze 145 | popd 146 | 147 | assert_success 148 | [[ "$output" == *"alf"* ]] 149 | rm ${CURRENT_DIR}/setup.py 150 | } 151 | 152 | @test "install from requirements" { 153 | echo "msgpack-python==0.4.8" > ${CURRENT_DIR}/requirements.txt 154 | 155 | run /var/lib/tsuru/deploy 156 | assert_success 157 | 158 | pushd ${CURRENT_DIR} 159 | run pip freeze 160 | popd 161 | assert_success 162 | [[ "$output" == *"msgpack-python"* ]] 163 | rm ${CURRENT_DIR}/requirements.txt 164 | } 165 | 166 | @test "install from Pipfile.lock" { 167 | cp Pipfile Pipfile.lock ${CURRENT_DIR}/ 168 | 169 | run /var/lib/tsuru/deploy 170 | assert_success 171 | 172 | pushd ${CURRENT_DIR} 173 | run pip freeze 174 | popd 175 | 176 | assert_success 177 | [[ "$output" == *"msgpack-python"* ]] 178 | rm ${CURRENT_DIR}/Pipfile* 179 | } 180 | 181 | @test "install from Pipfile.lock with custom pipenv" { 182 | export PYTHON_PIPENV_VERSION=2023.12.1 183 | cp Pipfile Pipfile.lock ${CURRENT_DIR}/ 184 | 185 | run /var/lib/tsuru/deploy 186 | assert_success 187 | [[ "$output" == *"Using pipenv version ==2023.12.1"* ]] 188 | 189 | run pipenv --version 190 | assert_success 191 | [[ "$output" == *"version 2023.12.1"* ]] 192 | 193 | rm ${CURRENT_DIR}/Pipfile* 194 | unset PYTHON_PIPENV_VERSION 195 | } 196 | 197 | @test "change python version" { 198 | export PYTHON_VERSION=3.11.3 199 | run /var/lib/tsuru/deploy 200 | assert_success 201 | run python --version 202 | 203 | assert_success 204 | [[ "$output" == *"3.11.3"* ]] 205 | 206 | export PYTHON_VERSION=3.10.5 207 | run /var/lib/tsuru/deploy 208 | assert_success 209 | run python --version 210 | 211 | assert_success 212 | [[ "$output" == *"3.10.5"* ]] 213 | unset PYTHON_VERSION 214 | } 215 | 216 | @test "reuses already installed python version" { 217 | echo "3.9.15" > ${CURRENT_DIR}/.python-version 218 | run /var/lib/tsuru/deploy 219 | assert_success 220 | [[ "$output" == *"Using python version: 3.9.15"* ]] 221 | 222 | pushd ${CURRENT_DIR} 223 | run python --version 224 | popd 225 | 226 | assert_success 227 | [[ "$output" == *"3.9.15"* ]] 228 | 229 | run /var/lib/tsuru/deploy 230 | assert_success 231 | [[ "$output" == *"Using already installed python version: 3.9.15"* ]] 232 | 233 | pushd ${CURRENT_DIR} 234 | run python --version 235 | popd 236 | 237 | assert_success 238 | [[ "$output" == *"3.9.15"* ]] 239 | } 240 | 241 | @test "change python version to closest version" { 242 | export PYTHON_VERSION=3.9.x 243 | run /var/lib/tsuru/deploy 244 | assert_success 245 | [[ "$output" == *"Using python version: 3.9.16 (PYTHON_VERSION environment variable (closest))"* ]] 246 | run python --version 247 | 248 | assert_success 249 | [[ "$output" == *"3.9.16"* ]] 250 | 251 | export PYTHON_VERSION=3.10.x 252 | run /var/lib/tsuru/deploy 253 | assert_success 254 | [[ "$output" == *"Using python version: 3.10.11 (PYTHON_VERSION environment variable (closest))"* ]] 255 | run python --version 256 | 257 | assert_success 258 | [[ "$output" == *"3.10.11"* ]] 259 | 260 | export PYTHON_VERSION=3.10 261 | run /var/lib/tsuru/deploy 262 | assert_success 263 | [[ "$output" == *"Using already installed python version: 3.10.11"* ]] 264 | run python --version 265 | 266 | assert_success 267 | [[ "$output" == *"3.10.11"* ]] 268 | 269 | export PYTHON_VERSION=3 270 | run /var/lib/tsuru/deploy 271 | assert_success 272 | 273 | [[ "$output" == *"Using python version: 3.12.0 (PYTHON_VERSION environment variable (closest))"* ]] 274 | export PYTHON_VERSION=3.12.0 275 | run python --version 276 | 277 | assert_success 278 | [[ "$output" == *"3.12.0"* ]] 279 | 280 | unset PYTHON_VERSION 281 | } 282 | 283 | @test "use default pip version" { 284 | run /var/lib/tsuru/deploy 285 | assert_success 286 | [[ "$output" == *"Using default pip version"* ]] 287 | } 288 | 289 | @test "set specific pip version" { 290 | export PYTHON_PIP_VERSION=9.0.3 291 | run /var/lib/tsuru/deploy 292 | assert_success 293 | [[ "$output" == *"Using pip version ==9.0.3"* ]] 294 | unset PYTHON_PIP_VERSION 295 | } 296 | 297 | @test "set pip version as range" { 298 | export PYTHON_PIP_VERSION="<10" 299 | run /var/lib/tsuru/deploy 300 | assert_success 301 | [[ "$output" == *"Using pip version <10"* ]] 302 | unset PYTHON_PIP_VERSION 303 | } 304 | 305 | @test "can install uwsgi with python 3" { 306 | echo "3.10" > ${CURRENT_DIR}/.python-version 307 | echo "uwsgi==2.0.26" > ${CURRENT_DIR}/requirements.txt 308 | 309 | run /var/lib/tsuru/deploy 310 | assert_success 311 | 312 | pushd ${CURRENT_DIR} 313 | run pip freeze 314 | popd 315 | assert_success 316 | [[ "$output" == *"uWSGI"* ]] 317 | rm ${CURRENT_DIR}/requirements.txt 318 | rm ${CURRENT_DIR}/.python-version 319 | } 320 | -------------------------------------------------------------------------------- /tests/ruby/tests.bats: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bats 2 | 3 | # Copyright 2016 tsuru authors. All rights reserved. 4 | # Use of this source code is governed by a BSD-style 5 | # license that can be found in the LICENSE file. 6 | 7 | setup() { 8 | rm -rf /home/application/ruby 9 | rm -rf /home/application/current && mkdir /home/application/current 10 | chown ubuntu /home/application/current 11 | export CURRENT_DIR=/home/application/current 12 | export PATH=/home/application/ruby/bin:${PATH} 13 | } 14 | 15 | load 'bats-support-master/load' 16 | load 'bats-assert-master/load' 17 | 18 | @test "installs build-essential" { 19 | dpkg -s build-essential | grep "install ok installed" 20 | } 21 | 22 | @test "install ruby version 3.1.6 as default" { 23 | run /var/lib/tsuru/deploy 24 | run /home/application/ruby/bin/ruby --version 25 | assert_success 26 | [[ "$output" == *"3.1.6"* ]] 27 | } 28 | 29 | @test "install specific ruby version" { 30 | export RUBY_VERSION="3.2.1" 31 | run /var/lib/tsuru/deploy 32 | run /home/application/ruby/bin/ruby --version 33 | assert_success 34 | [[ "$output" == *"3.2.1"* ]] 35 | } 36 | 37 | @test "deploy fails on invalid ruby version" { 38 | export RUBY_VERSION="ABC" 39 | run /var/lib/tsuru/deploy 40 | [ "$status" -eq 1 ] 41 | [[ "$output" == *"ERROR: ruby version ABC is not supported."* ]] 42 | } 43 | 44 | @test "display supported versions if set" { 45 | export RUBY_VERSION="ABC" 46 | export SUPPORTED_VERSIONS="1.1.1, 1.2, 1.3" 47 | run /var/lib/tsuru/deploy 48 | [ "$status" -eq 1 ] 49 | [[ "$output" == *"Supported versions are: 1.1.1, 1.2, 1.3"* ]] 50 | } 51 | 52 | @test "parse ruby version from .ruby-version" { 53 | echo "ruby-3.2.2" > ${CURRENT_DIR}/.ruby-version 54 | run /var/lib/tsuru/deploy 55 | run /home/application/ruby/bin/ruby --version 56 | assert_success 57 | [[ "$output" == *"3.2.2"* ]] 58 | rm ${CURRENT_DIR}/.ruby-version 59 | } 60 | 61 | @test "detect ruby version 3.2.1 on Gemfile" { 62 | echo "source 'https://rubygems.org'" > ${CURRENT_DIR}/Gemfile 63 | echo "gem 'hello-world', '1.2.0'" >> ${CURRENT_DIR}/Gemfile 64 | echo "ruby '3.2.1'" >> ${CURRENT_DIR}/Gemfile 65 | cat <${CURRENT_DIR}/Gemfile.lock 66 | GEM 67 | remote: https://rubygems.org/ 68 | specs: 69 | hello-world (1.2.0) 70 | 71 | PLATFORMS 72 | ruby 73 | 74 | DEPENDENCIES 75 | hello-world (= 1.2.0) 76 | 77 | RUBY VERSION 78 | ruby 3.2.1p123 79 | 80 | BUNDLED WITH 81 | 2.1.0 82 | EOF 83 | 84 | run /var/lib/tsuru/deploy 85 | assert_success 86 | [[ "$output" == *"-- Using ruby version: 3.2.1 --"* ]] 87 | } 88 | 89 | @test "bundle install when provide Gemfile and reuse already installed gem" { 90 | echo "ruby-3.2.2" > ${CURRENT_DIR}/.ruby-version 91 | echo "source 'https://rubygems.org'" > ${CURRENT_DIR}/Gemfile 92 | echo "gem 'hello-world', '1.2.0'" >> ${CURRENT_DIR}/Gemfile 93 | cat <${CURRENT_DIR}/Gemfile.lock 94 | GEM 95 | remote: https://rubygems.org/ 96 | specs: 97 | hello-world (1.2.0) 98 | 99 | PLATFORMS 100 | ruby 101 | 102 | DEPENDENCIES 103 | hello-world (= 1.2.0) 104 | 105 | BUNDLED WITH 106 | 2.1.4 107 | EOF 108 | 109 | run /var/lib/tsuru/deploy 110 | assert_success 111 | [[ "$output" == *"Installing hello-world"* ]] 112 | run /var/lib/tsuru/deploy 113 | [[ "$output" == *"Using hello-world"* ]] 114 | run /home/application/ruby/bin/bundler --version 115 | assert_success 116 | assert_output --partial "Bundler version 2." 117 | } 118 | 119 | @test "using bundle inside Gemfile.lock and ignore bundle vendoring version for ruby >= 2.6" { 120 | echo "ruby-3.2.1" > ${CURRENT_DIR}/.ruby-version 121 | echo "source 'https://rubygems.org'" > ${CURRENT_DIR}/Gemfile 122 | echo "gem 'hello-world', '1.2.0'" >> ${CURRENT_DIR}/Gemfile 123 | cat <${CURRENT_DIR}/Gemfile.lock 124 | GEM 125 | remote: https://rubygems.org/ 126 | specs: 127 | hello-world (1.2.0) 128 | 129 | PLATFORMS 130 | ruby 131 | 132 | DEPENDENCIES 133 | hello-world (= 1.2.0) 134 | 135 | BUNDLED WITH 136 | 2.1.4 137 | EOF 138 | 139 | run /var/lib/tsuru/deploy 140 | assert_success 141 | [[ "$output" == *"Installing hello-world"* ]] 142 | run /var/lib/tsuru/deploy 143 | [[ "$output" == *"Using hello-world"* ]] 144 | run /home/application/ruby/bin/bundler --version 145 | assert_success 146 | assert_output --partial "Bundler version 2." 147 | } 148 | 149 | @test "bundle install when provide Gemfile with no bundled with section" { 150 | echo "ruby-3.1.2" > ${CURRENT_DIR}/.ruby-version 151 | echo "source 'https://rubygems.org'" > ${CURRENT_DIR}/Gemfile 152 | echo "gem 'hello-world', '1.2.0'" >> ${CURRENT_DIR}/Gemfile 153 | cat <${CURRENT_DIR}/Gemfile.lock 154 | GEM 155 | remote: https://rubygems.org/ 156 | specs: 157 | hello-world (1.2.0) 158 | 159 | PLATFORMS 160 | ruby 161 | 162 | DEPENDENCIES 163 | hello-world (= 1.2.0) 164 | EOF 165 | 166 | run /var/lib/tsuru/deploy 167 | assert_success 168 | [[ "$output" == *"Installing hello-world"* ]] 169 | run /var/lib/tsuru/deploy 170 | [[ "$output" == *"Using hello-world"* ]] 171 | run /home/application/ruby/bin/bundler --version 172 | assert_success 173 | assert_output --partial "Bundler version 2." 174 | } 175 | -------------------------------------------------------------------------------- /tests/run.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Copyright 2016 tsuru authors. All rights reserved. 4 | # Use of this source code is governed by a BSD-style 5 | # license that can be found in the LICENSE file. 6 | 7 | set -e 8 | 9 | DOCKER=${DOCKER:-docker} 10 | NO_REBUILD=$2 11 | 12 | parent_path=$( cd "$(dirname "${BASH_SOURCE}")" ; pwd -P ) 13 | 14 | cd "$parent_path" 15 | 16 | if [ ! -z $1 ]; then 17 | platforms=$1 18 | else 19 | platforms=$(ls -d */ | cut -f1 -d'/' | grep -v common) 20 | fi 21 | 22 | function run_test { 23 | local plat=$1 24 | echo "Testing $plat platform..." 25 | sed "s/{PLATFORM}/$plat/g" Dockerfile.template > ./$plat/Dockerfile 26 | cp -r common ./$plat/common 27 | if [ -z ${NO_REBUILD} ]; then 28 | ${DOCKER} build --platform linux/amd64 -t platform-$plat ../$plat && ${DOCKER} build --progress plain -t tests-$plat --no-cache ./$plat 29 | else 30 | ${DOCKER} build --platform linux/amd64 --progress plain -t tests-$plat --no-cache ./$plat 31 | fi 32 | rm ./$plat/Dockerfile && rm -rf ./$plat/common 33 | } 34 | 35 | for plat in $platforms; do 36 | if [ ! -d "./${plat}" ]; then 37 | continue 38 | fi 39 | run_test $plat 40 | done 41 | -------------------------------------------------------------------------------- /tests/static/tests.bats: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bats 2 | 3 | # Copyright 2016 tsuru authors. All rights reserved. 4 | # Use of this source code is governed by a BSD-style 5 | # license that can be found in the LICENSE file. 6 | 7 | load 'bats-support-master/load' 8 | load 'bats-assert-master/load' 9 | 10 | @test "installs nginx" { 11 | dpkg -s nginx | grep "install ok installed" 12 | } 13 | 14 | @test "sets up a default nginx conf" { 15 | [ -f /etc/nginx/nginx.conf ] 16 | [ -s /etc/nginx/nginx.conf ] 17 | } 18 | 19 | @test "sets up a default Procfile" { 20 | [ -f /var/lib/tsuru/default/Procfile ] 21 | [ -s /var/lib/tsuru/default/Procfile ] 22 | } 23 | 24 | @test "deploys an customized nginx package" { 25 | export NGINX_PKG="nginx-extras" 26 | run /var/lib/tsuru/deploy 27 | assert_success 28 | dpkg -s nginx-extras | grep "install ok installed" 29 | } 30 | 31 | @test "deploys fail on invalid nginx package" { 32 | export NGINX_PKG="invalid-nginx" 33 | run /var/lib/tsuru/deploy 34 | [ "$status" -eq 1 ] 35 | [[ "$output" == *"ERROR: Invalid nginx package invalid-nginx."* ]] 36 | } 37 | 38 | @test "deploy installs default nginx if env not set" { 39 | export NGINX_PKG="" 40 | run /var/lib/tsuru/deploy 41 | assert_success 42 | dpkg -s nginx | grep "install ok installed" 43 | } 44 | --------------------------------------------------------------------------------