mirror of
https://github.com/semaphoreui/semaphore.git
synced 2025-01-20 15:29:28 +01:00
fix: merge conflict
This commit is contained in:
commit
3157397665
2
.dockerignore
Normal file
2
.dockerignore
Normal file
@ -0,0 +1,2 @@
|
||||
web/node_modules/
|
||||
vendor/
|
@ -1,8 +1,7 @@
|
||||
dry-run: null
|
||||
hookfiles: ./.dredd/compiled_hooks
|
||||
language: go
|
||||
#server: context=dev task dc:up
|
||||
server-wait: 240
|
||||
server-wait: 5
|
||||
init: false
|
||||
custom: {}
|
||||
names: false
|
||||
@ -28,4 +27,4 @@ hooks-worker-handler-host: 0.0.0.0
|
||||
hooks-worker-handler-port: 61321
|
||||
config: ./.dredd/dredd.yml
|
||||
blueprint: api-docs.yml
|
||||
endpoint: 'http://semaphore_ci:3000'
|
||||
endpoint: 'http://server:3000'
|
@ -1,8 +1,7 @@
|
||||
dry-run: null
|
||||
hookfiles: ./.dredd/compiled_hooks
|
||||
language: go
|
||||
#server: context=dev task dc:up
|
||||
server-wait: 240
|
||||
server-wait: 5
|
||||
init: false
|
||||
custom: {}
|
||||
names: false
|
||||
|
@ -1,8 +1,8 @@
|
||||
dry-run: null
|
||||
hookfiles: ./.dredd/compiled_hooks
|
||||
language: go
|
||||
#server: context=dev task dc:up
|
||||
server-wait: 240
|
||||
server: ./semaphore server --config .dredd/config.json
|
||||
server-wait: 5
|
||||
init: false
|
||||
custom: {}
|
||||
names: false
|
||||
@ -28,4 +28,4 @@ hooks-worker-handler-host: 0.0.0.0
|
||||
hooks-worker-handler-port: 61321
|
||||
config: ./.dredd/dredd.yml
|
||||
blueprint: api-docs.yml
|
||||
endpoint: 'http://semaphore_ci:3000'
|
||||
endpoint: 'http://localhost:3000'
|
@ -1,8 +1,7 @@
|
||||
dry-run: null
|
||||
hookfiles: ./.dredd/compiled_hooks.exe
|
||||
language: go
|
||||
#server: context=dev task dc:up
|
||||
server-wait: 240
|
||||
server-wait: 5
|
||||
init: false
|
||||
custom: {}
|
||||
names: false
|
||||
|
140
.github/workflows/beta.yml
vendored
140
.github/workflows/beta.yml
vendored
@ -1,75 +1,127 @@
|
||||
name: Beta
|
||||
on:
|
||||
|
||||
'on':
|
||||
push:
|
||||
tags:
|
||||
- v*-beta
|
||||
|
||||
jobs:
|
||||
pre-release:
|
||||
runs-on: [ubuntu-latest]
|
||||
prerelease:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/setup-go@v3
|
||||
with: { go-version: '1.21' }
|
||||
- name: Checkout source
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- uses: actions/setup-node@v3
|
||||
with: { node-version: '16' }
|
||||
- name: Setup golang
|
||||
uses: actions/setup-go@v5
|
||||
with:
|
||||
go-version: '^1.21.0'
|
||||
|
||||
- run: go install github.com/go-task/task/v3/cmd/task@latest
|
||||
- name: Setup nodejs
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: '16'
|
||||
cache: 'npm'
|
||||
cache-dependency-path: web/package-lock.json
|
||||
|
||||
- run: sudo apt update && sudo apt-get install rpm
|
||||
- name: Install go-task
|
||||
run: |
|
||||
go install github.com/go-task/task/v3/cmd/task@latest
|
||||
|
||||
- uses: actions/checkout@v3
|
||||
- name: Install rpm
|
||||
run: |
|
||||
sudo apt update && sudo apt-get install rpm
|
||||
|
||||
- run: task deps
|
||||
- name: Install deps
|
||||
run: |
|
||||
task deps
|
||||
|
||||
- run: |
|
||||
echo ${{ secrets.GPG_KEY }} | tr " " "\n" | base64 -d | gpg --import --batch
|
||||
- name: Import gnupg
|
||||
run: |
|
||||
echo "${{ secrets.GPG_KEY }}" | tr " " "\n" | base64 -d | gpg --import --batch
|
||||
gpg --sign -u "58A7 CC3D 8A9C A2E5 BB5C 141D 4064 23EA F814 63CA" --pinentry-mode loopback --yes --batch --passphrase "${{ secrets.GPG_PASS }}" --output unlock.sig --detach-sign README.md
|
||||
rm -f unlock.sig
|
||||
|
||||
- run: git reset --hard
|
||||
|
||||
- run: GITHUB_TOKEN=${{ secrets.GH_TOKEN }} task release:prod
|
||||
- name: Reset repo
|
||||
run: |
|
||||
git reset --hard
|
||||
|
||||
- name: Run release
|
||||
run: |
|
||||
GITHUB_TOKEN=${{ secrets.GH_TOKEN }} task release:prod
|
||||
|
||||
deploy-beta:
|
||||
runs-on: [ubuntu-latest]
|
||||
runs-on: ubuntu-latest
|
||||
if: github.repository_owner == 'semaphoreui'
|
||||
|
||||
steps:
|
||||
- uses: actions/setup-go@v3
|
||||
with: { go-version: '1.21' }
|
||||
- name: Checkout source
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- run: go install github.com/go-task/task/v3/cmd/task@latest
|
||||
- name: Setup qemu
|
||||
id: qemu
|
||||
uses: docker/setup-qemu-action@v3
|
||||
|
||||
- uses: actions/checkout@v3
|
||||
- name: Setup buildx
|
||||
id: buildx
|
||||
uses: docker/setup-buildx-action@v3
|
||||
|
||||
- run: context=prod task docker:test
|
||||
|
||||
- uses: docker/setup-qemu-action@v2
|
||||
|
||||
- uses: docker/setup-buildx-action@v2
|
||||
|
||||
- name: Login to Docker Hub
|
||||
uses: docker/login-action@v2
|
||||
- name: Hub login
|
||||
uses: docker/login-action@v3
|
||||
if: github.event_name != 'pull_request'
|
||||
with:
|
||||
username: ${{ secrets.DOCKER_USER }}
|
||||
password: ${{ secrets.DOCKER_PASS }}
|
||||
|
||||
- name: Build and push
|
||||
uses: docker/build-push-action@v3
|
||||
- name: Server meta
|
||||
id: server
|
||||
uses: docker/metadata-action@v5
|
||||
with:
|
||||
context: .
|
||||
platforms: linux/amd64,linux/arm64
|
||||
file: ./deployment/docker/prod/buildx.Dockerfile
|
||||
push: true
|
||||
tags: semaphoreui/semaphore:beta,semaphoreui/semaphore:${{ github.ref_name }}
|
||||
github-token: ${{ secrets.GITHUB_TOKEN }}
|
||||
images: |
|
||||
semaphoreui/semaphore
|
||||
labels: |
|
||||
org.opencontainers.image.vendor=SemaphoreUI
|
||||
maintainer=Semaphore UI <support@semui.co>
|
||||
tags: |
|
||||
type=raw,value=${{ github.ref_name }}
|
||||
flavor: |
|
||||
latest=false
|
||||
|
||||
|
||||
|
||||
- name: Build and push runner
|
||||
uses: docker/build-push-action@v3
|
||||
- name: Server build
|
||||
uses: docker/build-push-action@v5
|
||||
with:
|
||||
builder: ${{ steps.buildx.outputs.name }}
|
||||
context: .
|
||||
platforms: linux/amd64,linux/arm64
|
||||
file: ./deployment/docker/prod/runner.buildx.Dockerfile
|
||||
push: true
|
||||
tags: semaphoreui/runner:beta,semaphoreui/runner:${{ github.ref_name }}
|
||||
file: deployment/docker/server/Dockerfile
|
||||
platforms: linux/amd64,linux/arm64,linux/arm/v6
|
||||
push: ${{ github.event_name != 'pull_request' }}
|
||||
labels: ${{ steps.server.outputs.labels }}
|
||||
tags: ${{ steps.server.outputs.tags }}
|
||||
|
||||
- name: Runner meta
|
||||
id: runner
|
||||
uses: docker/metadata-action@v5
|
||||
with:
|
||||
github-token: ${{ secrets.GITHUB_TOKEN }}
|
||||
images: |
|
||||
semaphoreui/runner
|
||||
labels: |
|
||||
org.opencontainers.image.vendor=SemaphoreUI
|
||||
maintainer=Semaphore UI <support@semui.co>
|
||||
tags: |
|
||||
type=raw,value=${{ github.ref_name }}
|
||||
flavor: |
|
||||
latest=false
|
||||
|
||||
- name: Runner build
|
||||
uses: docker/build-push-action@v5
|
||||
with:
|
||||
builder: ${{ steps.buildx.outputs.name }}
|
||||
context: .
|
||||
file: deployment/docker/runner/Dockerfile
|
||||
platforms: linux/amd64,linux/arm64,linux/arm/v6
|
||||
push: ${{ github.event_name != 'pull_request' }}
|
||||
labels: ${{ steps.runner.outputs.labels }}
|
||||
tags: ${{ steps.runner.outputs.tags }}
|
||||
|
642
.github/workflows/dev.yml
vendored
642
.github/workflows/dev.yml
vendored
@ -1,134 +1,610 @@
|
||||
name: Dev
|
||||
on:
|
||||
|
||||
'on':
|
||||
push:
|
||||
branches:
|
||||
- develop
|
||||
pull_request:
|
||||
branches: [develop]
|
||||
branches:
|
||||
- develop
|
||||
|
||||
jobs:
|
||||
build-local:
|
||||
runs-on: [ubuntu-latest]
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/setup-go@v3
|
||||
with: { go-version: '1.21' }
|
||||
- name: Checkout source
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- uses: actions/setup-node@v3
|
||||
with: { node-version: '16' }
|
||||
- name: Setup golang
|
||||
uses: actions/setup-go@v5
|
||||
with:
|
||||
go-version: '^1.21.0'
|
||||
|
||||
- run: go install github.com/go-task/task/v3/cmd/task@latest
|
||||
- name: Setup nodejs
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: '16'
|
||||
cache: 'npm'
|
||||
cache-dependency-path: web/package-lock.json
|
||||
|
||||
- uses: actions/checkout@v3
|
||||
- name: Install go-task
|
||||
run: |
|
||||
go install github.com/go-task/task/v3/cmd/task@latest
|
||||
|
||||
- run: task deps
|
||||
- name: Install deps
|
||||
run: |
|
||||
task deps
|
||||
|
||||
- run: task compile
|
||||
- name: Run build
|
||||
run: task build
|
||||
|
||||
- name: Test that compile did not create/modify untracked files
|
||||
run: git diff --exit-code --stat -- . ':(exclude)web/package.json' ':(exclude)web/package-lock.json' ':(exclude)go.mod' ':(exclude)go.sum'
|
||||
- name: Check modification
|
||||
run: |
|
||||
git diff --exit-code --stat -- . ':(exclude)web/package.json' ':(exclude)web/package-lock.json' ':(exclude)go.mod' ':(exclude)go.sum'
|
||||
|
||||
- run: task build:local GOOS= GOARCH=
|
||||
- name: Run tests
|
||||
run: task test
|
||||
|
||||
- run: task test
|
||||
|
||||
- uses: actions/upload-artifact@master
|
||||
- name: Upload artifacts
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: semaphore
|
||||
path: bin/semaphore
|
||||
retention-days: 1
|
||||
|
||||
migrate-boltdb:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
needs:
|
||||
- build-local
|
||||
|
||||
test-db-migration:
|
||||
runs-on: [ubuntu-latest]
|
||||
needs: [build-local]
|
||||
steps:
|
||||
- uses: shogo82148/actions-setup-mysql@v1
|
||||
with:
|
||||
mysql-version: '5.6'
|
||||
|
||||
- uses: Harmon758/postgresql-action@v1
|
||||
with:
|
||||
postgresql version: '11'
|
||||
postgresql db: 'circle_test'
|
||||
postgresql user: 'root'
|
||||
postgresql password: 'pwd'
|
||||
|
||||
- uses: actions/download-artifact@master
|
||||
- name: Download artifacts
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
name: semaphore
|
||||
|
||||
- run: sleep 5
|
||||
- name: Write config
|
||||
run: |
|
||||
cat > config.json <<EOF
|
||||
{
|
||||
"bolt": {
|
||||
"host": "/tmp/database.bolt"
|
||||
},
|
||||
"dialect": "bolt",
|
||||
"email_alert": false
|
||||
}
|
||||
EOF
|
||||
|
||||
- run: "cat > config.json <<EOF\n{\n\t\"mysql\": {\n\t\t\"host\": \"127.0.0.1:3306\"\
|
||||
,\n\t\t\"user\": \"root\",\n\t\t\"pass\": \"\",\n\t\t\"name\": \"circle_test\"\
|
||||
\n\t},\n\t\"dialect\": \"mysql\",\n\t\"email_alert\": false\n}\nEOF\n"
|
||||
- name: Migrate database
|
||||
run: |
|
||||
chmod +x ./semaphore && ./semaphore migrate --config config.json
|
||||
|
||||
- run: chmod +x ./semaphore && ./semaphore migrate --config config.json
|
||||
migrate-mysql:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
- run: "cat > config.json <<EOF\n{\n\t\"postgres\": {\n\t\t\"host\": \"127.0.0.1:5432\"\
|
||||
,\n\t\t\"options\":{\"sslmode\":\"disable\"}\
|
||||
,\n\t\t\"user\": \"root\",\n\t\t\"pass\": \"pwd\",\n\t\t\"name\": \"circle_test\"\
|
||||
\n\t},\n\t\"dialect\": \"postgres\",\n\t\"email_alert\": false\n}\nEOF\n"
|
||||
needs:
|
||||
- build-local
|
||||
|
||||
- run: chmod +x ./semaphore && ./semaphore migrate --config config.json
|
||||
services:
|
||||
mysql:
|
||||
image: mysql:8.0
|
||||
env:
|
||||
MYSQL_ROOT_PASSWORD: p455w0rd
|
||||
MYSQL_USER: semaphore
|
||||
MYSQL_PASSWORD: p455w0rd
|
||||
MYSQL_DATABASE: semaphore
|
||||
options: >-
|
||||
--health-cmd "mysqladmin ping"
|
||||
--health-interval 10s
|
||||
--health-timeout 5s
|
||||
--health-retries 5
|
||||
ports:
|
||||
- 3306:3306
|
||||
|
||||
- run: "cat > config.json <<EOF\n{\n\t\"bolt\": {\n\t\t\"host\": \"/tmp/database.bolt\"\
|
||||
\n\t},\n\t\"dialect\": \"bolt\",\n\t\"email_alert\": false\n}\nEOF\n"
|
||||
|
||||
- run: chmod +x ./semaphore && ./semaphore migrate --config config.json
|
||||
|
||||
test-integration:
|
||||
runs-on: [ubuntu-latest]
|
||||
needs: [test-db-migration]
|
||||
steps:
|
||||
- uses: actions/setup-go@v3
|
||||
with: { go-version: '1.21' }
|
||||
- name: Download artifacts
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
name: semaphore
|
||||
|
||||
- run: go install github.com/go-task/task/v3/cmd/task@latest
|
||||
- name: Write config
|
||||
run: |
|
||||
cat > config.json <<EOF
|
||||
{
|
||||
"mysql": {
|
||||
"host": "localhost:3306",
|
||||
"user": "semaphore",
|
||||
"pass": "p455w0rd",
|
||||
"name": "semaphore"
|
||||
},
|
||||
"dialect": "mysql",
|
||||
"email_alert": false
|
||||
}
|
||||
EOF
|
||||
|
||||
- uses: actions/checkout@v3
|
||||
- name: Migrate database
|
||||
run: |
|
||||
chmod +x ./semaphore && ./semaphore migrate --config config.json
|
||||
|
||||
- run: context=ci prefix=.postgres task dc:up
|
||||
- run: context=ci prefix=.bolt task dc:up
|
||||
- run: context=ci prefix=.mysql task dc:up
|
||||
migrate-mariadb:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
needs:
|
||||
- build-local
|
||||
|
||||
services:
|
||||
mariadb:
|
||||
image: mariadb:10.4
|
||||
env:
|
||||
MARIADB_ROOT_PASSWORD: p455w0rd
|
||||
MARIADB_USER: semaphore
|
||||
MARIADB_PASSWORD: p455w0rd
|
||||
MARIADB_DATABASE: semaphore
|
||||
options: >-
|
||||
--health-cmd "mysqladmin ping"
|
||||
--health-interval 10s
|
||||
--health-timeout 5s
|
||||
--health-retries 5
|
||||
ports:
|
||||
- 3306:3306
|
||||
|
||||
steps:
|
||||
- name: Download artifacts
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
name: semaphore
|
||||
|
||||
- name: Write config
|
||||
run: |
|
||||
cat > config.json <<EOF
|
||||
{
|
||||
"mysql": {
|
||||
"host": "localhost:3306",
|
||||
"user": "semaphore",
|
||||
"pass": "p455w0rd",
|
||||
"name": "semaphore"
|
||||
},
|
||||
"dialect": "mysql",
|
||||
"email_alert": false
|
||||
}
|
||||
EOF
|
||||
|
||||
- name: Migrate database
|
||||
run: |
|
||||
chmod +x ./semaphore && ./semaphore migrate --config config.json
|
||||
|
||||
migrate-postgres:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
needs:
|
||||
- build-local
|
||||
|
||||
services:
|
||||
postgres:
|
||||
image: postgres:12.18
|
||||
env:
|
||||
POSTGRES_USER: semaphore
|
||||
POSTGRES_PASSWORD: p455w0rd
|
||||
POSTGRES_DB: semaphore
|
||||
options: >-
|
||||
--health-cmd pg_isready
|
||||
--health-interval 10s
|
||||
--health-timeout 5s
|
||||
--health-retries 5
|
||||
ports:
|
||||
- 5432:5432
|
||||
|
||||
steps:
|
||||
- name: Download artifacts
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
name: semaphore
|
||||
|
||||
- name: Write config
|
||||
run: |
|
||||
cat > config.json <<EOF
|
||||
{
|
||||
"postgres": {
|
||||
"host": "localhost:5432",
|
||||
"user": "semaphore",
|
||||
"pass": "p455w0rd",
|
||||
"name": "semaphore",
|
||||
"options": {
|
||||
"sslmode": "disable"
|
||||
}
|
||||
},
|
||||
"dialect": "postgres",
|
||||
"email_alert": false
|
||||
}
|
||||
EOF
|
||||
|
||||
- name: Migrate database
|
||||
run: |
|
||||
chmod +x ./semaphore && ./semaphore migrate --config config.json
|
||||
|
||||
integrate-boltdb:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
needs:
|
||||
- migrate-boltdb
|
||||
|
||||
steps:
|
||||
- name: Checkout source
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Setup golang
|
||||
uses: actions/setup-go@v5
|
||||
with:
|
||||
go-version: '^1.21.0'
|
||||
|
||||
- name: Setup nodejs
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: '16'
|
||||
cache: 'npm'
|
||||
cache-dependency-path: web/package-lock.json
|
||||
|
||||
- name: Install go-task
|
||||
run: |
|
||||
go install github.com/go-task/task/v3/cmd/task@latest
|
||||
|
||||
- name: Download artifacts
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
name: semaphore
|
||||
|
||||
- name: Write config
|
||||
run: |
|
||||
cat > config.stdin <<EOF
|
||||
2
|
||||
/tmp/database.bolt
|
||||
/tmp/semaphore
|
||||
http://localhost:3000
|
||||
no
|
||||
no
|
||||
no
|
||||
no
|
||||
no
|
||||
no
|
||||
$(pwd)/.dredd
|
||||
admin
|
||||
admin@localhost
|
||||
Developer
|
||||
password
|
||||
EOF
|
||||
|
||||
- name: Execute setup
|
||||
run: |
|
||||
chmod +x ./semaphore && ./semaphore setup - < config.stdin
|
||||
|
||||
- name: Launch dredd
|
||||
run: |
|
||||
task e2e:goodman
|
||||
task e2e:deps
|
||||
task e2e:hooks
|
||||
task e2e:test
|
||||
|
||||
integrate-mysql:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
needs:
|
||||
- migrate-mysql
|
||||
|
||||
services:
|
||||
mysql:
|
||||
image: mysql:8.0
|
||||
env:
|
||||
MYSQL_ROOT_PASSWORD: p455w0rd
|
||||
MYSQL_USER: semaphore
|
||||
MYSQL_PASSWORD: p455w0rd
|
||||
MYSQL_DATABASE: semaphore
|
||||
options: >-
|
||||
--health-cmd "mysqladmin ping"
|
||||
--health-interval 10s
|
||||
--health-timeout 5s
|
||||
--health-retries 5
|
||||
ports:
|
||||
- 3306:3306
|
||||
|
||||
steps:
|
||||
- name: Checkout source
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Setup golang
|
||||
uses: actions/setup-go@v5
|
||||
with:
|
||||
go-version: '^1.21.0'
|
||||
|
||||
- name: Setup nodejs
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: '16'
|
||||
cache: 'npm'
|
||||
cache-dependency-path: web/package-lock.json
|
||||
|
||||
- name: Install go-task
|
||||
run: |
|
||||
go install github.com/go-task/task/v3/cmd/task@latest
|
||||
|
||||
- name: Download artifacts
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
name: semaphore
|
||||
|
||||
- name: Write config
|
||||
run: |
|
||||
cat > config.stdin <<EOF
|
||||
1
|
||||
localhost:3306
|
||||
semaphore
|
||||
p455w0rd
|
||||
semaphore
|
||||
/tmp/semaphore
|
||||
http://localhost:3000
|
||||
no
|
||||
no
|
||||
no
|
||||
no
|
||||
no
|
||||
no
|
||||
$(pwd)/.dredd
|
||||
admin
|
||||
admin@localhost
|
||||
Developer
|
||||
password
|
||||
EOF
|
||||
|
||||
- name: Execute setup
|
||||
run: |
|
||||
chmod +x ./semaphore && ./semaphore setup - < config.stdin
|
||||
|
||||
- name: Launch dredd
|
||||
run: |
|
||||
task e2e:goodman
|
||||
task e2e:deps
|
||||
task e2e:hooks
|
||||
task e2e:test
|
||||
|
||||
integrate-mariadb:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
needs:
|
||||
- migrate-mariadb
|
||||
|
||||
services:
|
||||
mariadb:
|
||||
image: mariadb:10.4
|
||||
env:
|
||||
MARIADB_ROOT_PASSWORD: p455w0rd
|
||||
MARIADB_USER: semaphore
|
||||
MARIADB_PASSWORD: p455w0rd
|
||||
MARIADB_DATABASE: semaphore
|
||||
options: >-
|
||||
--health-cmd "mysqladmin ping"
|
||||
--health-interval 10s
|
||||
--health-timeout 5s
|
||||
--health-retries 5
|
||||
ports:
|
||||
- 3306:3306
|
||||
|
||||
steps:
|
||||
- name: Checkout source
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Setup golang
|
||||
uses: actions/setup-go@v5
|
||||
with:
|
||||
go-version: '^1.21.0'
|
||||
|
||||
- name: Setup nodejs
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: '16'
|
||||
cache: 'npm'
|
||||
cache-dependency-path: web/package-lock.json
|
||||
|
||||
- name: Install go-task
|
||||
run: |
|
||||
go install github.com/go-task/task/v3/cmd/task@latest
|
||||
|
||||
- name: Download artifacts
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
name: semaphore
|
||||
|
||||
- name: Write config
|
||||
run: |
|
||||
cat > config.stdin <<EOF
|
||||
1
|
||||
localhost:3306
|
||||
semaphore
|
||||
p455w0rd
|
||||
semaphore
|
||||
/tmp/semaphore
|
||||
http://localhost:3000
|
||||
no
|
||||
no
|
||||
no
|
||||
no
|
||||
no
|
||||
no
|
||||
$(pwd)/.dredd
|
||||
admin
|
||||
admin@localhost
|
||||
Developer
|
||||
password
|
||||
EOF
|
||||
|
||||
- name: Execute setup
|
||||
run: |
|
||||
chmod +x ./semaphore && ./semaphore setup - < config.stdin
|
||||
|
||||
- name: Launch dredd
|
||||
run: |
|
||||
task e2e:goodman
|
||||
task e2e:deps
|
||||
task e2e:hooks
|
||||
task e2e:test
|
||||
|
||||
integrate-postgres:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
needs:
|
||||
- migrate-postgres
|
||||
|
||||
services:
|
||||
postgres:
|
||||
image: postgres:12.18
|
||||
env:
|
||||
POSTGRES_USER: semaphore
|
||||
POSTGRES_PASSWORD: p455w0rd
|
||||
POSTGRES_DB: semaphore
|
||||
options: >-
|
||||
--health-cmd pg_isready
|
||||
--health-interval 10s
|
||||
--health-timeout 5s
|
||||
--health-retries 5
|
||||
ports:
|
||||
- 5432:5432
|
||||
|
||||
steps:
|
||||
- name: Checkout source
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Setup golang
|
||||
uses: actions/setup-go@v5
|
||||
with:
|
||||
go-version: '^1.21.0'
|
||||
|
||||
- name: Setup nodejs
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: '16'
|
||||
cache: 'npm'
|
||||
cache-dependency-path: web/package-lock.json
|
||||
|
||||
- name: Install go-task
|
||||
run: |
|
||||
go install github.com/go-task/task/v3/cmd/task@latest
|
||||
|
||||
- name: Download artifacts
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
name: semaphore
|
||||
|
||||
- name: Write config
|
||||
run: |
|
||||
cat > config.stdin <<EOF
|
||||
3
|
||||
localhost:5432
|
||||
semaphore
|
||||
p455w0rd
|
||||
semaphore
|
||||
/tmp/semaphore
|
||||
http://localhost:3000
|
||||
no
|
||||
no
|
||||
no
|
||||
no
|
||||
no
|
||||
no
|
||||
$(pwd)/.dredd
|
||||
admin
|
||||
admin@localhost
|
||||
Developer
|
||||
password
|
||||
EOF
|
||||
|
||||
- name: Execute setup
|
||||
run: |
|
||||
chmod +x ./semaphore && ./semaphore setup - < config.stdin
|
||||
|
||||
- name: Launch dredd
|
||||
run: |
|
||||
task e2e:goodman
|
||||
task e2e:deps
|
||||
task e2e:hooks
|
||||
task e2e:test
|
||||
|
||||
deploy-dev:
|
||||
runs-on: [ubuntu-latest]
|
||||
needs: [test-integration]
|
||||
if: github.ref == 'refs/heads/develop'
|
||||
runs-on: ubuntu-latest
|
||||
if: github.repository_owner == 'semaphoreui'
|
||||
|
||||
needs:
|
||||
- integrate-boltdb
|
||||
- integrate-mysql
|
||||
- integrate-mariadb
|
||||
- integrate-postgres
|
||||
|
||||
steps:
|
||||
- uses: actions/setup-go@v3
|
||||
with: { go-version: '1.21' }
|
||||
- name: Checkout source
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- run: go install github.com/go-task/task/v3/cmd/task@latest
|
||||
- name: Setup qemu
|
||||
id: qemu
|
||||
uses: docker/setup-qemu-action@v3
|
||||
|
||||
- uses: actions/checkout@v3
|
||||
- name: Setup buildx
|
||||
id: buildx
|
||||
uses: docker/setup-buildx-action@v3
|
||||
|
||||
- uses: docker/setup-qemu-action@v2
|
||||
|
||||
- uses: docker/setup-buildx-action@v2
|
||||
|
||||
- name: Login to Docker Hub
|
||||
uses: docker/login-action@v2
|
||||
- name: Hub login
|
||||
uses: docker/login-action@v3
|
||||
if: github.event_name != 'pull_request'
|
||||
with:
|
||||
username: ${{ secrets.DOCKER_USER }}
|
||||
password: ${{ secrets.DOCKER_PASS }}
|
||||
|
||||
- name: Build and push
|
||||
uses: docker/build-push-action@v3
|
||||
- name: Server meta
|
||||
id: server
|
||||
uses: docker/metadata-action@v5
|
||||
with:
|
||||
context: .
|
||||
platforms: linux/amd64,linux/arm64
|
||||
file: ./deployment/docker/prod/buildx.Dockerfile
|
||||
push: true
|
||||
tags: semaphoreui/semaphore:develop
|
||||
github-token: ${{ secrets.GITHUB_TOKEN }}
|
||||
images: |
|
||||
semaphoreui/semaphore
|
||||
labels: |
|
||||
org.opencontainers.image.vendor=SemaphoreUI
|
||||
maintainer=Semaphore UI <support@semui.co>
|
||||
tags: |
|
||||
type=raw,value=develop
|
||||
flavor: |
|
||||
latest=false
|
||||
|
||||
- name: Build and push runner
|
||||
uses: docker/build-push-action@v3
|
||||
- name: Server build
|
||||
uses: docker/build-push-action@v5
|
||||
with:
|
||||
builder: ${{ steps.buildx.outputs.name }}
|
||||
context: .
|
||||
platforms: linux/amd64,linux/arm64
|
||||
file: ./deployment/docker/prod/runner.buildx.Dockerfile
|
||||
push: true
|
||||
tags: semaphoreui/runner:develop
|
||||
file: deployment/docker/server/Dockerfile
|
||||
platforms: linux/amd64,linux/arm64 #,linux/arm/v6
|
||||
push: ${{ github.event_name != 'pull_request' }}
|
||||
labels: ${{ steps.server.outputs.labels }}
|
||||
tags: ${{ steps.server.outputs.tags }}
|
||||
|
||||
- name: Runner meta
|
||||
id: runner
|
||||
uses: docker/metadata-action@v5
|
||||
with:
|
||||
github-token: ${{ secrets.GITHUB_TOKEN }}
|
||||
images: |
|
||||
semaphoreui/runner
|
||||
labels: |
|
||||
org.opencontainers.image.vendor=SemaphoreUI
|
||||
maintainer=Semaphore UI <support@semui.co>
|
||||
tags: |
|
||||
type=raw,value=develop
|
||||
flavor: |
|
||||
latest=false
|
||||
|
||||
- name: Runner build
|
||||
uses: docker/build-push-action@v5
|
||||
with:
|
||||
builder: ${{ steps.buildx.outputs.name }}
|
||||
context: .
|
||||
file: deployment/docker/runner/Dockerfile
|
||||
platforms: linux/amd64,linux/arm64,linux/arm/v6
|
||||
push: ${{ github.event_name != 'pull_request' }}
|
||||
labels: ${{ steps.runner.outputs.labels }}
|
||||
tags: ${{ steps.runner.outputs.tags }}
|
||||
|
142
.github/workflows/release.yml
vendored
142
.github/workflows/release.yml
vendored
@ -1,75 +1,131 @@
|
||||
name: Release
|
||||
on:
|
||||
|
||||
'on':
|
||||
push:
|
||||
tags:
|
||||
- 'v[0-9]+.[0-9]+.[0-9]+'
|
||||
|
||||
jobs:
|
||||
release:
|
||||
runs-on: [ubuntu-latest]
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/setup-go@v3
|
||||
with: { go-version: '1.21' }
|
||||
- name: Checkout source
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- uses: actions/setup-node@v3
|
||||
with: { node-version: '16' }
|
||||
- name: Setup golang
|
||||
uses: actions/setup-go@v5
|
||||
with:
|
||||
go-version: '^1.21.0'
|
||||
|
||||
- run: go install github.com/go-task/task/v3/cmd/task@latest
|
||||
- name: Setup nodejs
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: '16'
|
||||
cache: 'npm'
|
||||
cache-dependency-path: web/package-lock.json
|
||||
|
||||
- run: sudo apt update && sudo apt-get install rpm
|
||||
- name: Install go-task
|
||||
run: |
|
||||
go install github.com/go-task/task/v3/cmd/task@latest
|
||||
|
||||
- uses: actions/checkout@v3
|
||||
- name: Install rpm
|
||||
run: |
|
||||
sudo apt update && sudo apt-get install rpm
|
||||
|
||||
- run: task deps
|
||||
- name: Install deps
|
||||
run: |
|
||||
task deps
|
||||
|
||||
- run: |
|
||||
echo ${{ secrets.GPG_KEY }} | tr " " "\n" | base64 -d | gpg --import --batch
|
||||
- name: Import gnupg
|
||||
run: |
|
||||
echo "${{ secrets.GPG_KEY }}" | tr " " "\n" | base64 -d | gpg --import --batch
|
||||
gpg --sign -u "58A7 CC3D 8A9C A2E5 BB5C 141D 4064 23EA F814 63CA" --pinentry-mode loopback --yes --batch --passphrase "${{ secrets.GPG_PASS }}" --output unlock.sig --detach-sign README.md
|
||||
rm -f unlock.sig
|
||||
|
||||
- run: git reset --hard
|
||||
|
||||
- run: GITHUB_TOKEN=${{ secrets.GH_TOKEN }} task release:prod
|
||||
- name: Reset repo
|
||||
run: |
|
||||
git reset --hard
|
||||
|
||||
- name: Run release
|
||||
run: |
|
||||
GITHUB_TOKEN=${{ secrets.GH_TOKEN }} task release:prod
|
||||
|
||||
deploy-prod:
|
||||
runs-on: [ubuntu-latest]
|
||||
runs-on: ubuntu-latest
|
||||
if: github.repository_owner == 'semaphoreui'
|
||||
|
||||
steps:
|
||||
- uses: actions/setup-go@v3
|
||||
with: { go-version: '1.21' }
|
||||
- name: Checkout source
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- run: go install github.com/go-task/task/v3/cmd/task@latest
|
||||
- name: Setup qemu
|
||||
id: qemu
|
||||
uses: docker/setup-qemu-action@v3
|
||||
|
||||
- uses: actions/checkout@v3
|
||||
- name: Setup buildx
|
||||
id: buildx
|
||||
uses: docker/setup-buildx-action@v3
|
||||
|
||||
- run: context=prod task docker:test
|
||||
|
||||
- uses: docker/setup-qemu-action@v2
|
||||
|
||||
- uses: docker/setup-buildx-action@v2
|
||||
|
||||
- name: Login to Docker Hub
|
||||
uses: docker/login-action@v2
|
||||
- name: Hub login
|
||||
uses: docker/login-action@v3
|
||||
if: github.event_name != 'pull_request'
|
||||
with:
|
||||
username: ${{ secrets.DOCKER_USER }}
|
||||
password: ${{ secrets.DOCKER_PASS }}
|
||||
|
||||
- name: Build and push
|
||||
uses: docker/build-push-action@v3
|
||||
- name: Server meta
|
||||
id: server
|
||||
uses: docker/metadata-action@v5
|
||||
with:
|
||||
context: .
|
||||
platforms: linux/amd64,linux/arm64
|
||||
file: ./deployment/docker/prod/buildx.Dockerfile
|
||||
push: true
|
||||
tags: semaphoreui/semaphore:latest,semaphoreui/semaphore:${{ github.ref_name }}
|
||||
github-token: ${{ secrets.GITHUB_TOKEN }}
|
||||
images: |
|
||||
semaphoreui/semaphore
|
||||
labels: |
|
||||
org.opencontainers.image.vendor=SemaphoreUI
|
||||
maintainer=Semaphore UI <support@semui.co>
|
||||
tags: |
|
||||
type=semver,pattern={{version}}
|
||||
type=semver,pattern={{major}}.{{minor}}
|
||||
type=semver,pattern={{major}}
|
||||
flavor: |
|
||||
latest=true
|
||||
|
||||
|
||||
|
||||
- name: Build and push runner
|
||||
uses: docker/build-push-action@v3
|
||||
- name: Server build
|
||||
uses: docker/build-push-action@v5
|
||||
with:
|
||||
builder: ${{ steps.buildx.outputs.name }}
|
||||
context: .
|
||||
platforms: linux/amd64,linux/arm64
|
||||
file: ./deployment/docker/prod/runner.buildx.Dockerfile
|
||||
push: true
|
||||
tags: semaphoreui/runner:latest,semaphoreui/runner:${{ github.ref_name }}
|
||||
file: deployment/docker/server/Dockerfile
|
||||
platforms: linux/amd64,linux/arm64,linux/arm/v6
|
||||
push: ${{ github.event_name != 'pull_request' }}
|
||||
labels: ${{ steps.server.outputs.labels }}
|
||||
tags: ${{ steps.server.outputs.tags }}
|
||||
|
||||
- name: Runner meta
|
||||
id: runner
|
||||
uses: docker/metadata-action@v5
|
||||
with:
|
||||
github-token: ${{ secrets.GITHUB_TOKEN }}
|
||||
images: |
|
||||
semaphoreui/runner
|
||||
labels: |
|
||||
org.opencontainers.image.vendor=SemaphoreUI
|
||||
maintainer=Semaphore UI <support@semui.co>
|
||||
tags: |
|
||||
type=semver,pattern={{version}}
|
||||
type=semver,pattern={{major}}.{{minor}}
|
||||
type=semver,pattern={{major}}
|
||||
flavor: |
|
||||
latest=true
|
||||
|
||||
- name: Runner build
|
||||
uses: docker/build-push-action@v5
|
||||
with:
|
||||
builder: ${{ steps.buildx.outputs.name }}
|
||||
context: .
|
||||
file: deployment/docker/runner/Dockerfile
|
||||
platforms: linux/amd64,linux/arm64 #,linux/arm/v6
|
||||
push: ${{ github.event_name != 'pull_request' }}
|
||||
labels: ${{ steps.runner.outputs.labels }}
|
||||
tags: ${{ steps.runner.outputs.tags }}
|
||||
|
1
.gitignore
vendored
1
.gitignore
vendored
@ -18,7 +18,6 @@ node_modules/
|
||||
/semaphore.iml
|
||||
/bin/
|
||||
|
||||
util/version.go
|
||||
/vendor/
|
||||
/coverage.out
|
||||
/public/package-lock.json
|
||||
|
@ -1,77 +1,72 @@
|
||||
# Goreleaser configuration
|
||||
# for building binaries and packages for distributions and releasing on github
|
||||
dist: bin
|
||||
|
||||
before:
|
||||
hooks:
|
||||
- task compile
|
||||
- task build:fe
|
||||
|
||||
builds:
|
||||
- binary: semaphore
|
||||
env:
|
||||
- CGO_ENABLED=0
|
||||
main: ./cli/main.go
|
||||
ldflags: -s -w -X github.com/ansible-semaphore/semaphore/util.Ver={{ .Version }} -X github.com/ansible-semaphore/semaphore/util.Commit={{ .ShortCommit }} -X github.com/ansible-semaphore/semaphore/util.Date={{ .Timestamp }}
|
||||
tags:
|
||||
- netgo
|
||||
goos:
|
||||
- windows
|
||||
- darwin
|
||||
- linux
|
||||
- freebsd
|
||||
#- openbsd
|
||||
#- netbsd
|
||||
goarch:
|
||||
- 386
|
||||
- amd64
|
||||
#- 386
|
||||
- arm
|
||||
- arm64
|
||||
- ppc64le
|
||||
ignore:
|
||||
- goos: darwin
|
||||
goarch: 386
|
||||
# hooks:
|
||||
# pre: task compile
|
||||
- goos: darwin
|
||||
goarch: arm
|
||||
- goos: darwin
|
||||
goarch: ppc64le
|
||||
- goos: windows
|
||||
goarch: ppc64le
|
||||
|
||||
archives:
|
||||
-
|
||||
- files:
|
||||
- LICENSE
|
||||
format_overrides:
|
||||
- goos: windows
|
||||
format: zip
|
||||
files:
|
||||
- LICENSE
|
||||
|
||||
signs:
|
||||
-
|
||||
artifacts: checksum
|
||||
- artifacts: checksum
|
||||
args: ["-u", "58A7 CC3D 8A9C A2E5 BB5C 141D 4064 23EA F814 63CA", "--pinentry-mode", "loopback", "--yes", "--batch", "--output", "${signature}", "--detach-sign", "${artifact}"]
|
||||
|
||||
# Start the snapshot name with a numerical value
|
||||
# so it does not need to be force installed
|
||||
snapshot:
|
||||
name_template: "{{ .Timestamp }}-{{ .ShortCommit }}-SNAPSHOT"
|
||||
|
||||
nfpms:
|
||||
-
|
||||
file_name_template: "{{ .ProjectName }}_{{ .Version }}_{{ .Os }}_{{ .Arch }}"
|
||||
|
||||
vendor: Castaway Consulting LLC
|
||||
homepage: https://github.com/ansible-semaphore/semaphore
|
||||
maintainer: Castaway Consulting LLC <support@castawaylabs.com>
|
||||
- file_name_template: "{{ .ProjectName }}_{{ .Version }}_{{ .Os }}_{{ .Arch }}"
|
||||
description: Open Source alternative to Ansible Tower
|
||||
homepage: https://github.com/semaphoreui/semaphore
|
||||
vendor: Semaphore UI
|
||||
maintainer: Semaphore UI <support@semui.co>
|
||||
license: MIT
|
||||
|
||||
formats:
|
||||
- deb
|
||||
- rpm
|
||||
|
||||
# Packages your package depends on.
|
||||
dependencies:
|
||||
- git
|
||||
|
||||
suggests:
|
||||
- ansible
|
||||
|
||||
# install binary in /usr/bin
|
||||
bindir: /usr/bin
|
||||
|
||||
release:
|
||||
# Do not auto publish release
|
||||
draft: true
|
||||
name_template: "{{.Tag}}"
|
||||
|
405
Taskfile.yml
405
Taskfile.yml
@ -1,77 +1,59 @@
|
||||
# Semaphore Tasks
|
||||
# These tasks should be used to build and develop Semaphore
|
||||
#
|
||||
# Tasks without a `desc:` field are intended mainly to be called
|
||||
# internally by other tasks and therefore are not listed when running `task` or `task -l`
|
||||
version: '3'
|
||||
version: "3"
|
||||
|
||||
vars:
|
||||
docker_namespace: semaphoreui
|
||||
docker_image: semaphore
|
||||
|
||||
|
||||
DOCKER_ORG: semaphoreui
|
||||
DOCKER_SERVER: semaphore
|
||||
DOCKER_RUNNER: runner
|
||||
DOCKER_CMD: docker
|
||||
|
||||
tasks:
|
||||
all:
|
||||
desc: Install, Compile, Test and Build Semaphore for local architecture
|
||||
desc: Install, test and build Semaphore for local architecture
|
||||
cmds:
|
||||
- task: deps
|
||||
- task: compile
|
||||
- task: test
|
||||
- task: build:local
|
||||
- task: build
|
||||
vars:
|
||||
GOOS: ''
|
||||
GOARCH: ''
|
||||
GOOS: ""
|
||||
GOARCH: ""
|
||||
|
||||
deps:
|
||||
desc: Install all dependencies (except dredd requirements)
|
||||
desc: Install all build dependencies
|
||||
cmds:
|
||||
- task: deps:tools
|
||||
- task: deps:be
|
||||
- task: deps:fe2
|
||||
- task: deps:fe
|
||||
|
||||
deps:tools:
|
||||
desc: Installs required tools to build and publish
|
||||
vars:
|
||||
SWAGGER_VERSION: v0.30.5
|
||||
GORELEASER_VERSION: v1.25.1
|
||||
GOLINTER_VERSION: v1.57.2
|
||||
cmds:
|
||||
- go install github.com/go-swagger/go-swagger/cmd/swagger@{{ .SWAGGER_VERSION }}
|
||||
- go install github.com/goreleaser/goreleaser@{{ .GORELEASER_VERSION }}
|
||||
- go install github.com/golangci/golangci-lint/cmd/golangci-lint@{{ .GOLINTER_VERSION }}
|
||||
|
||||
deps:be:
|
||||
desc: Vendor application dependencies
|
||||
cmds:
|
||||
- go mod vendor
|
||||
|
||||
deps:fe2:
|
||||
desc: Installs npm requirements for front end from package.json
|
||||
deps:fe:
|
||||
desc: Installs nodejs requirements
|
||||
dir: web
|
||||
cmds:
|
||||
- npm install
|
||||
# - npm audit fix
|
||||
|
||||
deps:integration:
|
||||
desc: Installs requirements for integration testing with dredd
|
||||
dir: web
|
||||
build:
|
||||
desc: Build a full set of release binaries and packages
|
||||
cmds:
|
||||
- npm install dredd@13.1.2
|
||||
# - npm audit fix
|
||||
- task: build:fe
|
||||
- task: build:be
|
||||
|
||||
deps:tools:
|
||||
desc: Installs tools needed
|
||||
dir: web
|
||||
vars:
|
||||
GORELEASER_VERSION: "0.183.0"
|
||||
GOLINTER_VERSION: "1.46.2"
|
||||
cmds:
|
||||
- go install github.com/snikch/goodman/cmd/goodman@latest
|
||||
- go install github.com/go-swagger/go-swagger/cmd/swagger@v0.29.0
|
||||
- '{{ if ne OS "windows" }} sh -c "curl -L https://github.com/goreleaser/goreleaser/releases/download/v{{ .GORELEASER_VERSION }}/goreleaser_$(uname -s)_$(uname -m).tar.gz | tar -xz -C $(go env GOPATH)/bin goreleaser"{{ else }} {{ end }}'
|
||||
- '{{ if ne OS "windows" }} chmod +x $(go env GOPATH)/bin/goreleaser{{ else }} {{ end }}'
|
||||
- '{{ if eq OS "windows" }} echo "NOTICE: You must download goreleaser manually to build this application https://github.com/goreleaser/goreleaser/releases "{{ else }}:{{ end }}'
|
||||
# - '{{ if ne OS "windows" }} sh -c "curl -sSfL https://raw.githubusercontent.com/golangci/golangci-lint/master/install.sh | sh -s -- -b $(go env GOPATH)/bin v{{ .GOLINTER_VERSION }}"{{ else }}{{ end }}'
|
||||
- '{{ if eq OS "windows" }} echo "NOTICE: You need to install golangci-lint manually to build this application https://github.com/golangci/golangci-lint#install"{{ else }}{{ end }}'
|
||||
|
||||
compile:
|
||||
desc: Generates compiled frontend and backend resources (must be in this order)
|
||||
cmds:
|
||||
- task: compile:fe2
|
||||
- task: compile:be
|
||||
|
||||
compile:fe2:
|
||||
desc: Build vue.js project
|
||||
build:fe:
|
||||
desc: Build VueJS project
|
||||
dir: web
|
||||
sources:
|
||||
- src/*.*
|
||||
@ -90,199 +72,230 @@ tasks:
|
||||
cmds:
|
||||
- npm run build
|
||||
|
||||
compile:be:
|
||||
desc: Generate the version
|
||||
build:be:
|
||||
desc: Build server binary
|
||||
cmds:
|
||||
- go run util/version_gen/generator.go {{ if .TAG }}{{ .TAG }}{{ else }}{{ if .SEMAPHORE_VERSION }}{{ .SEMAPHORE_VERSION }}{{ else }}{{ .BRANCH }}-{{ .SHA }}-{{ .TIMESTAMP }}{{ if .DIRTY }}-dirty{{ end }}{{ end }}{{end}}
|
||||
- >-
|
||||
env CGO_ENABLED=0 GOOS={{ .GOOS }} GOARCH={{ .GOARCH }}
|
||||
go build -o bin/semaphore{{ if eq OS "windows" }}.exe{{ end }}
|
||||
-tags "netgo"
|
||||
-ldflags "-s -w -X {{ .IMPORT }}/util.Ver={{ .VERSION }} -X {{ .IMPORT }}/util.Commit={{ .SHA }} -X {{ .IMPORT }}/util.Date={{ .DATE }}" ./cli
|
||||
vars:
|
||||
TAG:
|
||||
sh: git name-rev --name-only --tags --no-undefined HEAD 2>/dev/null | sed -n 's/^\([^^~]\{1,\}\)\(\^0\)\{0,1\}$/\1/p'
|
||||
BRANCH:
|
||||
sh: git rev-parse --abbrev-ref HEAD
|
||||
DIRTY:
|
||||
# We must exclude the package-lock file as npm install can change it!
|
||||
sh: git diff --exit-code --stat -- . ':(exclude)web/package-lock.json' ':(exclude)web/package.json' || true
|
||||
sh: git name-rev --name-only --tags --no-undefined HEAD 2>/dev/null || git rev-parse --abbrev-ref HEAD
|
||||
SHA:
|
||||
sh: git log --pretty=format:'%h' -n 1
|
||||
TIMESTAMP:
|
||||
sh: date +%s
|
||||
|
||||
compile:api:hooks:
|
||||
dir: ./.dredd/hooks
|
||||
cmds:
|
||||
- go build -o ../compiled_hooks{{ if eq OS "windows" }}.exe{{ end }}
|
||||
|
||||
build:
|
||||
desc: Build a full set of release binaries and packages
|
||||
cmds:
|
||||
- task: release
|
||||
|
||||
build:local:
|
||||
desc: Build a binary for the current architecture
|
||||
dir: cli
|
||||
cmds:
|
||||
- env CGO_ENABLED=0 GOOS={{ .GOOS }} GOARCH={{ .GOARCH }} go build -o ../bin/semaphore{{ if eq OS "windows" }}.exe{{ end }}
|
||||
|
||||
release:
|
||||
desc: creates a release without performing validations or publishing artifacts
|
||||
cmds:
|
||||
- goreleaser --snapshot --rm-dist
|
||||
|
||||
release:prod:
|
||||
cmds:
|
||||
- goreleaser
|
||||
VERSION: "{{ if eq .GITHUB_REF_TYPE \"tag\" }}{{ .GITHUB_REF_NAME }}{{ else }}{{ .TAG }}{{ end }}"
|
||||
DATE: "{{ now | unixEpoch }}"
|
||||
IMPORT: "github.com/ansible-semaphore/semaphore"
|
||||
|
||||
lint:
|
||||
cmds:
|
||||
- task: lint:fe
|
||||
- task: lint:be
|
||||
|
||||
lint:fe:
|
||||
dir: web
|
||||
cmds:
|
||||
- npm run lint
|
||||
|
||||
lint:be:
|
||||
# --errors
|
||||
cmds:
|
||||
- golangci-lint run --disable goconst --timeout 240s ./...
|
||||
- go vet ./...
|
||||
- swagger validate ./api-docs.yml
|
||||
|
||||
test:
|
||||
cmds:
|
||||
# - task: test:fe
|
||||
- task: test:be
|
||||
|
||||
test:fe:
|
||||
dir: web
|
||||
cmds:
|
||||
- npm run test:unit
|
||||
|
||||
test:be:
|
||||
desc: Run go code tests
|
||||
cmds:
|
||||
- go vet ./...
|
||||
- swagger validate ./api-docs.yml
|
||||
- go test -v -coverprofile=coverage.out ./...
|
||||
|
||||
test:api:
|
||||
desc: test the api with dredd
|
||||
e2e:goodman:
|
||||
desc: Installs goodman which is required by dredd
|
||||
cmds:
|
||||
- ./web/node_modules/.bin/dredd --config .dredd/dredd.yml
|
||||
- go install github.com/snikch/goodman/cmd/goodman@latest
|
||||
|
||||
ci:artifacts:
|
||||
e2e:deps:
|
||||
desc: Installs dredd dep for integration testing
|
||||
dir: web
|
||||
cmds:
|
||||
- rsync -a bin/ $CIRCLE_ARTIFACTS/
|
||||
- npm install dredd@13.1.2
|
||||
|
||||
# docker(-compose) commands
|
||||
dc:dev:
|
||||
desc: build and start a development stack using docker-compose
|
||||
e2e:hooks:
|
||||
desc: Compile required dredd hooks built
|
||||
dir: ./.dredd/hooks
|
||||
cmds:
|
||||
- task: docker
|
||||
vars:
|
||||
context: dev
|
||||
args: build semaphore_dev
|
||||
compose: true
|
||||
- task: dc:up
|
||||
vars:
|
||||
context: dev
|
||||
- go build -o ../compiled_hooks{{ if eq OS "windows" }}.exe{{ end }}
|
||||
|
||||
# convenience function to build and start a production like stack
|
||||
dc:prod:
|
||||
desc: build and start a production like stack using docker-compose
|
||||
e2e:test:
|
||||
desc: Run end to end test for API with dredd
|
||||
cmds:
|
||||
- task: docker
|
||||
vars:
|
||||
context: prod
|
||||
args: build semaphore
|
||||
compose: true
|
||||
- task: dc:up
|
||||
vars:
|
||||
context: prod
|
||||
- ./web/node_modules/.bin/dredd --config .dredd/dredd.testing.yml
|
||||
|
||||
dc:up:
|
||||
desc: start a docker-compose instance, requires context
|
||||
release:prod:
|
||||
desc: Create and publish a release
|
||||
cmds:
|
||||
- task: docker
|
||||
vars:
|
||||
compose: true
|
||||
args: up --abort-on-container-exit
|
||||
prefix: "{{ .prefix }}"
|
||||
context: "{{ .context }}"
|
||||
- goreleaser
|
||||
|
||||
dc:build:
|
||||
desc: build a set of docker-compose containers, requires context
|
||||
release:test:
|
||||
desc: Create a local test release
|
||||
cmds:
|
||||
- task: docker
|
||||
vars:
|
||||
compose: true
|
||||
args: build
|
||||
context: "{{ .context }}"
|
||||
|
||||
dc:down:
|
||||
desc: down a docker-compose instance, requires context
|
||||
cmds:
|
||||
- task: docker
|
||||
vars:
|
||||
compose: true
|
||||
args: down
|
||||
context: "{{ .context }}"
|
||||
|
||||
dc:stop:
|
||||
desc: stop a docker-compose instance, requires context
|
||||
cmds:
|
||||
- task: docker
|
||||
vars:
|
||||
compose: true
|
||||
args: stop
|
||||
context: "{{ .context }}"
|
||||
|
||||
docker:build:
|
||||
desc: Build an image for Semaphore, requires context
|
||||
vars:
|
||||
tag: "{{ if .tag }}{{ .tag }}{{ else }}latest{{ end }}"
|
||||
cmds:
|
||||
- task: docker
|
||||
vars:
|
||||
context: "{{ .context }}"
|
||||
action: build
|
||||
tag: "{{ .tag }}"
|
||||
args: -t "{{ .docker_namespace }}/{{ .docker_image }}:{{ .tag }}" .
|
||||
|
||||
deps:docker:
|
||||
desc: Install docker testing dependencies. These must be installed explicitly and are not included in the general deps task.
|
||||
status:
|
||||
- test -f /usr/local/bin/goss
|
||||
- test -f /usr/local/bin/dgoss
|
||||
- test -f /usr/local/bin/hadolint
|
||||
cmds:
|
||||
- sudo curl -L https://github.com/aelsabbahy/goss/releases/download/v0.3.5/goss-linux-amd64 -o /usr/local/bin/goss
|
||||
- sudo chmod +rx /usr/local/bin/goss
|
||||
- sudo curl -L https://raw.githubusercontent.com/aelsabbahy/goss/v0.3.5/extras/dgoss/dgoss -o /usr/local/bin/dgoss
|
||||
- sudo chmod +rx /usr/local/bin/dgoss
|
||||
- sudo curl -L https://github.com/hadolint/hadolint/releases/download/v2.10.0/hadolint-Linux-x86_64 -o /usr/local/bin/hadolint
|
||||
- sudo chmod +rx /usr/local/bin/hadolint
|
||||
- goreleaser --auto-snapshot --clean --skip=sign
|
||||
|
||||
docker:test:
|
||||
desc: Test docker containers by building them, running tests and deleting
|
||||
deps: ['deps:docker']
|
||||
desc: Test containers by building, running, testing and deleting them
|
||||
deps:
|
||||
- task: docker:deps
|
||||
cmds:
|
||||
- task: docker:lint
|
||||
vars:
|
||||
context: "{{ .context }}"
|
||||
- task: docker:build
|
||||
vars:
|
||||
tag: "{{ .context }}-test"
|
||||
- task: docker:goss
|
||||
- docker rmi "{{ .docker_namespace }}/{{ .docker_image }}:{{ .context }}-test"
|
||||
tag: test
|
||||
|
||||
docker:goss:
|
||||
dir: "deployment/docker/{{ .context}}"
|
||||
deps: ['deps:docker']
|
||||
cmds:
|
||||
- GOSS_FILES_STRATEGY='cp' dgoss run -it "{{ .docker_namespace }}/{{ .docker_image }}:{{ .context }}-test"
|
||||
- task: docker:goss
|
||||
- task: docker:lint
|
||||
|
||||
- "{{ .DOCKER_CMD }} rmi {{ .DOCKER_ORG }}/{{ .DOCKER_SERVER }}:test"
|
||||
- "{{ .DOCKER_CMD }} rmi {{ .DOCKER_ORG }}/{{ .DOCKER_RUNNER }}:test"
|
||||
|
||||
docker:lint:
|
||||
desc: hadolint a dockerfile. Ignores version pinning warning
|
||||
dir: "deployment/docker/{{ .context}}"
|
||||
desc: Lint all dockerfiles based on Hadolint
|
||||
deps:
|
||||
- task: docker:deps
|
||||
cmds:
|
||||
- task: docker:lint:server
|
||||
- task: docker:lint:runner
|
||||
|
||||
docker:lint:server:
|
||||
desc: Lint server dockerfile based on Hadolint
|
||||
dir: deployment/docker/server
|
||||
cmds:
|
||||
- hadolint Dockerfile --ignore DL3018
|
||||
|
||||
docker:push:
|
||||
desc: push a docker image to a repo. Defaults to the official docker hub
|
||||
docker:lint:runner:
|
||||
desc: Lint runner dockerfile based on Hadolint
|
||||
dir: deployment/docker/runner
|
||||
cmds:
|
||||
- docker push {{ .docker_namespace }}/{{ .docker_image }}:{{ .tag }}
|
||||
- hadolint Dockerfile --ignore DL3018
|
||||
|
||||
# templated command to reduce code duplication
|
||||
docker:
|
||||
vars:
|
||||
docker_root: deployment/docker/
|
||||
docker:goss:
|
||||
desc: Check if container contains defined files
|
||||
deps:
|
||||
- task: docker:deps
|
||||
cmds:
|
||||
- docker{{ if .compose }}-compose{{ end }} {{ if .action }}{{ .action }}{{ end }} -f {{ .docker_root }}{{ .context }}/{{ if .compose }}docker-compose{{ if .prefix }}{{ .prefix }}{{ end }}.yml{{ else }}Dockerfile{{ if .prefix }}{{ .prefix }}{{ end }}{{ end }} {{if .args }}{{ .args }}{{ end }}
|
||||
- task: docker:goss:server
|
||||
- task: docker:goss:runner
|
||||
|
||||
docker:goss:server:
|
||||
desc: Check if server contains defined files
|
||||
dir: deployment/docker/server
|
||||
env:
|
||||
GOSS_FILES_STRATEGY: cp
|
||||
cmds:
|
||||
- dgoss run -it "{{ .DOCKER_ORG }}/{{ .DOCKER_SERVER }}:test"
|
||||
|
||||
docker:goss:runner:
|
||||
desc: Check if runner contains defined files
|
||||
dir: deployment/docker/runner
|
||||
env:
|
||||
GOSS_FILES_STRATEGY: cp
|
||||
cmds:
|
||||
- dgoss run -it "{{ .DOCKER_ORG }}/{{ .DOCKER_RUNNER }}:test"
|
||||
|
||||
docker:build:
|
||||
desc: Build all defined images for Semaphore
|
||||
vars:
|
||||
tag: "{{ if .tag }}{{ .tag }}{{ else }}latest{{ end }}"
|
||||
cmds:
|
||||
- task: docker:build:server
|
||||
vars:
|
||||
tag: "{{ .tag }}"
|
||||
- task: docker:build:runner
|
||||
vars:
|
||||
tag: "{{ .tag }}"
|
||||
|
||||
docker:build:server:
|
||||
desc: Build an image for Semaphore server
|
||||
vars:
|
||||
tag: "{{ if .tag }}{{ .tag }}{{ else }}latest{{ end }}"
|
||||
cmds:
|
||||
- "{{ .DOCKER_CMD }} build -f deployment/docker/server/Dockerfile -t {{ .DOCKER_ORG }}/{{ .DOCKER_SERVER }}:{{ .tag }} ."
|
||||
|
||||
docker:build:runner:
|
||||
desc: Build an image for Semaphore runner
|
||||
vars:
|
||||
tag: "{{ if .tag }}{{ .tag }}{{ else }}latest{{ end }}"
|
||||
cmds:
|
||||
- "{{ .DOCKER_CMD }} build -f deployment/docker/runner/Dockerfile -t {{ .DOCKER_ORG }}/{{ .DOCKER_RUNNER }}:{{ .tag }} ."
|
||||
|
||||
docker:push:
|
||||
desc: Push the images to registry
|
||||
cmds:
|
||||
- docker push {{ .DOCKER_ORG }}/{{ .DOCKER_SERVER }}:{{ .tag }}
|
||||
- docker push {{ .DOCKER_ORG }}/{{ .DOCKER_RUNNER }}:{{ .tag }}
|
||||
|
||||
docker:deps:
|
||||
desc: Install docker testing dependencies
|
||||
vars:
|
||||
INSTALL_PATH: '{{ .INSTALL_PATH | default "/usr/local/bin" }}'
|
||||
REQUIRE_SUDO: '{{ .REQUIRE_SUDO | default "true" }}'
|
||||
cmds:
|
||||
- task: docker:deps:hadolint
|
||||
vars:
|
||||
INSTALL_PATH: "{{ .INSTALL_PATH }}"
|
||||
REQUIRE_SUDO: "{{ .REQUIRE_SUDO }}"
|
||||
- task: docker:deps:goss
|
||||
vars:
|
||||
INSTALL_PATH: "{{ .INSTALL_PATH }}"
|
||||
REQUIRE_SUDO: "{{ .REQUIRE_SUDO }}"
|
||||
- task: docker:deps:dgoss
|
||||
vars:
|
||||
INSTALL_PATH: "{{ .INSTALL_PATH }}"
|
||||
REQUIRE_SUDO: "{{ .REQUIRE_SUDO }}"
|
||||
|
||||
docker:deps:hadolint:
|
||||
platforms:
|
||||
- linux/amd64
|
||||
- linux/arm64
|
||||
- darwin/amd64
|
||||
- darwin/arm64
|
||||
vars:
|
||||
HADOLINT_VERSION: v2.10.0
|
||||
status:
|
||||
- test -f "{{ .INSTALL_PATH }}/hadolint"
|
||||
cmds:
|
||||
- '{{ if eq .REQUIRE_SUDO "true" }}sudo {{ end }}curl -sSL https://github.com/hadolint/hadolint/releases/download/{{ .HADOLINT_VERSION }}/hadolint-{{ if eq OS "linux" }}Linux{{ end }}{{ if eq OS "darwin" }}Darwin{{ end }}-{{ if eq ARCH "amd64" }}x86_64{{ else }}{{ ARCH }}{{ end }} -o {{ .INSTALL_PATH }}/hadolint'
|
||||
- '{{ if eq .REQUIRE_SUDO "true" }}sudo {{ end }}chmod +x {{ .INSTALL_PATH }}/hadolint'
|
||||
|
||||
docker:deps:goss:
|
||||
platforms:
|
||||
- linux
|
||||
- darwin
|
||||
vars:
|
||||
GOSS_VERSION: v0.3.5
|
||||
status:
|
||||
- test -f "{{ .INSTALL_PATH }}/goss"
|
||||
cmds:
|
||||
- '{{ if eq .REQUIRE_SUDO "true" }}sudo {{ end }}curl -sSL https://github.com/aelsabbahy/goss/releases/download/{{ .GOSS_VERSION }}/goss-{{ OS }}-{{ ARCH }} -o {{ .INSTALL_PATH }}/goss'
|
||||
- '{{ if eq .REQUIRE_SUDO "true" }}sudo {{ end }}chmod +x {{ .INSTALL_PATH }}/goss'
|
||||
|
||||
docker:deps:dgoss:
|
||||
platforms:
|
||||
- linux
|
||||
- darwin
|
||||
vars:
|
||||
GOSS_VERSION: v0.3.5
|
||||
status:
|
||||
- test -f "{{ .INSTALL_PATH }}/dgoss"
|
||||
cmds:
|
||||
- '{{ if eq .REQUIRE_SUDO "true" }}sudo {{ end }}curl -sSL https://raw.githubusercontent.com/aelsabbahy/goss/{{ .GOSS_VERSION }}/extras/dgoss/dgoss -o {{ .INSTALL_PATH }}/dgoss'
|
||||
- '{{ if eq .REQUIRE_SUDO "true" }}sudo {{ end }}chmod +x {{ .INSTALL_PATH }}/dgoss'
|
||||
|
@ -1,9 +0,0 @@
|
||||
version: '2'
|
||||
tasks:
|
||||
compile:be:
|
||||
cmds:
|
||||
- go run util/version_gen/generator.go 1
|
||||
build:local:
|
||||
dir: cli
|
||||
cmds:
|
||||
- go build -o ../bin/semaphore{{ if eq OS "windows" }}.exe{{ end }}
|
@ -644,6 +644,8 @@ definitions:
|
||||
type: string
|
||||
environment:
|
||||
type: string
|
||||
secret:
|
||||
type: string
|
||||
limit:
|
||||
type: string
|
||||
TaskOutput:
|
||||
|
@ -253,7 +253,6 @@ func RunIntegration(integration db.Integration, project db.Project, r *http.Requ
|
||||
var taskDefinition = db.Task{
|
||||
TemplateID: integration.TemplateID,
|
||||
ProjectID: integration.ProjectID,
|
||||
Debug: true,
|
||||
Environment: environmentJSONString,
|
||||
IntegrationID: &integration.ID,
|
||||
}
|
||||
|
@ -431,7 +431,7 @@ func serveFile(w http.ResponseWriter, r *http.Request, name string) {
|
||||
|
||||
func getSystemInfo(w http.ResponseWriter, r *http.Request) {
|
||||
body := map[string]interface{}{
|
||||
"version": util.Version,
|
||||
"version": util.Version(),
|
||||
"ansible": util.AnsibleVersion(),
|
||||
}
|
||||
|
||||
|
@ -2,7 +2,10 @@ package cmd
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
log "github.com/sirupsen/logrus"
|
||||
"net/http"
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
"github.com/ansible-semaphore/semaphore/api"
|
||||
"github.com/ansible-semaphore/semaphore/api/sockets"
|
||||
"github.com/ansible-semaphore/semaphore/db"
|
||||
@ -12,10 +15,8 @@ import (
|
||||
"github.com/ansible-semaphore/semaphore/util"
|
||||
"github.com/gorilla/context"
|
||||
"github.com/gorilla/handlers"
|
||||
log "github.com/sirupsen/logrus"
|
||||
"github.com/spf13/cobra"
|
||||
"net/http"
|
||||
"os"
|
||||
"strings"
|
||||
)
|
||||
|
||||
var configPath string
|
||||
@ -56,7 +57,7 @@ func runService() {
|
||||
}
|
||||
|
||||
fmt.Printf("Tmp Path (projects home) %v\n", util.Config.TmpPath)
|
||||
fmt.Printf("Semaphore %v\n", util.Version)
|
||||
fmt.Printf("Semaphore %v\n", util.Version())
|
||||
fmt.Printf("Interface %v\n", util.Config.Interface)
|
||||
fmt.Printf("Port %v\n", util.Config.Port)
|
||||
|
||||
|
@ -1,102 +0,0 @@
|
||||
package cmd
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"github.com/ansible-semaphore/semaphore/util"
|
||||
"github.com/google/go-github/github"
|
||||
"github.com/spf13/cobra"
|
||||
"io"
|
||||
"net/http"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"runtime"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
// Adapted from github.com/apex/apex
|
||||
|
||||
// doUpgrade checks for an update, and if available downloads the binary and installs it
|
||||
func doUpgrade() error {
|
||||
updateAvailable, err := util.CheckUpdate()
|
||||
|
||||
if err != nil || updateAvailable == nil {
|
||||
return err
|
||||
}
|
||||
|
||||
asset := findAsset(updateAvailable)
|
||||
if asset == nil {
|
||||
return errors.New("cannot find binary for your system")
|
||||
}
|
||||
|
||||
// create tmp file
|
||||
tmpPath := filepath.Join(os.TempDir(), "semaphore-upgrade")
|
||||
f, err := os.OpenFile(tmpPath, os.O_CREATE|os.O_TRUNC|os.O_RDWR, 0755) //nolint: gas
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// download binary
|
||||
fmt.Printf("downloading %s\n", *asset.BrowserDownloadURL)
|
||||
res, err := http.Get(*asset.BrowserDownloadURL)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
defer res.Body.Close() //nolint: errcheck
|
||||
|
||||
// copy it down
|
||||
_, err = io.Copy(f, res.Body)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// replace it
|
||||
cmdPath := util.FindSemaphore()
|
||||
if len(cmdPath) == 0 {
|
||||
return errors.New("cannot find semaphore binary")
|
||||
}
|
||||
|
||||
fmt.Printf("replacing %s\n", cmdPath)
|
||||
err = os.Rename(tmpPath, cmdPath)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
fmt.Println("visit https://github.com/ansible-semaphore/semaphore/releases for the changelog")
|
||||
go func() {
|
||||
time.Sleep(time.Second * 3)
|
||||
os.Exit(0)
|
||||
}()
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// findAsset returns the binary for this platform.
|
||||
func findAsset(release *github.RepositoryRelease) *github.ReleaseAsset {
|
||||
for _, asset := range release.Assets {
|
||||
suffix := fmt.Sprintf("_%s_%s.tar.gz", runtime.GOOS, runtime.GOARCH)
|
||||
if strings.HasPrefix(*asset.Name, "semaphore_") &&
|
||||
strings.HasSuffix(*asset.Name, suffix) {
|
||||
return &asset
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func init() {
|
||||
rootCmd.AddCommand(upgradeCmd)
|
||||
}
|
||||
|
||||
var upgradeCmd = &cobra.Command{
|
||||
Use: "upgrade",
|
||||
Short: "Upgrade to latest stable version",
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
err := doUpgrade()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
},
|
||||
}
|
@ -2,6 +2,7 @@ package cmd
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/ansible-semaphore/semaphore/util"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
@ -14,6 +15,6 @@ var versionCmd = &cobra.Command{
|
||||
Use: "version",
|
||||
Short: "Print the version of Semaphore",
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
fmt.Println(util.Version)
|
||||
fmt.Println(util.Version())
|
||||
},
|
||||
}
|
||||
}
|
||||
|
@ -8,7 +8,7 @@ func TestObjectToJSON(t *testing.T) {
|
||||
Title: "Test",
|
||||
}
|
||||
s := ObjectToJSON(v)
|
||||
if s == nil || *s != "{\"name\":\"test\",\"title\":\"Test\",\"required\":false,\"type\":\"\",\"description\":\"\"}" {
|
||||
if s == nil || *s != "{\"name\":\"test\",\"title\":\"Test\",\"required\":false,\"type\":\"\",\"description\":\"\",\"values\":null}" {
|
||||
t.Fail()
|
||||
}
|
||||
}
|
||||
@ -27,7 +27,7 @@ func TestObjectToJSON3(t *testing.T) {
|
||||
Title: "Test",
|
||||
}
|
||||
s := ObjectToJSON(v)
|
||||
if s == nil || *s != "{\"name\":\"test\",\"title\":\"Test\",\"required\":false,\"type\":\"\",\"description\":\"\"}" {
|
||||
if s == nil || *s != "{\"name\":\"test\",\"title\":\"Test\",\"required\":false,\"type\":\"\",\"description\":\"\",\"values\":null}" {
|
||||
t.Fail()
|
||||
}
|
||||
}
|
||||
|
@ -26,6 +26,7 @@ type Task struct {
|
||||
Playbook string `db:"playbook" json:"playbook"`
|
||||
Environment string `db:"environment" json:"environment"`
|
||||
Limit string `db:"hosts_limit" json:"limit"`
|
||||
Secret string `db:"-" json:"secret"`
|
||||
|
||||
UserID *int `db:"user_id" json:"user_id"`
|
||||
|
||||
|
@ -21,16 +21,23 @@ const (
|
||||
type SurveyVarType string
|
||||
|
||||
const (
|
||||
SurveyVarStr TemplateType = ""
|
||||
SurveyVarInt TemplateType = "int"
|
||||
SurveyVarStr TemplateType = ""
|
||||
SurveyVarInt TemplateType = "int"
|
||||
SurveyVarEnum TemplateType = "enum"
|
||||
)
|
||||
|
||||
type SurveyVarEnumValue struct {
|
||||
Name string `json:"name"`
|
||||
Value string `json:"value"`
|
||||
}
|
||||
|
||||
type SurveyVar struct {
|
||||
Name string `json:"name"`
|
||||
Title string `json:"title"`
|
||||
Required bool `json:"required"`
|
||||
Type SurveyVarType `json:"type"`
|
||||
Description string `json:"description"`
|
||||
Name string `json:"name"`
|
||||
Title string `json:"title"`
|
||||
Required bool `json:"required"`
|
||||
Type SurveyVarType `json:"type"`
|
||||
Description string `json:"description"`
|
||||
Values []SurveyVarEnumValue `json:"values"`
|
||||
}
|
||||
|
||||
type TemplateFilter struct {
|
||||
|
@ -91,7 +91,7 @@ func (t *AnsibleApp) getRepoPath() string {
|
||||
}
|
||||
|
||||
func (t *AnsibleApp) installRolesRequirements() error {
|
||||
requirementsFilePath := fmt.Sprintf("%s/roles/requirements.yml", t.getRepoPath())
|
||||
requirementsFilePath := path.Join(t.getRepoPath(), "roles", "requirements.yml")
|
||||
requirementsHashFilePath := fmt.Sprintf("%s.md5", requirementsFilePath)
|
||||
|
||||
if _, err := os.Stat(requirementsFilePath); err != nil {
|
||||
@ -126,7 +126,7 @@ func (t *AnsibleApp) GetPlaybookDir() string {
|
||||
}
|
||||
|
||||
func (t *AnsibleApp) installCollectionsRequirements() error {
|
||||
requirementsFilePath := path.Join(t.GetPlaybookDir(), "collections", "requirements.yml")
|
||||
requirementsFilePath := path.Join(t.getRepoPath(), "collections", "requirements.yml")
|
||||
requirementsHashFilePath := fmt.Sprintf("%s.md5", requirementsFilePath)
|
||||
|
||||
if _, err := os.Stat(requirementsFilePath); err != nil {
|
||||
|
@ -31,18 +31,8 @@ func (p AnsiblePlaybook) makeCmd(command string, args []string, environmentVars
|
||||
cmd.Env = append(cmd.Env, *environmentVars...)
|
||||
}
|
||||
|
||||
sensitiveEnvs := []string{
|
||||
"SEMAPHORE_ACCESS_KEY_ENCRYPTION",
|
||||
"SEMAPHORE_ADMIN_PASSWORD",
|
||||
"SEMAPHORE_DB_USER",
|
||||
"SEMAPHORE_DB_NAME",
|
||||
"SEMAPHORE_DB_HOST",
|
||||
"SEMAPHORE_DB_PASS",
|
||||
"SEMAPHORE_LDAP_PASSWORD",
|
||||
}
|
||||
|
||||
// Remove sensitive env variables from cmd process
|
||||
for _, env := range sensitiveEnvs {
|
||||
for _, env := range getSensitiveEnvs() {
|
||||
cmd.Env = append(cmd.Env, env+"=")
|
||||
}
|
||||
|
||||
|
@ -6,6 +6,18 @@ import (
|
||||
"github.com/ansible-semaphore/semaphore/pkg/task_logger"
|
||||
)
|
||||
|
||||
func getSensitiveEnvs() []string {
|
||||
return []string{
|
||||
"SEMAPHORE_ACCESS_KEY_ENCRYPTION",
|
||||
"SEMAPHORE_ADMIN_PASSWORD",
|
||||
"SEMAPHORE_DB_USER",
|
||||
"SEMAPHORE_DB_NAME",
|
||||
"SEMAPHORE_DB_HOST",
|
||||
"SEMAPHORE_DB_PASS",
|
||||
"SEMAPHORE_LDAP_PASSWORD",
|
||||
}
|
||||
}
|
||||
|
||||
type LocalApp interface {
|
||||
SetLogger(logger task_logger.Logger) task_logger.Logger
|
||||
InstallRequirements() error
|
||||
|
131
deployment/compose/README.md
Normal file
131
deployment/compose/README.md
Normal file
@ -0,0 +1,131 @@
|
||||
# Compose
|
||||
|
||||
With the `docker-compose` snippets within this directory you are able to plug
|
||||
different setups of Semaphore UI together. Below you can find some example
|
||||
combinations.
|
||||
|
||||
Some of the snippets define environment variables which could be optionally
|
||||
overwritten if needed.
|
||||
|
||||
## Server
|
||||
|
||||
First of all we need the server definition and we need to decide if we want to
|
||||
build the image dynamically or if we just want to use a released image.
|
||||
|
||||
### Build
|
||||
|
||||
This simply takes the currently cloned source and builds a new image including
|
||||
all local changes.
|
||||
|
||||
```console
|
||||
docker-compose -f deployment/compose/server/base.yml -f deployment/compose/server/build.yml up
|
||||
```
|
||||
|
||||
### Image
|
||||
|
||||
This simply downloads the defined image from DockerHub and starts/configures it
|
||||
properly based on the integrated bootstrapping scripts.
|
||||
|
||||
```console
|
||||
docker-compose -f deployment/compose/server/base.yml -f deployment/compose/server/image.yml up
|
||||
```
|
||||
|
||||
### Config
|
||||
|
||||
If you want to provide a custom `config.json` file to add options which are not
|
||||
exposed as environment variables you could add this snippet which sources the
|
||||
file from the current working directory.
|
||||
|
||||
```console
|
||||
docker-compose <server from above> -f deployment/compose/server/config.yml up
|
||||
```
|
||||
|
||||
## Runner
|
||||
|
||||
If you want to try the remote runner functionality of Semaphore you could just
|
||||
add this snippet to get a runner up and connected to semaphore. Similar to the
|
||||
examples above for the server you got different options like building the runner
|
||||
from the source or using our prebuilt images.
|
||||
|
||||
### Build
|
||||
|
||||
This simply takes the currently cloned source and builds a new image including
|
||||
all local changes.
|
||||
|
||||
```console
|
||||
docker-compose <server from above> -f deployment/compose/runner/base.yml -f deployment/compose/runner/build.yml up
|
||||
```
|
||||
|
||||
### Image
|
||||
|
||||
This simply downloads the defined image from DockerHub and starts/configures it
|
||||
properly based on the integrated bootstrapping scripts.
|
||||
|
||||
```console
|
||||
docker-compose <server from above> -f deployment/compose/runner/base.yml -f deployment/compose/runner/image.yml up
|
||||
```
|
||||
|
||||
### Config
|
||||
|
||||
If you want to provide a custom `config.json` file to add options which are not
|
||||
exposed as environment variables you could add this snippet which sources the
|
||||
file from the current working directory.
|
||||
|
||||
```console
|
||||
docker-compose <runner from above> -f deployment/compose/runner/config.yml up
|
||||
```
|
||||
|
||||
## Database
|
||||
|
||||
After deciding the base of it you should choose one of the supported databases.
|
||||
Here we got currently the following options so far.
|
||||
|
||||
### SQLite
|
||||
|
||||
This simply configures a named volume for the SQLite storage used as a database
|
||||
backend.
|
||||
|
||||
```console
|
||||
docker-compose <server/runner from above> -f deployment/compose/store/sqlite.yml up
|
||||
```
|
||||
|
||||
### BoltDB
|
||||
|
||||
This simply configures a named volume for the BoltDB storage used as a database
|
||||
backend.
|
||||
|
||||
```console
|
||||
docker-compose <server/runner from above> -f deployment/compose/store/boltdb.yml up
|
||||
```
|
||||
|
||||
### MariaDB
|
||||
|
||||
This simply starts an additional container for a MariaDB instance used as a
|
||||
database backend including the required credentials.
|
||||
|
||||
```console
|
||||
docker-compose <server/runner from above> -f deployment/compose/store/mariadb.yml up
|
||||
```
|
||||
|
||||
### MySQL
|
||||
|
||||
This simply starts an additional container for a MySQL instance used as a
|
||||
database backend including the required credentials.
|
||||
|
||||
```console
|
||||
docker-compose <server/runner from above> -f deployment/compose/store/mysql.yml up
|
||||
```
|
||||
|
||||
### PostgreSQL
|
||||
|
||||
This simply starts an additional container for a PostgreSQL instance used as a
|
||||
database backend including the required credentials.
|
||||
|
||||
```console
|
||||
docker-compose <server/runner from above> -f deployment/compose/store/postgres.yml up
|
||||
```
|
||||
|
||||
## Cleanup
|
||||
|
||||
After playing with the setup you are able to stop the whole setup by just
|
||||
replacing `up` at the end of the command with `down`.
|
25
deployment/compose/dredd/base.yml
Normal file
25
deployment/compose/dredd/base.yml
Normal file
@ -0,0 +1,25 @@
|
||||
version: "3.4"
|
||||
|
||||
volumes:
|
||||
dredd:
|
||||
|
||||
services:
|
||||
server:
|
||||
environment:
|
||||
SEMAPHORE_ADMIN_PASSWORD: password
|
||||
SEMAPHORE_ADMIN_NAME: Developer
|
||||
SEMAPHORE_ADMIN_EMAIL: admin@localhost
|
||||
SEMAPHORE_ADMIN: admin
|
||||
SEMAPHORE_WEB_ROOT: http://0.0.0.0:3000
|
||||
|
||||
dredd:
|
||||
build:
|
||||
context: ../../../
|
||||
dockerfile: deployment/docker/dredd/Dockerfile
|
||||
command:
|
||||
- --config
|
||||
- .dredd/dredd.docker.yml
|
||||
environment:
|
||||
SEMAPHORE_ACCESS_KEY_ENCRYPTION: ${SEMAPHORE_ACCESS_KEY_ENCRYPTION:-IlRqgrrO5Gp27MlWakDX1xVrPv4jhoUx+ARY+qGyDxQ=}
|
||||
volumes:
|
||||
- dredd:/data
|
9
deployment/compose/dredd/boltdb.yml
Normal file
9
deployment/compose/dredd/boltdb.yml
Normal file
@ -0,0 +1,9 @@
|
||||
version: "3.4"
|
||||
|
||||
services:
|
||||
dredd:
|
||||
environment:
|
||||
SEMAPHORE_DB_DIALECT: bolt
|
||||
SEMAPHORE_DB_CONFIG: '{"host": "/data/database.boltdb"}'
|
||||
depends_on:
|
||||
- server
|
10
deployment/compose/dredd/mariadb.yml
Normal file
10
deployment/compose/dredd/mariadb.yml
Normal file
@ -0,0 +1,10 @@
|
||||
version: "3.4"
|
||||
|
||||
services:
|
||||
dredd:
|
||||
environment:
|
||||
SEMAPHORE_DB_DIALECT: mysql
|
||||
SEMAPHORE_DB_CONFIG: '{"host": "db:3306","user": "semaphore","pass": "semaphore","name": "semaphore"}'
|
||||
depends_on:
|
||||
- server
|
||||
- db
|
10
deployment/compose/dredd/mysql.yml
Normal file
10
deployment/compose/dredd/mysql.yml
Normal file
@ -0,0 +1,10 @@
|
||||
version: "3.4"
|
||||
|
||||
services:
|
||||
dredd:
|
||||
environment:
|
||||
SEMAPHORE_DB_DIALECT: mysql
|
||||
SEMAPHORE_DB_CONFIG: '{"host": "db:3306","user": "semaphore","pass": "semaphore","name": "semaphore"}'
|
||||
depends_on:
|
||||
- server
|
||||
- db
|
10
deployment/compose/dredd/postgres.yml
Normal file
10
deployment/compose/dredd/postgres.yml
Normal file
@ -0,0 +1,10 @@
|
||||
version: "3.4"
|
||||
|
||||
services:
|
||||
dredd:
|
||||
environment:
|
||||
SEMAPHORE_DB_DIALECT: postgres
|
||||
SEMAPHORE_DB_CONFIG: '{"host": "db:5432","user": "semaphore","pass": "semaphore","name": "semaphore","options": {"sslmode": "disable"}}'
|
||||
depends_on:
|
||||
- server
|
||||
- db
|
9
deployment/compose/dredd/sqlite.yml
Normal file
9
deployment/compose/dredd/sqlite.yml
Normal file
@ -0,0 +1,9 @@
|
||||
version: "3.4"
|
||||
|
||||
services:
|
||||
dredd:
|
||||
environment:
|
||||
SEMAPHORE_DB_DIALECT: sqlite
|
||||
SEMAPHORE_DB_CONFIG: '{"host": "/data/database.sqlite3"}'
|
||||
depends_on:
|
||||
- server
|
13
deployment/compose/runner/base.yml
Normal file
13
deployment/compose/runner/base.yml
Normal file
@ -0,0 +1,13 @@
|
||||
version: "3.4"
|
||||
|
||||
services:
|
||||
runner:
|
||||
image: docker.io/semaphoreui/runner:${SEMAPHORE_VERSION:-latest}
|
||||
restart: always
|
||||
environment:
|
||||
SEMAPHORE_RUNNER_API_URL: ${SEMAPHORE_RUNNER_API_URL:-http://server:3000/api}
|
||||
SEMAPHORE_RUNNER_REGISTRATION_TOKEN: ${SEMAPHORE_RUNNER_REGISTRATION_TOKEN:-H1wDyorbg6gTSwJlVwle2Fne}
|
||||
|
||||
server:
|
||||
environment:
|
||||
SEMAPHORE_RUNNER_REGISTRATION_TOKEN: ${SEMAPHORE_RUNNER_REGISTRATION_TOKEN:-H1wDyorbg6gTSwJlVwle2Fne}
|
7
deployment/compose/runner/build.yml
Normal file
7
deployment/compose/runner/build.yml
Normal file
@ -0,0 +1,7 @@
|
||||
version: "3.4"
|
||||
|
||||
services:
|
||||
runner:
|
||||
build:
|
||||
context: ../../../
|
||||
dockerfile: deployment/docker/runner/Dockerfile
|
6
deployment/compose/runner/config.yml
Normal file
6
deployment/compose/runner/config.yml
Normal file
@ -0,0 +1,6 @@
|
||||
version: "3.4"
|
||||
|
||||
services:
|
||||
runner:
|
||||
volumes:
|
||||
- ${SEMAPHORE_RUNNER_LOCAL_CONFIG:-runner.json}:/etc/semaphore/config.json:Z
|
20
deployment/compose/server/base.yml
Normal file
20
deployment/compose/server/base.yml
Normal file
@ -0,0 +1,20 @@
|
||||
version: "3.4"
|
||||
|
||||
volumes:
|
||||
server:
|
||||
|
||||
services:
|
||||
server:
|
||||
image: docker.io/semaphoreui/semaphore:${SEMAPHORE_VERSION:-latest}
|
||||
restart: always
|
||||
environment:
|
||||
SEMAPHORE_ADMIN_NAME: ${SEMAPHORE_ADMIN_NAME:-Admin}
|
||||
SEMAPHORE_ADMIN: ${SEMAPHORE_ADMIN_USERNAME:-admin}
|
||||
SEMAPHORE_ADMIN_PASSWORD: ${SEMAPHORE_ADMIN_PASSWORD:-p455w0rd}
|
||||
SEMAPHORE_ADMIN_EMAIL: ${SEMAPHORE_ADMIN_EMAIL:-admin@localhost}
|
||||
SEMAPHORE_WEB_ROOT: ${SEMAPHORE_WEB_ROOT:-http://0.0.0.0:3000}
|
||||
SEMAPHORE_ACCESS_KEY_ENCRYPTION: ${SEMAPHORE_ACCESS_KEY_ENCRYPTION:-IlRqgrrO5Gp27MlWakDX1xVrPv4jhoUx+ARY+qGyDxQ=}
|
||||
volumes:
|
||||
- server:/var/lib/semaphore
|
||||
ports:
|
||||
- "3000:3000"
|
7
deployment/compose/server/build.yml
Normal file
7
deployment/compose/server/build.yml
Normal file
@ -0,0 +1,7 @@
|
||||
version: "3.4"
|
||||
|
||||
services:
|
||||
server:
|
||||
build:
|
||||
context: ../../../
|
||||
dockerfile: deployment/docker/server/Dockerfile
|
6
deployment/compose/server/config.yml
Normal file
6
deployment/compose/server/config.yml
Normal file
@ -0,0 +1,6 @@
|
||||
version: "3.4"
|
||||
|
||||
services:
|
||||
server:
|
||||
volumes:
|
||||
- ${SEMAPHORE_RUNNER_LOCAL_CONFIG:-config.json}:/etc/semaphore/config.json:Z
|
12
deployment/compose/store/boltdb.yml
Normal file
12
deployment/compose/store/boltdb.yml
Normal file
@ -0,0 +1,12 @@
|
||||
version: "3.4"
|
||||
|
||||
volumes:
|
||||
boltdb:
|
||||
|
||||
services:
|
||||
server:
|
||||
environment:
|
||||
SEMAPHORE_DB_DIALECT: bolt
|
||||
SEMAPHORE_DB_PATH: /var/lib/database
|
||||
volumes:
|
||||
- boltdb:/var/lib/database
|
31
deployment/compose/store/local.yml
Normal file
31
deployment/compose/store/local.yml
Normal file
@ -0,0 +1,31 @@
|
||||
version: "3.4"
|
||||
|
||||
volumes:
|
||||
mariadb:
|
||||
postgres:
|
||||
|
||||
services:
|
||||
mariadb:
|
||||
image: mariadb:10.8
|
||||
restart: always
|
||||
environment:
|
||||
MARIADB_ROOT_PASSWORD: root
|
||||
MARIADB_USER: semaphore
|
||||
MARIADB_PASSWORD: semaphore
|
||||
MARIADB_DATABASE: semaphore
|
||||
volumes:
|
||||
- mariadb:/var/lib/mysql
|
||||
ports:
|
||||
- 3306:3306
|
||||
|
||||
postgres:
|
||||
image: postgres:14.3
|
||||
restart: always
|
||||
environment:
|
||||
POSTGRES_USER: semaphore
|
||||
POSTGRES_PASSWORD: semaphore
|
||||
POSTGRES_DB: semaphore
|
||||
volumes:
|
||||
- postgres:/var/lib/postgresql
|
||||
ports:
|
||||
- 5432:5432
|
27
deployment/compose/store/mariadb.yml
Normal file
27
deployment/compose/store/mariadb.yml
Normal file
@ -0,0 +1,27 @@
|
||||
version: "3.4"
|
||||
|
||||
volumes:
|
||||
mariadb:
|
||||
|
||||
services:
|
||||
server:
|
||||
environment:
|
||||
SEMAPHORE_DB_DIALECT: mysql
|
||||
SEMAPHORE_DB_HOST: db
|
||||
SEMAPHORE_DB_PORT: 3306
|
||||
SEMAPHORE_DB_USER: ${MARIADB_USERNAME:-semaphore}
|
||||
SEMAPHORE_DB_PASS: ${MARIADB_PASSWORD:-semaphore}
|
||||
SEMAPHORE_DB: ${MARIADB_DATABASE:-semaphore}
|
||||
depends_on:
|
||||
- db
|
||||
|
||||
db:
|
||||
image: mariadb:10.8
|
||||
restart: always
|
||||
environment:
|
||||
MARIADB_ROOT_PASSWORD: ${MARIADB_ROOT:-root}
|
||||
MARIADB_USER: ${MARIADB_USERNAME:-semaphore}
|
||||
MARIADB_PASSWORD: ${MARIADB_PASSWORD:-semaphore}
|
||||
MARIADB_DATABASE: ${MARIADB_DATABASE:-semaphore}
|
||||
volumes:
|
||||
- mariadb:/var/lib/mysql
|
27
deployment/compose/store/mysql.yml
Normal file
27
deployment/compose/store/mysql.yml
Normal file
@ -0,0 +1,27 @@
|
||||
version: "3.4"
|
||||
|
||||
volumes:
|
||||
mysql:
|
||||
|
||||
services:
|
||||
server:
|
||||
environment:
|
||||
SEMAPHORE_DB_DIALECT: mysql
|
||||
SEMAPHORE_DB_HOST: db
|
||||
SEMAPHORE_DB_PORT: 3306
|
||||
SEMAPHORE_DB_USER: ${MYSQL_USERNAME:-semaphore}
|
||||
SEMAPHORE_DB_PASS: ${MYSQL_PASSWORD:-semaphore}
|
||||
SEMAPHORE_DB: ${MYSQL_DATABASE:-semaphore}
|
||||
depends_on:
|
||||
- db
|
||||
|
||||
db:
|
||||
image: mysql:8.0
|
||||
restart: always
|
||||
environment:
|
||||
MYSQL_ROOT_PASSWORD: ${MYSQL_ROOT:-root}
|
||||
MYSQL_USER: ${MYSQL_USERNAME:-semaphore}
|
||||
MYSQL_PASSWORD: ${MYSQL_PASSWORD:-semaphore}
|
||||
MYSQL_DATABASE: ${MYSQL_DATABASE:-semaphore}
|
||||
volumes:
|
||||
- mysql:/var/lib/mysql
|
26
deployment/compose/store/postgres.yml
Normal file
26
deployment/compose/store/postgres.yml
Normal file
@ -0,0 +1,26 @@
|
||||
version: "3.4"
|
||||
|
||||
volumes:
|
||||
postgres:
|
||||
|
||||
services:
|
||||
server:
|
||||
environment:
|
||||
SEMAPHORE_DB_DIALECT: postgres
|
||||
SEMAPHORE_DB_HOST: db
|
||||
SEMAPHORE_DB_PORT: 5432
|
||||
SEMAPHORE_DB_USER: ${POSTGRES_USERNAME:-semaphore}
|
||||
SEMAPHORE_DB_PASS: ${POSTGRES_PASSWORD:-semaphore}
|
||||
SEMAPHORE_DB: ${POSTGRES_DATABASE:-semaphore}
|
||||
depends_on:
|
||||
- db
|
||||
|
||||
db:
|
||||
image: postgres:14.3
|
||||
restart: always
|
||||
environment:
|
||||
POSTGRES_USER: ${POSTGRES_USERNAME:-semaphore}
|
||||
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:-semaphore}
|
||||
POSTGRES_DB: ${POSTGRES_DATABASE:-semaphore}
|
||||
volumes:
|
||||
- postgres:/var/lib/postgresql
|
12
deployment/compose/store/sqlite.yml
Normal file
12
deployment/compose/store/sqlite.yml
Normal file
@ -0,0 +1,12 @@
|
||||
version: "3.4"
|
||||
|
||||
volumes:
|
||||
sqlite:
|
||||
|
||||
services:
|
||||
server:
|
||||
environment:
|
||||
SEMAPHORE_DB_DIALECT: sqlite
|
||||
SEMAPHORE_DB_PATH: /var/lib/database
|
||||
volumes:
|
||||
- sqlite:/var/lib/database
|
60
deployment/docker/README.md
Normal file
60
deployment/docker/README.md
Normal file
@ -0,0 +1,60 @@
|
||||
# Docker
|
||||
|
||||
Generally we are building production-grade images for each tag, latest and even
|
||||
for the development branch which will be pushed to [DockerHub][dockerhub]. If
|
||||
you still need to build your own image you can easily do that, you just need
|
||||
install [Docker][docker] and [Task][gotask] on your system.
|
||||
|
||||
If you just want to use our pre-built images please follow the instructions on
|
||||
our [documentation][documentation].
|
||||
|
||||
If you want to use [docker-compose][dockercompose] to start Semaphore you could
|
||||
also read about it on our [documentation][documentation] or take a look at our
|
||||
collection of [snippets][snippets] within this repository.
|
||||
|
||||
## Build
|
||||
|
||||
We have prepared multiple tasks to build an publish container images, including
|
||||
tasks to verify the image contains all required tools:
|
||||
|
||||
```console
|
||||
task docker:build
|
||||
task docker:push
|
||||
```
|
||||
|
||||
If you want to customize the image names or if you want to use [Podman][podman]
|
||||
instead of [Docker][docker] you are able to provide some set of environment
|
||||
variables to the [Task][gotask] command:
|
||||
|
||||
* `DOCKER_ORG`: Define a custom organization for the image, defaults to `semaphoreui`
|
||||
* `DOCKER_SERVER`: Define a different name for the server image, defaults to `semaphore`
|
||||
* `DOCKER_RUNNER`: Define a different name for the runner image, defaults to `runner`
|
||||
* `DOCKER_CMD`: Use another command to build the image, defaults to `docker`
|
||||
|
||||
## Test
|
||||
|
||||
We defined tasks to handle some linting and to verify the images contain the
|
||||
tools and binaries that are required to run Semaphore. Here we are using
|
||||
[Hadolint][hadolint] to ensure we are mostly following best-practices and
|
||||
[Goss][goss] which is using a configuration file to define the requirements.
|
||||
|
||||
To install the required tools you also need to install [Golang][golang] on your
|
||||
system, the installation of [Golang][golang] is not covered by us.
|
||||
|
||||
The installation of the dependencies can be customized by providing environment
|
||||
variables for `INSTALL_PATH` (`/usr/local/bin`) and `REQUIRE_SUDO` (true).
|
||||
|
||||
```console
|
||||
task docker:test
|
||||
```
|
||||
|
||||
[dockerhub]: https://hub.docker.com/r/semaphoreui/semaphore
|
||||
[docker]: https://docs.docker.com/engine/install/
|
||||
[podman]: https://podman.io/docs/installation
|
||||
[gotask]: https://taskfile.dev/installation/
|
||||
[dockercompose]: https://docs.docker.com/compose/
|
||||
[golang]: https://go.dev/doc/install
|
||||
[hadolint]: https://github.com/hadolint/hadolint
|
||||
[goss]: https://github.com/goss-org/goss
|
||||
[snippets]: ../compose/README.md
|
||||
[documentation]: https://docs.semui.co/administration-guide/installation
|
@ -1,83 +0,0 @@
|
||||
# Docker Deployments
|
||||
|
||||
Production images for each tag, latest and the development branch will be pushed to [docker hub](https://hub.docker.com/r/semaphoreui/semaphore).
|
||||
To build images locally see the contexts included here and use the `d` and `dc` tasks in the root Taskfile.yml to help with building and running.
|
||||
|
||||
## Contexts
|
||||
|
||||
### Prod
|
||||
|
||||
To build a production image you should run
|
||||
|
||||
context=prod task docker:build
|
||||
|
||||
this will create an image called `semaphoreui/semaphore:latest` which will be compiled from the currently checked out code
|
||||
|
||||
This image is run as non root user 1001 (for PaaS systems such as openshift) and is build on alpine with added glibc.
|
||||
With ansible etc... installed in the container it is ~283MiB in size.
|
||||
|
||||
You will need to provide environmental variables so that the configuration can be built correctly for your environment.
|
||||
See `docker-compose.yml` for an example, or look at `../common/entrypoint` to see which variables are available
|
||||
|
||||
If you want to build an image with a custom tag you can optionally pass a tag to the command
|
||||
|
||||
context=prod tag=mybranch task docker:build
|
||||
|
||||
#### Example Configuration
|
||||
|
||||
To run Semaphore in a simple production-like docker configuration run the following command:
|
||||
|
||||
task dc:prod
|
||||
|
||||
You can then access Semaphore directly from the url http://localhost:8081/
|
||||
|
||||
#### SSL Termination Using Nginx
|
||||
|
||||
Generate a cert, ca cert, and key file and place into `prod/proxy/cert/` with
|
||||
these names:
|
||||
|
||||
* `cert.pem`
|
||||
* `privkey.pem`
|
||||
* `fullchain.pem`
|
||||
|
||||
(I've used letsencrypt generated certs with success.)
|
||||
|
||||
Run `task dc:prod` and your Semaphore instance will then be at the url
|
||||
https://localhost:8443
|
||||
|
||||
If you do not add certificates the container will create self-signed certs instead
|
||||
|
||||
## Dev
|
||||
|
||||
To start a development start you could run
|
||||
```
|
||||
context=dev task dc:up
|
||||
```
|
||||
The development stack will run `task watch` by default and `dc:up` will volume link the application in to the container.
|
||||
Without `dc:up` the application will run the version of the application which existed at image build time.
|
||||
|
||||
The development container is based on [micro-golang](https://github.com/twhiston/micro-golang)'s test base image
|
||||
which contains the go toolchain and glibc in alpine.
|
||||
|
||||
Because the test image links your local volume it expects that you have run `task deps` and `task compile` locally
|
||||
as necessary to make the application usable.
|
||||
|
||||
## CI
|
||||
|
||||
This context is a proxyless stack used to test the API in the ci. Essentially it just installs the app, adds a few bootstrapping files
|
||||
and starts up so that dredd can be run against it. This should not be used in production as it does not remove the build toolchain,
|
||||
or source code.
|
||||
It is more advisable to use the dev context locally as it volume links the application directory and defaults to the watch task.
|
||||
|
||||
## Convenience Functions
|
||||
|
||||
### dc:dev
|
||||
|
||||
`dc:dev` rebuilds the development images and runs a development stack, with the semaphore root as a volume link
|
||||
This allows you to work inside the container with live code. The container has all the tools you need to build and test semaphore
|
||||
|
||||
### dc:prod
|
||||
|
||||
`dc:prod` rebuilds the production example images and starts the production-like stack.
|
||||
This will compile the application for the currently checked out code but will not leave build tools or source in the container.
|
||||
Therefore file changes will result in needing a rebuild.
|
@ -1,42 +0,0 @@
|
||||
FROM golang:1.21-alpine3.18
|
||||
|
||||
ENV SEMAPHORE_VERSION="development" SEMAPHORE_ARCH="linux_amd64" \
|
||||
SEMAPHORE_CONFIG_PATH="${SEMAPHORE_CONFIG_PATH:-/etc/semaphore}" \
|
||||
APP_ROOT="/go/src/github.com/ansible-semaphore/semaphore/"
|
||||
|
||||
# hadolint ignore=DL3013
|
||||
RUN apk add --no-cache gcc g++ sshpass git mysql-client python3 py3-pip py-openssl openssl ca-certificates curl curl-dev openssh-client-default tini nodejs npm bash rsync tzdata zip unzip tar && \
|
||||
apk --update add --virtual build-dependencies python3-dev libffi-dev openssl-dev build-base &&\
|
||||
rm -rf /var/cache/apk/*
|
||||
|
||||
RUN gcc --version
|
||||
|
||||
RUN pip3 install --upgrade pip cffi && \
|
||||
pip3 install ansible &&\
|
||||
apk del build-dependencies
|
||||
|
||||
RUN adduser -D -u 1002 -g 0 semaphore && \
|
||||
mkdir -p /go/src/github.com/ansible-semaphore/semaphore && \
|
||||
mkdir -p /tmp/semaphore && \
|
||||
mkdir -p /etc/semaphore && \
|
||||
mkdir -p /var/lib/semaphore && \
|
||||
chown -R semaphore:0 /go && \
|
||||
chown -R semaphore:0 /tmp/semaphore && \
|
||||
chown -R semaphore:0 /etc/semaphore && \
|
||||
chown -R semaphore:0 /var/lib/semaphore && \
|
||||
ssh-keygen -t rsa -q -f "/root/.ssh/id_rsa" -N "" && \
|
||||
ssh-keyscan -H github.com > /root/.ssh/known_hosts
|
||||
|
||||
RUN cd $(go env GOPATH) && go install github.com/go-task/task/v3/cmd/task@latest
|
||||
|
||||
RUN git config --global --add safe.directory /go/src/github.com/ansible-semaphore/semaphore
|
||||
|
||||
# Copy in app source
|
||||
WORKDIR ${APP_ROOT}
|
||||
COPY . ${APP_ROOT}
|
||||
RUN deployment/docker/ci/bin/install
|
||||
|
||||
USER semaphore
|
||||
EXPOSE 3000
|
||||
ENTRYPOINT ["/usr/local/bin/semaphore-wrapper"]
|
||||
CMD ["./bin/semaphore", "server", "--config", "/etc/semaphore/config.json"]
|
@ -1,15 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
echo "--> Turn off StrictKeyChecking"
|
||||
cat > /etc/ssh/ssh_config <<EOF
|
||||
Host *
|
||||
StrictHostKeyChecking no
|
||||
UserKnownHostsFile=/dev/null
|
||||
EOF
|
||||
|
||||
echo "--> Install Semaphore entrypoint wrapper script"
|
||||
cp ./deployment/docker/common/semaphore-wrapper /usr/local/bin/semaphore-wrapper
|
||||
cp ./deployment/docker/common/runner-wrapper /usr/local/bin/runner-wrapper
|
||||
task deps
|
||||
task compile
|
||||
task build:local GOOS= GOARCH=
|
@ -1,38 +0,0 @@
|
||||
version: '2'
|
||||
|
||||
volumes:
|
||||
data:
|
||||
|
||||
services:
|
||||
semaphore_ci:
|
||||
image: semaphoreui/semaphore:ci-compose
|
||||
build:
|
||||
context: ./../../../
|
||||
dockerfile: ./deployment/docker/ci/Dockerfile
|
||||
environment:
|
||||
SEMAPHORE_DB_DIALECT: bolt
|
||||
SEMAPHORE_ADMIN_PASSWORD: password
|
||||
SEMAPHORE_ADMIN_NAME: "Developer"
|
||||
SEMAPHORE_ADMIN_EMAIL: admin@localhost
|
||||
SEMAPHORE_ADMIN: admin
|
||||
SEMAPHORE_WEB_ROOT: http://0.0.0.0:3000
|
||||
SEMAPHORE_ACCESS_KEY_ENCRYPTION: "IlRqgrrO5Gp27MlWakDX1xVrPv4jhoUx+ARY+qGyDxQ="
|
||||
ports:
|
||||
- "3000:3000"
|
||||
volumes:
|
||||
- data:/var/lib/semaphore
|
||||
|
||||
dredd:
|
||||
image: semaphoreui/dredd:ci
|
||||
command: [ "--config", ".dredd/dredd.yml" ]
|
||||
environment:
|
||||
SEMAPHORE_ACCESS_KEY_ENCRYPTION: "IlRqgrrO5Gp27MlWakDX1xVrPv4jhoUx+ARY+qGyDxQ="
|
||||
SEMAPHORE_DB_DIALECT: bolt
|
||||
build:
|
||||
context: ./../../../
|
||||
dockerfile: ./deployment/docker/ci/dredd.Dockerfile
|
||||
depends_on:
|
||||
- semaphore_ci
|
||||
volumes:
|
||||
- data:/data
|
||||
|
@ -1,49 +0,0 @@
|
||||
version: '2'
|
||||
|
||||
services:
|
||||
mysql:
|
||||
image: mysql:5.6
|
||||
environment:
|
||||
MYSQL_RANDOM_ROOT_PASSWORD: 'yes'
|
||||
MYSQL_DATABASE: semaphore
|
||||
MYSQL_USER: semaphore
|
||||
MYSQL_PASSWORD: semaphore
|
||||
ports:
|
||||
- "3306:3306"
|
||||
|
||||
semaphore_ci:
|
||||
image: semaphoreui/semaphore:ci-compose
|
||||
build:
|
||||
context: ./../../../
|
||||
dockerfile: ./deployment/docker/ci/Dockerfile
|
||||
environment:
|
||||
SEMAPHORE_DB_DIALECT: mysql
|
||||
SEMAPHORE_DB_USER: semaphore
|
||||
SEMAPHORE_DB_PASS: semaphore
|
||||
SEMAPHORE_DB_HOST: mysql
|
||||
SEMAPHORE_DB_PORT: 3306
|
||||
SEMAPHORE_DB: semaphore
|
||||
SEMAPHORE_ADMIN_PASSWORD: password
|
||||
SEMAPHORE_ADMIN_NAME: "Developer"
|
||||
SEMAPHORE_ADMIN_EMAIL: admin@localhost
|
||||
SEMAPHORE_ADMIN: admin
|
||||
SEMAPHORE_WEB_ROOT: http://0.0.0.0:3000
|
||||
SEMAPHORE_ACCESS_KEY_ENCRYPTION: "IlRqgrrO5Gp27MlWakDX1xVrPv4jhoUx+ARY+qGyDxQ="
|
||||
ports:
|
||||
- "3000:3000"
|
||||
depends_on:
|
||||
- mysql
|
||||
|
||||
dredd:
|
||||
image: ansiblesemaphore/dredd:ci
|
||||
command: ["--config", ".dredd/dredd.yml"]
|
||||
environment:
|
||||
SEMAPHORE_ACCESS_KEY_ENCRYPTION: "IlRqgrrO5Gp27MlWakDX1xVrPv4jhoUx+ARY+qGyDxQ="
|
||||
SEMAPHORE_DB_DIALECT: mysql
|
||||
build:
|
||||
context: ./../../../
|
||||
dockerfile: ./deployment/docker/ci/dredd.Dockerfile
|
||||
depends_on:
|
||||
- semaphore_ci
|
||||
- mysql
|
||||
|
@ -1,48 +0,0 @@
|
||||
version: '2'
|
||||
|
||||
services:
|
||||
postgres:
|
||||
image: postgres:14
|
||||
environment:
|
||||
POSTGRES_USER: semaphore
|
||||
POSTGRES_PASSWORD: semaphore
|
||||
POSTGRES_DB: semaphore
|
||||
ports:
|
||||
- "5432:5432"
|
||||
|
||||
semaphore_ci:
|
||||
image: semaphoreui/semaphore:ci-compose
|
||||
build:
|
||||
context: ./../../../
|
||||
dockerfile: ./deployment/docker/ci/Dockerfile
|
||||
environment:
|
||||
SEMAPHORE_DB_DIALECT: postgres
|
||||
SEMAPHORE_DB_USER: semaphore
|
||||
SEMAPHORE_DB_PASS: semaphore
|
||||
SEMAPHORE_DB_HOST: postgres
|
||||
SEMAPHORE_DB_PORT: 5432
|
||||
SEMAPHORE_DB: semaphore
|
||||
SEMAPHORE_ADMIN_PASSWORD: password
|
||||
SEMAPHORE_ADMIN_NAME: "Developer"
|
||||
SEMAPHORE_ADMIN_EMAIL: admin@localhost
|
||||
SEMAPHORE_ADMIN: admin
|
||||
SEMAPHORE_WEB_ROOT: http://0.0.0.0:3000
|
||||
SEMAPHORE_ACCESS_KEY_ENCRYPTION: "IlRqgrrO5Gp27MlWakDX1xVrPv4jhoUx+ARY+qGyDxQ="
|
||||
ports:
|
||||
- "3000:3000"
|
||||
depends_on:
|
||||
- postgres
|
||||
|
||||
dredd:
|
||||
image: ansiblesemaphore/dredd:ci
|
||||
command: ["--config", ".dredd/dredd.yml"]
|
||||
environment:
|
||||
SEMAPHORE_ACCESS_KEY_ENCRYPTION: "IlRqgrrO5Gp27MlWakDX1xVrPv4jhoUx+ARY+qGyDxQ="
|
||||
SEMAPHORE_DB_DIALECT: postgres
|
||||
build:
|
||||
context: ./../../../
|
||||
dockerfile: ./deployment/docker/ci/dredd.Dockerfile
|
||||
depends_on:
|
||||
- semaphore_ci
|
||||
- postgres
|
||||
|
@ -1,27 +0,0 @@
|
||||
FROM golang:1.21-alpine3.18 as golang
|
||||
|
||||
RUN apk add --no-cache curl git
|
||||
|
||||
# We need the source and task to compile the hooks
|
||||
COPY . /semaphore/
|
||||
|
||||
RUN (cd /usr && curl -sL https://taskfile.dev/install.sh | sh)
|
||||
WORKDIR /semaphore
|
||||
RUN task deps:tools && task deps:be && task compile:be && task compile:api:hooks
|
||||
|
||||
FROM apiaryio/dredd:13.0.0 as dredd
|
||||
|
||||
RUN apk add --no-cache bash go git
|
||||
|
||||
RUN go get github.com/snikch/goodman/cmd/goodman
|
||||
|
||||
COPY --from=golang /semaphore /semaphore
|
||||
|
||||
WORKDIR /semaphore
|
||||
|
||||
COPY deployment/docker/ci/dredd/entrypoint /usr/local/bin
|
||||
COPY deployment/docker/ci/dredd/gen-config-bolt /usr/local/bin
|
||||
COPY deployment/docker/ci/dredd/gen-config-mysql /usr/local/bin
|
||||
COPY deployment/docker/ci/dredd/gen-config-postgres /usr/local/bin
|
||||
|
||||
ENTRYPOINT ["/usr/local/bin/entrypoint"]
|
@ -1,17 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
set -e
|
||||
|
||||
echo "---> Add Config"
|
||||
|
||||
/usr/local/bin/gen-config-${SEMAPHORE_DB_DIALECT} > /semaphore/.dredd/config.json
|
||||
|
||||
echo "---> Waiting for semaphore"
|
||||
while ! nc -z semaphore_ci 3000; do
|
||||
sleep 1
|
||||
done
|
||||
|
||||
echo "---> Run Dredd"
|
||||
# We do this because otherwise it can fail out
|
||||
sleep 5
|
||||
dredd $@
|
@ -1,11 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
cat <<EOF
|
||||
{
|
||||
"bolt": {
|
||||
"host": "/data/database.boltdb"
|
||||
},
|
||||
"dialect": "bolt",
|
||||
"access_key_encryption": "${SEMAPHORE_ACCESS_KEY_ENCRYPTION}"
|
||||
}
|
||||
EOF
|
@ -1,15 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
cat <<EOF
|
||||
{
|
||||
"mysql": {
|
||||
"host": "mysql:3306",
|
||||
"user": "semaphore",
|
||||
"pass": "semaphore",
|
||||
"name": "semaphore"
|
||||
},
|
||||
"dialect": "mysql",
|
||||
"access_key_encryption": "${SEMAPHORE_ACCESS_KEY_ENCRYPTION}"
|
||||
}
|
||||
EOF
|
||||
|
@ -1,17 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
cat <<EOF
|
||||
{
|
||||
"postgres": {
|
||||
"host": "postgres:5432",
|
||||
"user": "semaphore",
|
||||
"pass": "semaphore",
|
||||
"name": "semaphore",
|
||||
"options": {
|
||||
"sslmode": "disable"
|
||||
}
|
||||
},
|
||||
"dialect": "postgres",
|
||||
"access_key_encryption": "${SEMAPHORE_ACCESS_KEY_ENCRYPTION}"
|
||||
}
|
||||
EOF
|
@ -1,14 +0,0 @@
|
||||
# semaphore-wrapper
|
||||
|
||||
## What it does
|
||||
|
||||
`semaphore-wrapper` generates `config.json` using `setup` command and execute provided command.
|
||||
|
||||
## How to test semaphore-wrapper
|
||||
|
||||
```bash
|
||||
SEMAPHORE_DB_DIALECT=bolt \
|
||||
SEMAPHORE_CONFIG_PATH=/tmp/semaphore \
|
||||
SEMAPHORE_DB_HOST=/tmp/semaphore \
|
||||
./semaphore-wrapper ../../../bin/semaphore server --config /tmp/semaphore/config.json
|
||||
```
|
@ -1,20 +0,0 @@
|
||||
#!/bin/sh
|
||||
|
||||
echo Loading environment...
|
||||
source /home/semaphore/venv/bin/activate
|
||||
|
||||
echo Staring runner...
|
||||
export ANSIBLE_HOST_KEY_CHECKING=False
|
||||
export ANSIBLE_STDOUT_CALLBACK=yaml
|
||||
export ANSIBLE_LOAD_CALLBACK_PLUGINS=yes
|
||||
export ANSIBLE_CONFIG=/tmp/semaphore/ansible.cfg
|
||||
|
||||
tee "/tmp/semaphore/ansible.cfg" <<CONFIG
|
||||
[defaults]
|
||||
host_key_checking = False
|
||||
stdout_callback = yaml
|
||||
bin_ansible_callbacks = yes
|
||||
CONFIG
|
||||
|
||||
|
||||
/usr/local/bin/semaphore runner start --config /etc/semaphore/config.json
|
@ -1,173 +0,0 @@
|
||||
#!/bin/sh
|
||||
|
||||
set -e
|
||||
|
||||
echoerr() { printf "%s\n" "$*" >&2; }
|
||||
|
||||
file_env() {
|
||||
local var=""
|
||||
local fileVar=""
|
||||
eval var="\$${1}"
|
||||
eval fileVar="\$${1}_FILE"
|
||||
local def="${2:-}"
|
||||
if [ -n "${var:-}" ] && [ -n "${fileVar:-}" ]; then
|
||||
echo >&2 "error: both ${1} and ${1}_FILE are set (but are exclusive)"
|
||||
exit 1
|
||||
fi
|
||||
local val="$def"
|
||||
if [ -n "${var:-}" ]; then
|
||||
val="${var}"
|
||||
elif [ -n "${fileVar:-}" ]; then
|
||||
val="$(cat "${fileVar}")"
|
||||
fi
|
||||
export "${1}"="$val"
|
||||
unset "${1}_FILE"
|
||||
}
|
||||
|
||||
SEMAPHORE_CONFIG_PATH="${SEMAPHORE_CONFIG_PATH:-/etc/semaphore}"
|
||||
SEMAPHORE_TMP_PATH="${SEMAPHORE_TMP_PATH:-/tmp/semaphore}"
|
||||
|
||||
# Semaphore database env config
|
||||
SEMAPHORE_DB_DIALECT="${SEMAPHORE_DB_DIALECT:-mysql}"
|
||||
SEMAPHORE_DB_HOST="${SEMAPHORE_DB_HOST:-0.0.0.0}"
|
||||
SEMAPHORE_DB_PATH="${SEMAPHORE_DB_PATH:-/var/lib/semaphore}"
|
||||
SEMAPHORE_DB_PORT="${SEMAPHORE_DB_PORT:-}"
|
||||
SEMAPHORE_DB="${SEMAPHORE_DB:-semaphore}"
|
||||
file_env 'SEMAPHORE_DB_USER' 'semaphore'
|
||||
file_env 'SEMAPHORE_DB_PASS' 'semaphore'
|
||||
# Email alert env config
|
||||
SEMAPHORE_WEB_ROOT="${SEMAPHORE_WEB_ROOT:-}"
|
||||
# Semaphore Admin env config
|
||||
file_env 'SEMAPHORE_ADMIN' 'admin'
|
||||
SEMAPHORE_ADMIN_EMAIL="${SEMAPHORE_ADMIN_EMAIL:-admin@localhost}"
|
||||
SEMAPHORE_ADMIN_NAME="${SEMAPHORE_ADMIN_NAME:-Semaphore Admin}"
|
||||
file_env 'SEMAPHORE_ADMIN_PASSWORD' 'semaphorepassword'
|
||||
#Semaphore LDAP env config
|
||||
SEMAPHORE_LDAP_ACTIVATED="${SEMAPHORE_LDAP_ACTIVATED:-no}"
|
||||
SEMAPHORE_LDAP_HOST="${SEMAPHORE_LDAP_HOST:-}"
|
||||
SEMAPHORE_LDAP_PORT="${SEMAPHORE_LDAP_PORT:-}"
|
||||
SEMAPHORE_LDAP_NEEDTLS="${SEMAPHORE_LDAP_NEEDTLS:-no}"
|
||||
SEMAPHORE_LDAP_DN_BIND="${SEMAPHORE_LDAP_DN_BIND:-}"
|
||||
file_env 'SEMAPHORE_LDAP_PASSWORD'
|
||||
SEMAPHORE_LDAP_DN_SEARCH="${SEMAPHORE_LDAP_DN_SEARCH:-}"
|
||||
SEMAPHORE_LDAP_SEARCH_FILTER="${SEMAPHORE_LDAP_SEARCH_FILTER:-(uid=%s)}"
|
||||
SEMAPHORE_LDAP_MAPPING_DN="${SEMAPHORE_LDAP_MAPPING_DN:-dn}"
|
||||
SEMAPHORE_LDAP_MAPPING_USERNAME="${SEMAPHORE_LDAP_MAPPING_USERNAME:-uid}"
|
||||
SEMAPHORE_LDAP_MAPPING_FULLNAME="${SEMAPHORE_LDAP_MAPPING_FULLNAME:-cn}"
|
||||
SEMAPHORE_LDAP_MAPPING_EMAIL="${SEMAPHORE_LDAP_MAPPING_EMAIL:-mail}"
|
||||
|
||||
file_env 'SEMAPHORE_ACCESS_KEY_ENCRYPTION'
|
||||
|
||||
[ -d "${SEMAPHORE_TMP_PATH}" ] || mkdir -p "${SEMAPHORE_TMP_PATH}" || {
|
||||
echo "Can't create Semaphore tmp path ${SEMAPHORE_TMP_PATH}."
|
||||
exit 1
|
||||
}
|
||||
|
||||
[ -d "${SEMAPHORE_CONFIG_PATH}" ] || mkdir -p "${SEMAPHORE_CONFIG_PATH}" || {
|
||||
echo "Can't create Semaphore Config path ${SEMAPHORE_CONFIG_PATH}."
|
||||
exit 1
|
||||
}
|
||||
|
||||
[ -d "${SEMAPHORE_DB_PATH}" ] || mkdir -p "${SEMAPHORE_DB_PATH}" || {
|
||||
echo "Can't create data path ${SEMAPHORE_DB_PATH}."
|
||||
exit 1
|
||||
}
|
||||
|
||||
# wait on db to be up
|
||||
|
||||
if [ "${SEMAPHORE_DB_DIALECT}" != 'bolt' ]; then
|
||||
echoerr "Attempting to connect to database ${SEMAPHORE_DB} on ${SEMAPHORE_DB_HOST}:${SEMAPHORE_DB_PORT} with user ${SEMAPHORE_DB_USER} ..."
|
||||
TIMEOUT=30
|
||||
while ! $(nc -z "$SEMAPHORE_DB_HOST" "$SEMAPHORE_DB_PORT") >/dev/null 2>&1; do
|
||||
TIMEOUT=$(expr $TIMEOUT - 1)
|
||||
if [ $TIMEOUT -eq 0 ]; then
|
||||
echoerr "Could not connect to database server. Exiting."
|
||||
exit 1
|
||||
fi
|
||||
echo -n "."
|
||||
sleep 1
|
||||
done
|
||||
fi
|
||||
|
||||
if [ -n "${SEMAPHORE_DB_PORT}" ]; then
|
||||
SEMAPHORE_DB_HOST="${SEMAPHORE_DB_HOST}:${SEMAPHORE_DB_PORT}"
|
||||
fi
|
||||
|
||||
case ${SEMAPHORE_DB_DIALECT} in
|
||||
mysql) SEMAPHORE_DB_DIALECT_ID=1;;
|
||||
bolt) SEMAPHORE_DB_DIALECT_ID=2;;
|
||||
postgres) SEMAPHORE_DB_DIALECT_ID=3;;
|
||||
*)
|
||||
echoerr "Unknown database dialect: ${SEMAPHORE_DB_DIALECT}"
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
|
||||
# Create a config if it does not exist in the current config path
|
||||
if [ ! -f "${SEMAPHORE_CONFIG_PATH}/config.json" ]; then
|
||||
echoerr "Generating ${SEMAPHORE_TMP_PATH}/config.stdin ..."
|
||||
cat << EOF > "${SEMAPHORE_TMP_PATH}/config.stdin"
|
||||
${SEMAPHORE_DB_DIALECT_ID}
|
||||
EOF
|
||||
|
||||
if [ "${SEMAPHORE_DB_DIALECT}" = "bolt" ]; then
|
||||
cat << EOF >> "${SEMAPHORE_TMP_PATH}/config.stdin"
|
||||
${SEMAPHORE_DB_PATH}/database.boltdb
|
||||
EOF
|
||||
else
|
||||
cat << EOF >> "${SEMAPHORE_TMP_PATH}/config.stdin"
|
||||
${SEMAPHORE_DB_HOST}
|
||||
${SEMAPHORE_DB_USER}
|
||||
${SEMAPHORE_DB_PASS}
|
||||
${SEMAPHORE_DB}
|
||||
EOF
|
||||
fi
|
||||
|
||||
cat << EOF >> "${SEMAPHORE_TMP_PATH}/config.stdin"
|
||||
${SEMAPHORE_TMP_PATH}
|
||||
${SEMAPHORE_WEB_ROOT}
|
||||
no
|
||||
no
|
||||
no
|
||||
no
|
||||
no
|
||||
${SEMAPHORE_LDAP_ACTIVATED}
|
||||
EOF
|
||||
|
||||
if [ "${SEMAPHORE_LDAP_ACTIVATED}" = "yes" ]; then
|
||||
cat << EOF >> "${SEMAPHORE_TMP_PATH}/config.stdin"
|
||||
${SEMAPHORE_LDAP_HOST}:${SEMAPHORE_LDAP_PORT}
|
||||
${SEMAPHORE_LDAP_NEEDTLS}
|
||||
${SEMAPHORE_LDAP_DN_BIND}
|
||||
${SEMAPHORE_LDAP_PASSWORD}
|
||||
${SEMAPHORE_LDAP_DN_SEARCH}
|
||||
${SEMAPHORE_LDAP_SEARCH_FILTER}
|
||||
${SEMAPHORE_LDAP_MAPPING_DN}
|
||||
${SEMAPHORE_LDAP_MAPPING_USERNAME}
|
||||
${SEMAPHORE_LDAP_MAPPING_FULLNAME}
|
||||
${SEMAPHORE_LDAP_MAPPING_EMAIL}
|
||||
EOF
|
||||
fi;
|
||||
|
||||
cat << EOF >> "${SEMAPHORE_TMP_PATH}/config.stdin"
|
||||
${SEMAPHORE_CONFIG_PATH}
|
||||
${SEMAPHORE_ADMIN}
|
||||
${SEMAPHORE_ADMIN_EMAIL}
|
||||
${SEMAPHORE_ADMIN_NAME}
|
||||
${SEMAPHORE_ADMIN_PASSWORD}
|
||||
EOF
|
||||
|
||||
$1 setup - < "${SEMAPHORE_TMP_PATH}/config.stdin"
|
||||
echoerr "Run Semaphore with semaphore server --config ${SEMAPHORE_CONFIG_PATH}/config.json"
|
||||
fi
|
||||
|
||||
# Install additional python requirements
|
||||
if [ -f "${SEMAPHORE_CONFIG_PATH}/requirements.txt" ]; then
|
||||
echoerr "Installing additional python packages"
|
||||
pip3 install --upgrade --user -r "${SEMAPHORE_CONFIG_PATH}/requirements.txt"
|
||||
else
|
||||
echoerr "No additional python packages to install"
|
||||
fi
|
||||
|
||||
# run our command
|
||||
exec "$@"
|
@ -1,40 +0,0 @@
|
||||
FROM golang:1.21-alpine3.18
|
||||
|
||||
ENV SEMAPHORE_VERSION="development" SEMAPHORE_ARCH="linux_amd64" \
|
||||
SEMAPHORE_CONFIG_PATH="${SEMAPHORE_CONFIG_PATH:-/etc/semaphore}" \
|
||||
APP_ROOT="/go/src/github.com/ansible-semaphore/semaphore/"
|
||||
|
||||
# hadolint ignore=DL3013
|
||||
RUN apk add --no-cache gcc g++ sshpass git mysql-client python3 py3-pip py-openssl openssl ca-certificates curl curl-dev openssh-client-default tini nodejs npm bash rsync tzdata zip unzip tar && \
|
||||
apk --update add --virtual build-dependencies python3-dev libffi-dev openssl-dev build-base &&\
|
||||
rm -rf /var/cache/apk/*
|
||||
|
||||
RUN pip3 install --upgrade pip cffi &&\
|
||||
apk del build-dependencies && \
|
||||
pip3 install ansible
|
||||
|
||||
RUN adduser -D -u 1002 -g 0 semaphore && \
|
||||
mkdir -p /go/src/github.com/ansible-semaphore/semaphore && \
|
||||
mkdir -p /tmp/semaphore && \
|
||||
mkdir -p /etc/semaphore && \
|
||||
mkdir -p /var/lib/semaphore && \
|
||||
chown -R semaphore:0 /go && \
|
||||
chown -R semaphore:0 /tmp/semaphore && \
|
||||
chown -R semaphore:0 /etc/semaphore && \
|
||||
chown -R semaphore:0 /var/lib/semaphore && \
|
||||
ssh-keygen -t rsa -q -f "/root/.ssh/id_rsa" -N "" && \
|
||||
ssh-keyscan -H github.com > /root/.ssh/known_hosts
|
||||
|
||||
RUN cd $(go env GOPATH) && curl -sL https://taskfile.dev/install.sh | sh
|
||||
|
||||
RUN git config --global --add safe.directory /go/src/github.com/ansible-semaphore/semaphore
|
||||
|
||||
# Copy in app source
|
||||
WORKDIR ${APP_ROOT}
|
||||
COPY . ${APP_ROOT}
|
||||
RUN deployment/docker/dev/bin/install
|
||||
|
||||
USER semaphore
|
||||
EXPOSE 3000
|
||||
ENTRYPOINT ["/usr/local/bin/semaphore-wrapper"]
|
||||
CMD ["./bin/semaphore", "server", "--config", "/etc/semaphore/config.json"]
|
@ -1,16 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
set -e
|
||||
|
||||
echo "--> Turn off StrictKeyChecking"
|
||||
cat > /etc/ssh/ssh_config <<EOF
|
||||
Host *
|
||||
StrictHostKeyChecking no
|
||||
UserKnownHostsFile=/dev/null
|
||||
EOF
|
||||
|
||||
echo "--> Install Semaphore entrypoint wrapper script"
|
||||
mv ./deployment/docker/common/semaphore-wrapper /usr/local/bin/semaphore-wrapper
|
||||
mv ./deployment/docker/common/runner-wrapper /usr/local/bin/runner-wrapper
|
||||
task deps
|
||||
chmod -R 0777 /go
|
@ -1,39 +0,0 @@
|
||||
version: '2'
|
||||
|
||||
services:
|
||||
mysql:
|
||||
image: mariadb:10
|
||||
environment:
|
||||
MYSQL_RANDOM_ROOT_PASSWORD: 'yes'
|
||||
MYSQL_DATABASE: semaphore
|
||||
MYSQL_USER: semaphore
|
||||
MYSQL_PASSWORD: semaphore
|
||||
## uncomment if you want to store mysql data between launches
|
||||
#volumes:
|
||||
# - /tmp/mysql_data:/var/lib/mysql
|
||||
ports:
|
||||
- "3306:3306"
|
||||
|
||||
semaphore_dev:
|
||||
image: semaphoreui/semaphore:dev-compose
|
||||
build:
|
||||
context: ./../../../
|
||||
dockerfile: ./deployment/docker/dev/Dockerfile
|
||||
volumes:
|
||||
- "./../../../:/go/src/github.com/ansible-semaphore/semaphore:rw"
|
||||
environment:
|
||||
SEMAPHORE_DB_DIALECT: mysql
|
||||
SEMAPHORE_DB_USER: semaphore
|
||||
SEMAPHORE_DB_PASS: semaphore
|
||||
SEMAPHORE_DB_HOST: mysql
|
||||
SEMAPHORE_DB_PORT: 3306
|
||||
SEMAPHORE_DB: semaphore
|
||||
SEMAPHORE_ADMIN_PASSWORD: password
|
||||
SEMAPHORE_ADMIN_NAME: "Developer"
|
||||
SEMAPHORE_ADMIN_EMAIL: admin@localhost
|
||||
SEMAPHORE_ADMIN: admin
|
||||
SEMAPHORE_WEB_ROOT: http://0.0.0.0:3000
|
||||
ports:
|
||||
- "3000:3000"
|
||||
depends_on:
|
||||
- mysql
|
34
deployment/docker/dredd/Dockerfile
Normal file
34
deployment/docker/dredd/Dockerfile
Normal file
@ -0,0 +1,34 @@
|
||||
FROM golang:1.22-alpine3.19 as golang
|
||||
|
||||
RUN apk add --no-cache -U \
|
||||
curl git
|
||||
|
||||
WORKDIR /usr/local
|
||||
# hadolint ignore=DL4006
|
||||
RUN curl -sL https://taskfile.dev/install.sh | sh
|
||||
|
||||
WORKDIR /go/src/semaphore
|
||||
COPY go.mod go.sum /go/src/semaphore/
|
||||
|
||||
RUN --mount=type=cache,target=/go/pkg \
|
||||
go mod download -x
|
||||
|
||||
COPY . /go/src/semaphore
|
||||
|
||||
RUN --mount=type=cache,target=/go/pkg --mount=type=cache,target=/root/.cache/go-build \
|
||||
task deps:tools && \
|
||||
task deps:be && \
|
||||
task e2e:goodman && \
|
||||
task e2e:hooks
|
||||
|
||||
FROM apiaryio/dredd:13.0.0
|
||||
|
||||
RUN apk add --no-cache -U \
|
||||
bash git go
|
||||
|
||||
COPY --from=golang /go/bin/goodman /root/go/bin/goodman
|
||||
COPY --from=golang /go/src/semaphore /semaphore
|
||||
WORKDIR /semaphore
|
||||
|
||||
COPY deployment/docker/dredd/entrypoint /usr/local/bin
|
||||
ENTRYPOINT ["/usr/local/bin/entrypoint"]
|
20
deployment/docker/dredd/entrypoint
Executable file
20
deployment/docker/dredd/entrypoint
Executable file
@ -0,0 +1,20 @@
|
||||
#!/usr/bin/env bash
|
||||
set -eo pipefail
|
||||
|
||||
echo "---> Gen semaphore config"
|
||||
cat << EOF > /semaphore/.dredd/config.json
|
||||
{
|
||||
"dialect": "${SEMAPHORE_DB_DIALECT}",
|
||||
"${SEMAPHORE_DB_DIALECT}": ${SEMAPHORE_DB_CONFIG},
|
||||
"access_key_encryption": "${SEMAPHORE_ACCESS_KEY_ENCRYPTION}"
|
||||
}
|
||||
EOF
|
||||
|
||||
echo "---> Waiting for semaphore"
|
||||
while ! nc -z server 3000; do
|
||||
sleep 1
|
||||
done
|
||||
|
||||
echo "---> Start dredd server"
|
||||
sleep 5
|
||||
dredd $@
|
@ -1,32 +0,0 @@
|
||||
# ansible-semaphore production image
|
||||
FROM golang:1.21-alpine3.18 as builder
|
||||
|
||||
COPY ./ /go/src/github.com/ansible-semaphore/semaphore
|
||||
WORKDIR /go/src/github.com/ansible-semaphore/semaphore
|
||||
|
||||
RUN apk add --no-cache -U libc-dev curl nodejs npm git gcc g++ && \
|
||||
./deployment/docker/prod/bin/install
|
||||
|
||||
FROM alpine:3.18 as runner
|
||||
LABEL maintainer="Tom Whiston <tom.whiston@gmail.com>"
|
||||
|
||||
RUN apk add --no-cache sshpass git curl ansible mysql-client openssh-client-default tini py3-aiohttp tzdata zip unzip tar py3-pip && \
|
||||
adduser -D -u 1001 -G root semaphore && \
|
||||
mkdir -p /tmp/semaphore && \
|
||||
mkdir -p /etc/semaphore && \
|
||||
mkdir -p /var/lib/semaphore && \
|
||||
chown -R semaphore:0 /tmp/semaphore && \
|
||||
chown -R semaphore:0 /etc/semaphore && \
|
||||
chown -R semaphore:0 /var/lib/semaphore
|
||||
|
||||
COPY --from=builder /usr/local/bin/semaphore-wrapper /usr/local/bin/
|
||||
COPY --from=builder /usr/local/bin/semaphore /usr/local/bin/
|
||||
|
||||
RUN chown -R semaphore:0 /usr/local/bin/semaphore-wrapper &&\
|
||||
chown -R semaphore:0 /usr/local/bin/semaphore
|
||||
|
||||
WORKDIR /home/semaphore
|
||||
USER 1001
|
||||
|
||||
ENTRYPOINT ["/sbin/tini", "--"]
|
||||
CMD ["/usr/local/bin/semaphore-wrapper", "/usr/local/bin/semaphore", "server", "--config", "/etc/semaphore/config.json"]
|
@ -1,24 +0,0 @@
|
||||
#!/usr/bin/env sh
|
||||
|
||||
set -e
|
||||
|
||||
# Get prerequisites for building the app
|
||||
(cd $(go env GOPATH) && curl -sL https://taskfile.dev/install.sh | sh)
|
||||
|
||||
# Compile and build
|
||||
task deps
|
||||
set +e
|
||||
task compile
|
||||
set -e
|
||||
|
||||
task build:local GOOS=$1 GOARCH=$2
|
||||
|
||||
mv ./bin/semaphore /usr/local/bin/
|
||||
chown 1001:0 /usr/local/bin/semaphore
|
||||
chmod +x /usr/local/bin/semaphore
|
||||
|
||||
mv ./deployment/docker/common/semaphore-wrapper /usr/local/bin/semaphore-wrapper
|
||||
chown 1001:0 /usr/local/bin/semaphore-wrapper
|
||||
|
||||
mv ./deployment/docker/common/runner-wrapper /usr/local/bin/runner-wrapper
|
||||
chown 1001:0 /usr/local/bin/runner-wrapper
|
@ -1,37 +0,0 @@
|
||||
# ansible-semaphore production image
|
||||
FROM --platform=$BUILDPLATFORM golang:1.21-alpine3.18 as builder
|
||||
|
||||
COPY ./ /go/src/github.com/ansible-semaphore/semaphore
|
||||
WORKDIR /go/src/github.com/ansible-semaphore/semaphore
|
||||
|
||||
ARG TARGETOS
|
||||
ARG TARGETARCH
|
||||
|
||||
RUN apk add --no-cache -U libc-dev curl nodejs npm git gcc
|
||||
RUN ./deployment/docker/prod/bin/install ${TARGETOS} ${TARGETARCH}
|
||||
|
||||
FROM alpine:3.18 as runner
|
||||
LABEL maintainer="Tom Whiston <tom.whiston@gmail.com>"
|
||||
|
||||
RUN apk add --no-cache sshpass git curl ansible mysql-client openssh-client-default tini py3-aiohttp tzdata py3-pip && \
|
||||
adduser -D -u 1001 -G root semaphore && \
|
||||
mkdir -p /tmp/semaphore && \
|
||||
mkdir -p /etc/semaphore && \
|
||||
mkdir -p /var/lib/semaphore && \
|
||||
chown -R semaphore:0 /tmp/semaphore && \
|
||||
chown -R semaphore:0 /etc/semaphore && \
|
||||
chown -R semaphore:0 /var/lib/semaphore
|
||||
|
||||
COPY --from=builder /usr/local/bin/semaphore-wrapper /usr/local/bin/
|
||||
COPY --from=builder /usr/local/bin/semaphore /usr/local/bin/
|
||||
|
||||
RUN chown -R semaphore:0 /usr/local/bin/semaphore-wrapper &&\
|
||||
chown -R semaphore:0 /usr/local/bin/semaphore &&\
|
||||
chmod +x /usr/local/bin/semaphore-wrapper &&\
|
||||
chmod +x /usr/local/bin/semaphore
|
||||
|
||||
WORKDIR /home/semaphore
|
||||
USER 1001
|
||||
|
||||
ENTRYPOINT ["/sbin/tini", "--"]
|
||||
CMD ["/usr/local/bin/semaphore-wrapper", "/usr/local/bin/semaphore", "server", "--config", "/etc/semaphore/config.json"]
|
@ -1,41 +0,0 @@
|
||||
# This dockerfile provides an example of using the production image in a working stack
|
||||
version: '2'
|
||||
|
||||
services:
|
||||
|
||||
mysql:
|
||||
image: mysql:5.6
|
||||
hostname: mysql
|
||||
environment:
|
||||
MYSQL_RANDOM_ROOT_PASSWORD: 'yes'
|
||||
MYSQL_DATABASE: semaphore
|
||||
MYSQL_USER: semaphore
|
||||
MYSQL_PASSWORD: hx4hjxqthfwbfsy5535u4agfdscm
|
||||
|
||||
semaphore:
|
||||
image: semaphoreui/semaphore:prod-compose
|
||||
build:
|
||||
context: ./../../../
|
||||
dockerfile: ./deployment/docker/prod/Dockerfile
|
||||
environment:
|
||||
SEMAPHORE_DB_DIALECT: mysql
|
||||
SEMAPHORE_DB_USER: semaphore
|
||||
SEMAPHORE_DB_PASS: hx4hjxqthfwbfsy5535u4agfdscm
|
||||
SEMAPHORE_DB_HOST: mysql
|
||||
SEMAPHORE_DB_PORT: 3306
|
||||
SEMAPHORE_DB: semaphore
|
||||
SEMAPHORE_ADMIN_PASSWORD: cangetin
|
||||
SEMAPHORE_ADMIN_NAME: admin
|
||||
SEMAPHORE_ADMIN_EMAIL: admin@localhost
|
||||
SEMAPHORE_ADMIN: admin
|
||||
depends_on:
|
||||
- mysql
|
||||
semaphore_proxy:
|
||||
image: ansiblesemaphore/proxy:latest
|
||||
build:
|
||||
context: ./proxy
|
||||
ports:
|
||||
- "80:80"
|
||||
- "443:443"
|
||||
depends_on:
|
||||
- semaphore
|
@ -1,11 +0,0 @@
|
||||
FROM nginx:alpine
|
||||
|
||||
LABEL maintainer="Tom Whiston <tom.whiston@gmail.com>"
|
||||
|
||||
COPY nginx.conf /etc/nginx/nginx.conf
|
||||
COPY cert/ /etc/nginx/cert
|
||||
COPY bin /usr/local/bin
|
||||
RUN apk add --no-cache openssl && \
|
||||
/usr/local/bin/install && \
|
||||
apk del openssl && \
|
||||
rm -rf /var/cache/apk/*
|
@ -1,6 +0,0 @@
|
||||
#!/usr/bin/env sh
|
||||
|
||||
if [ ! -f /etc/nginx/cert/privkey.pem ] && [ ! -f /etc/nginx/cert/cert.pem ]; then
|
||||
echo "--> Generating self-signed cert. This should not be used in production"
|
||||
openssl req -x509 -newkey rsa:4096 -keyout /etc/nginx/cert/privkey.pem -out /etc/nginx/cert/cert.pem -sha256 -nodes -subj "/O=Ansible Semaphore/OU=Production Test/CN=github.com\/ansible-semaphore\/semaphore"
|
||||
fi
|
@ -1,68 +0,0 @@
|
||||
worker_processes auto;
|
||||
|
||||
events {
|
||||
worker_connections 1024;
|
||||
use epoll;
|
||||
multi_accept on;
|
||||
}
|
||||
|
||||
http {
|
||||
tcp_nodelay on;
|
||||
|
||||
# this is necessary for us to be able to disable request buffering in all cases
|
||||
proxy_http_version 1.1;
|
||||
|
||||
upstream semaphore {
|
||||
server semaphore:3000;
|
||||
}
|
||||
|
||||
server {
|
||||
listen [::]:80 default_server;
|
||||
server_name _;
|
||||
return 301 https://$host$request_uri;
|
||||
}
|
||||
|
||||
server {
|
||||
listen 443 ssl;
|
||||
server_name _;
|
||||
|
||||
# add Strict-Transport-Security to prevent man in the middle attacks
|
||||
add_header Strict-Transport-Security "max-age=31536000" always;
|
||||
|
||||
# SSL
|
||||
ssl_certificate /etc/nginx/cert/cert.pem;
|
||||
ssl_certificate_key /etc/nginx/cert/privkey.pem;
|
||||
|
||||
# Recommendations from https://raymii.org/s/tutorials/Strong_SSL_Security_On_nginx.html
|
||||
ssl_protocols TLSv1.1 TLSv1.2;
|
||||
ssl_ciphers 'EECDH+AESGCM:EDH+AESGCM:AES256+EECDH:AES256+EDH';
|
||||
ssl_prefer_server_ciphers on;
|
||||
ssl_session_cache shared:SSL:10m;
|
||||
|
||||
# disable any limits to avoid HTTP 413 for large image uploads
|
||||
client_max_body_size 0;
|
||||
|
||||
# required to avoid HTTP 411: see Issue #1486 (https://github.com/docker/docker/issues/1486)
|
||||
chunked_transfer_encoding on;
|
||||
|
||||
location / {
|
||||
proxy_pass http://semaphore/;
|
||||
proxy_set_header Host $http_host;
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
|
||||
proxy_set_header X-Forwarded-Proto $scheme;
|
||||
|
||||
proxy_buffering off;
|
||||
proxy_request_buffering off;
|
||||
}
|
||||
|
||||
location /api/ws {
|
||||
proxy_pass http://semaphore/api/ws;
|
||||
proxy_http_version 1.1;
|
||||
proxy_set_header Upgrade $http_upgrade;
|
||||
proxy_set_header Connection "upgrade";
|
||||
proxy_set_header Origin "";
|
||||
}
|
||||
}
|
||||
}
|
@ -1,32 +0,0 @@
|
||||
FROM dind-ansible:latest
|
||||
|
||||
RUN apk add --no-cache wget git rsync tzdata zip unzip tar
|
||||
|
||||
RUN adduser -D -u 1001 -G root -G docker semaphore && \
|
||||
mkdir -p /tmp/semaphore && \
|
||||
mkdir -p /etc/semaphore && \
|
||||
mkdir -p /var/lib/semaphore && \
|
||||
chown -R semaphore:0 /tmp/semaphore && \
|
||||
chown -R semaphore:0 /etc/semaphore && \
|
||||
chown -R semaphore:0 /var/lib/semaphore
|
||||
|
||||
RUN wget https://raw.githubusercontent.com/ansible-semaphore/semaphore/develop/deployment/docker/common/runner-wrapper -P /usr/local/bin/ && chmod +x /usr/local/bin/runner-wrapper
|
||||
RUN wget https://github.com/ansible-semaphore/semaphore/releases/download/v2.9.37/semaphore_2.9.37_linux_amd64.tar.gz -O - | tar -xz -C /usr/local/bin/ semaphore
|
||||
|
||||
RUN chown -R semaphore:0 /usr/local/bin/runner-wrapper &&\
|
||||
chown -R semaphore:0 /usr/local/bin/semaphore &&\
|
||||
chmod +x /usr/local/bin/runner-wrapper &&\
|
||||
chmod +x /usr/local/bin/semaphore
|
||||
|
||||
WORKDIR /home/semaphore
|
||||
USER 1001
|
||||
|
||||
RUN mkdir ./venv
|
||||
|
||||
RUN python3 -m venv ./venv --system-site-packages && \
|
||||
source ./venv/bin/activate && \
|
||||
pip3 install --upgrade pip boto3 botocore requests
|
||||
|
||||
RUN echo '{"tmp_path": "/tmp/semaphore","dialect": "bolt", "runner": {"config_file": "/var/lib/semaphore/runner.json"}}' > /etc/semaphore/config.json
|
||||
|
||||
CMD [ "/usr/local/bin/runner-wrapper" ]
|
@ -1,46 +0,0 @@
|
||||
# ansible-semaphore production image
|
||||
FROM --platform=$BUILDPLATFORM golang:1.21-alpine3.18 as builder
|
||||
|
||||
COPY ./ /go/src/github.com/ansible-semaphore/semaphore
|
||||
WORKDIR /go/src/github.com/ansible-semaphore/semaphore
|
||||
|
||||
ARG TARGETOS
|
||||
ARG TARGETARCH
|
||||
|
||||
RUN apk add --no-cache -U libc-dev curl nodejs npm git gcc zip unzip tar
|
||||
RUN ./deployment/docker/prod/bin/install ${TARGETOS} ${TARGETARCH}
|
||||
|
||||
FROM alpine/ansible:latest
|
||||
|
||||
RUN apk add --no-cache wget git rsync tzdata
|
||||
|
||||
RUN adduser -D -u 1001 -G root semaphore && \
|
||||
mkdir -p /tmp/semaphore && \
|
||||
mkdir -p /etc/semaphore && \
|
||||
mkdir -p /var/lib/semaphore && \
|
||||
chown -R semaphore:0 /tmp/semaphore && \
|
||||
chown -R semaphore:0 /etc/semaphore && \
|
||||
chown -R semaphore:0 /var/lib/semaphore
|
||||
|
||||
COPY --from=builder /usr/local/bin/runner-wrapper /usr/local/bin/
|
||||
COPY --from=builder /usr/local/bin/semaphore /usr/local/bin/
|
||||
|
||||
RUN chown -R semaphore:0 /usr/local/bin/runner-wrapper &&\
|
||||
chown -R semaphore:0 /usr/local/bin/semaphore &&\
|
||||
chmod +x /usr/local/bin/runner-wrapper &&\
|
||||
chmod +x /usr/local/bin/semaphore
|
||||
|
||||
WORKDIR /home/semaphore
|
||||
USER 1001
|
||||
|
||||
RUN mkdir ./venv
|
||||
|
||||
RUN python3 -m venv ./venv --system-site-packages && \
|
||||
source ./venv/bin/activate && \
|
||||
pip3 install --upgrade pip
|
||||
|
||||
RUN pip3 install boto3 botocore
|
||||
|
||||
RUN echo '{"tmp_path": "/tmp/semaphore","dialect": "bolt", "runner": {"config_file": "/var/lib/semaphore/runner.json"}}' > /etc/semaphore/config.json
|
||||
|
||||
CMD [ "/usr/local/bin/runner-wrapper" ]
|
63
deployment/docker/runner/Dockerfile
Normal file
63
deployment/docker/runner/Dockerfile
Normal file
@ -0,0 +1,63 @@
|
||||
FROM --platform=$BUILDPLATFORM golang:1.22-alpine3.18 as builder
|
||||
|
||||
RUN apk add --no-cache -U \
|
||||
libc-dev curl nodejs npm git gcc zip unzip tar
|
||||
|
||||
WORKDIR /usr/local
|
||||
# hadolint ignore=DL4006
|
||||
RUN curl -sL https://taskfile.dev/install.sh | sh
|
||||
|
||||
WORKDIR /go/src/semaphore
|
||||
COPY go.mod go.sum /go/src/semaphore/
|
||||
|
||||
RUN --mount=type=cache,target=/go/pkg \
|
||||
go mod download -x
|
||||
|
||||
COPY . /go/src/semaphore
|
||||
|
||||
ARG TARGETOS
|
||||
ARG TARGETARCH
|
||||
|
||||
RUN --mount=type=cache,target=/go/src/semaphore/web/node_modules \
|
||||
--mount=type=cache,target=/go/pkg \
|
||||
--mount=type=cache,target=/root/.cache/go-build \
|
||||
task deps && \
|
||||
task build GOOS=${TARGETOS} GOARCH=${TARGETARCH}
|
||||
|
||||
FROM alpine:3.19
|
||||
|
||||
RUN apk add --no-cache -U \
|
||||
bash curl git gnupg mysql-client openssh-client-default python3 python3-dev py3-pip rsync sshpass tar tini tzdata unzip wget zip build-base openssl-dev libffi-dev cargo && \
|
||||
rm -rf /var/cache/apk/* && \
|
||||
adduser -D -u 1001 -G root semaphore && \
|
||||
mkdir -p /tmp/semaphore && \
|
||||
mkdir -p /etc/semaphore && \
|
||||
mkdir -p /var/lib/semaphore && \
|
||||
chown -R semaphore:0 /tmp/semaphore && \
|
||||
chown -R semaphore:0 /etc/semaphore && \
|
||||
chown -R semaphore:0 /var/lib/semaphore
|
||||
|
||||
COPY --chown=1001:0 ./deployment/docker/runner/ansible.cfg /tmp/semaphore/ansible.cfg
|
||||
COPY --from=builder /go/src/semaphore/deployment/docker/runner/runner-wrapper /usr/local/bin/
|
||||
COPY --from=builder /go/src/semaphore/bin/semaphore /usr/local/bin/
|
||||
|
||||
RUN chown -R semaphore:0 /usr/local/bin/runner-wrapper && \
|
||||
chmod +x /usr/local/bin/runner-wrapper && \
|
||||
chown -R semaphore:0 /usr/local/bin/semaphore && \
|
||||
chmod +x /usr/local/bin/semaphore
|
||||
|
||||
WORKDIR /home/semaphore
|
||||
USER 1001
|
||||
|
||||
# renovate: datasource=pypi depName=ansible
|
||||
ENV ANSIBLE_VERSION 9.4.0
|
||||
|
||||
ENV PATH /home/semaphore/.local/bin:$PATH
|
||||
|
||||
# hadolint ignore=DL3013
|
||||
RUN pip3 install -U --break-system-packages --no-cache-dir \
|
||||
ansible==${ANSIBLE_VERSION} \
|
||||
boto3 botocore requests netaddr
|
||||
|
||||
ENTRYPOINT ["/sbin/tini", "--"]
|
||||
CMD [ "/usr/local/bin/runner-wrapper"]
|
4
deployment/docker/runner/ansible.cfg
Normal file
4
deployment/docker/runner/ansible.cfg
Normal file
@ -0,0 +1,4 @@
|
||||
[defaults]
|
||||
host_key_checking = False
|
||||
bin_ansible_callbacks = True
|
||||
stdout_callback = yaml
|
@ -1,5 +1,5 @@
|
||||
file:
|
||||
/usr/local/bin/semaphore-wrapper:
|
||||
/usr/local/bin/runner-wrapper:
|
||||
exists: true
|
||||
owner: semaphore
|
||||
group: root
|
||||
@ -9,31 +9,51 @@ file:
|
||||
owner: semaphore
|
||||
group: root
|
||||
filetype: file
|
||||
|
||||
package:
|
||||
ansible:
|
||||
installed: true
|
||||
curl:
|
||||
installed: true
|
||||
git:
|
||||
installed: true
|
||||
go:
|
||||
installed: false
|
||||
libc-dev:
|
||||
installed: false
|
||||
mysql-client:
|
||||
installed: true
|
||||
nodejs:
|
||||
installed: false
|
||||
|
||||
curl:
|
||||
installed: true
|
||||
git:
|
||||
installed: true
|
||||
mysql-client:
|
||||
installed: true
|
||||
openssh-client-default:
|
||||
installed: true
|
||||
python3:
|
||||
installed: true
|
||||
py3-pip:
|
||||
installed: true
|
||||
rsync:
|
||||
installed: true
|
||||
sshpass:
|
||||
installed: true
|
||||
tar:
|
||||
installed: true
|
||||
tini:
|
||||
installed: true
|
||||
tzdata:
|
||||
installed: true
|
||||
unzip:
|
||||
installed: true
|
||||
wget:
|
||||
installed: true
|
||||
zip:
|
||||
installed: true
|
||||
|
||||
user:
|
||||
semaphore:
|
||||
exists: true
|
||||
uid: 1001
|
||||
gid: 0
|
||||
home: /home/semaphore
|
||||
|
||||
command:
|
||||
semaphore:
|
||||
exit-status: 0
|
30
deployment/docker/runner/runner-wrapper
Normal file
30
deployment/docker/runner/runner-wrapper
Normal file
@ -0,0 +1,30 @@
|
||||
#!/bin/sh
|
||||
set -e
|
||||
echoerr() { printf "%s\n" "$*" >&2; }
|
||||
|
||||
export SEMAPHORE_CONFIG_PATH="${SEMAPHORE_CONFIG_PATH:-/etc/semaphore}"
|
||||
export SEMAPHORE_TMP_PATH="${SEMAPHORE_TMP_PATH:-/tmp/semaphore}"
|
||||
export ANSIBLE_CONFIG="${ANSIBLE_CONFIG:-${SEMAPHORE_TMP_PATH}/ansible.cfg}"
|
||||
|
||||
if test -f "${SEMAPHORE_CONFIG_PATH}/packages.txt"; then
|
||||
echoerr "Installing additional system dependencies"
|
||||
apk add --no-cache --upgrade \
|
||||
$(cat "${SEMAPHORE_CONFIG_PATH}/packages.txt" | xargs)
|
||||
else
|
||||
echoerr "No additional system dependencies to install"
|
||||
fi
|
||||
|
||||
if test -f "${SEMAPHORE_CONFIG_PATH}/requirements.txt"; then
|
||||
echoerr "Installing additional python dependencies"
|
||||
pip3 install --upgrade --user \
|
||||
-r "${SEMAPHORE_CONFIG_PATH}/requirements.txt"
|
||||
else
|
||||
echoerr "No additional python dependencies to install"
|
||||
fi
|
||||
|
||||
echoerr "Starting semaphore runner"
|
||||
if test "$#" -ne 1; then
|
||||
exec /usr/local/bin/semaphore runner start --config "${SEMAPHORE_CONFIG_PATH}/config.json"
|
||||
else
|
||||
exec "$@"
|
||||
fi
|
63
deployment/docker/server/Dockerfile
Normal file
63
deployment/docker/server/Dockerfile
Normal file
@ -0,0 +1,63 @@
|
||||
FROM --platform=$BUILDPLATFORM golang:1.22-alpine3.18 as builder
|
||||
|
||||
RUN apk add --no-cache -U \
|
||||
libc-dev curl nodejs npm git gcc zip unzip tar
|
||||
|
||||
WORKDIR /usr/local
|
||||
# hadolint ignore=DL4006
|
||||
RUN curl -sL https://taskfile.dev/install.sh | sh
|
||||
|
||||
WORKDIR /go/src/semaphore
|
||||
COPY go.mod go.sum /go/src/semaphore/
|
||||
|
||||
RUN --mount=type=cache,target=/go/pkg \
|
||||
go mod download -x
|
||||
|
||||
COPY . /go/src/semaphore
|
||||
|
||||
ARG TARGETOS
|
||||
ARG TARGETARCH
|
||||
|
||||
RUN --mount=type=cache,target=/go/src/semaphore/web/node_modules \
|
||||
--mount=type=cache,target=/go/pkg \
|
||||
--mount=type=cache,target=/root/.cache/go-build \
|
||||
task deps && \
|
||||
task build GOOS=${TARGETOS} GOARCH=${TARGETARCH}
|
||||
|
||||
FROM alpine:3.19
|
||||
|
||||
RUN apk add --no-cache -U \
|
||||
bash curl git gnupg mysql-client openssh-client-default python3 python3-dev py3-pip rsync sshpass tar tini tzdata unzip wget zip build-base openssl-dev libffi-dev cargo && \
|
||||
rm -rf /var/cache/apk/* && \
|
||||
adduser -D -u 1001 -G root semaphore && \
|
||||
mkdir -p /tmp/semaphore && \
|
||||
mkdir -p /etc/semaphore && \
|
||||
mkdir -p /var/lib/semaphore && \
|
||||
chown -R semaphore:0 /tmp/semaphore && \
|
||||
chown -R semaphore:0 /etc/semaphore && \
|
||||
chown -R semaphore:0 /var/lib/semaphore
|
||||
|
||||
COPY --chown=1001:0 ./deployment/docker/server/ansible.cfg /tmp/semaphore/ansible.cfg
|
||||
COPY --from=builder /go/src/semaphore/deployment/docker/server/server-wrapper /usr/local/bin/
|
||||
COPY --from=builder /go/src/semaphore/bin/semaphore /usr/local/bin/
|
||||
|
||||
RUN chown -R semaphore:0 /usr/local/bin/server-wrapper && \
|
||||
chmod +x /usr/local/bin/server-wrapper && \
|
||||
chown -R semaphore:0 /usr/local/bin/semaphore && \
|
||||
chmod +x /usr/local/bin/semaphore
|
||||
|
||||
WORKDIR /home/semaphore
|
||||
USER 1001
|
||||
|
||||
# renovate: datasource=pypi depName=ansible
|
||||
ENV ANSIBLE_VERSION 9.4.0
|
||||
|
||||
ENV PATH /home/semaphore/.local/bin:$PATH
|
||||
|
||||
# hadolint ignore=DL3013
|
||||
RUN pip3 install -U --break-system-packages --no-cache-dir \
|
||||
ansible==${ANSIBLE_VERSION} \
|
||||
boto3 botocore requests netaddr
|
||||
|
||||
ENTRYPOINT ["/sbin/tini", "--"]
|
||||
CMD [ "/usr/local/bin/server-wrapper"]
|
4
deployment/docker/server/ansible.cfg
Normal file
4
deployment/docker/server/ansible.cfg
Normal file
@ -0,0 +1,4 @@
|
||||
[defaults]
|
||||
host_key_checking = False
|
||||
bin_ansible_callbacks = True
|
||||
stdout_callback = yaml
|
60
deployment/docker/server/goss.yaml
Normal file
60
deployment/docker/server/goss.yaml
Normal file
@ -0,0 +1,60 @@
|
||||
file:
|
||||
/usr/local/bin/server-wrapper:
|
||||
exists: true
|
||||
owner: semaphore
|
||||
group: root
|
||||
filetype: file
|
||||
/usr/local/bin/semaphore:
|
||||
exists: true
|
||||
owner: semaphore
|
||||
group: root
|
||||
filetype: file
|
||||
|
||||
package:
|
||||
go:
|
||||
installed: false
|
||||
libc-dev:
|
||||
installed: false
|
||||
nodejs:
|
||||
installed: false
|
||||
|
||||
curl:
|
||||
installed: true
|
||||
git:
|
||||
installed: true
|
||||
mysql-client:
|
||||
installed: true
|
||||
openssh-client-default:
|
||||
installed: true
|
||||
python3:
|
||||
installed: true
|
||||
py3-pip:
|
||||
installed: true
|
||||
rsync:
|
||||
installed: true
|
||||
sshpass:
|
||||
installed: true
|
||||
tar:
|
||||
installed: true
|
||||
tini:
|
||||
installed: true
|
||||
tzdata:
|
||||
installed: true
|
||||
unzip:
|
||||
installed: true
|
||||
wget:
|
||||
installed: true
|
||||
zip:
|
||||
installed: true
|
||||
|
||||
user:
|
||||
semaphore:
|
||||
exists: true
|
||||
uid: 1001
|
||||
gid: 0
|
||||
home: /home/semaphore
|
||||
|
||||
command:
|
||||
semaphore:
|
||||
exit-status: 0
|
||||
timeout: 10000
|
194
deployment/docker/server/server-wrapper
Executable file
194
deployment/docker/server/server-wrapper
Executable file
@ -0,0 +1,194 @@
|
||||
#!/bin/sh
|
||||
set -e
|
||||
echoerr() { printf "%s\n" "$*" >&2; }
|
||||
|
||||
file_env() {
|
||||
local var=""
|
||||
local fileVar=""
|
||||
|
||||
eval var="\$${1}"
|
||||
eval fileVar="\$${1}_FILE"
|
||||
|
||||
local def="${2:-}"
|
||||
|
||||
if [ -n "${var:-}" ] && [ -n "${fileVar:-}" ]; then
|
||||
echo >&2 "error: both ${1} and ${1}_FILE are set (but are exclusive)"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
local val="$def"
|
||||
|
||||
if [ -n "${var:-}" ]; then
|
||||
val="${var}"
|
||||
elif [ -n "${fileVar:-}" ]; then
|
||||
val="$(cat "${fileVar}")"
|
||||
fi
|
||||
|
||||
export "${1}"="$val"
|
||||
unset "${1}_FILE"
|
||||
}
|
||||
|
||||
export SEMAPHORE_CONFIG_PATH="${SEMAPHORE_CONFIG_PATH:-/etc/semaphore}"
|
||||
export SEMAPHORE_TMP_PATH="${SEMAPHORE_TMP_PATH:-/tmp/semaphore}"
|
||||
export ANSIBLE_CONFIG="${ANSIBLE_CONFIG:-${SEMAPHORE_TMP_PATH}/ansible.cfg}"
|
||||
export SEMAPHORE_DB_DIALECT="${SEMAPHORE_DB_DIALECT:-mysql}"
|
||||
export SEMAPHORE_DB_HOST="${SEMAPHORE_DB_HOST:-0.0.0.0}"
|
||||
export SEMAPHORE_DB_PATH="${SEMAPHORE_DB_PATH:-/var/lib/semaphore}"
|
||||
export SEMAPHORE_DB_PORT="${SEMAPHORE_DB_PORT:-}"
|
||||
export SEMAPHORE_DB="${SEMAPHORE_DB:-semaphore}"
|
||||
file_env 'SEMAPHORE_DB_USER' 'semaphore'
|
||||
file_env 'SEMAPHORE_DB_PASS' 'semaphore'
|
||||
export SEMAPHORE_WEB_ROOT="${SEMAPHORE_WEB_ROOT:-}"
|
||||
file_env 'SEMAPHORE_ADMIN' 'admin'
|
||||
export SEMAPHORE_ADMIN_EMAIL="${SEMAPHORE_ADMIN_EMAIL:-admin@localhost}"
|
||||
export SEMAPHORE_ADMIN_NAME="${SEMAPHORE_ADMIN_NAME:-Semaphore Admin}"
|
||||
file_env 'SEMAPHORE_ADMIN_PASSWORD' 'semaphorepassword'
|
||||
export SEMAPHORE_LDAP_ACTIVATED="${SEMAPHORE_LDAP_ACTIVATED:-no}"
|
||||
export SEMAPHORE_LDAP_HOST="${SEMAPHORE_LDAP_HOST:-}"
|
||||
export SEMAPHORE_LDAP_PORT="${SEMAPHORE_LDAP_PORT:-}"
|
||||
export SEMAPHORE_LDAP_NEEDTLS="${SEMAPHORE_LDAP_NEEDTLS:-no}"
|
||||
export SEMAPHORE_LDAP_DN_BIND="${SEMAPHORE_LDAP_DN_BIND:-}"
|
||||
file_env 'SEMAPHORE_LDAP_PASSWORD'
|
||||
export SEMAPHORE_LDAP_DN_SEARCH="${SEMAPHORE_LDAP_DN_SEARCH:-}"
|
||||
export SEMAPHORE_LDAP_SEARCH_FILTER="${SEMAPHORE_LDAP_SEARCH_FILTER:-(uid=%s)}"
|
||||
export SEMAPHORE_LDAP_MAPPING_DN="${SEMAPHORE_LDAP_MAPPING_DN:-dn}"
|
||||
export SEMAPHORE_LDAP_MAPPING_USERNAME="${SEMAPHORE_LDAP_MAPPING_USERNAME:-uid}"
|
||||
export SEMAPHORE_LDAP_MAPPING_FULLNAME="${SEMAPHORE_LDAP_MAPPING_FULLNAME:-cn}"
|
||||
export SEMAPHORE_LDAP_MAPPING_EMAIL="${SEMAPHORE_LDAP_MAPPING_EMAIL:-mail}"
|
||||
file_env 'SEMAPHORE_ACCESS_KEY_ENCRYPTION'
|
||||
|
||||
[ -d "${SEMAPHORE_TMP_PATH}" ] || mkdir -p "${SEMAPHORE_TMP_PATH}" || {
|
||||
echo "Can't create Semaphore tmp path ${SEMAPHORE_TMP_PATH}."
|
||||
exit 1
|
||||
}
|
||||
|
||||
[ -d "${SEMAPHORE_CONFIG_PATH}" ] || mkdir -p "${SEMAPHORE_CONFIG_PATH}" || {
|
||||
echo "Can't create Semaphore config path ${SEMAPHORE_CONFIG_PATH}."
|
||||
exit 1
|
||||
}
|
||||
|
||||
[ -d "${SEMAPHORE_DB_PATH}" ] || mkdir -p "${SEMAPHORE_DB_PATH}" || {
|
||||
echo "Can't create Semaphore data path ${SEMAPHORE_DB_PATH}."
|
||||
exit 1
|
||||
}
|
||||
|
||||
if [ "${SEMAPHORE_DB_DIALECT}" != 'bolt' ]; then
|
||||
echoerr "Attempting to connect to database ${SEMAPHORE_DB} on ${SEMAPHORE_DB_HOST}:${SEMAPHORE_DB_PORT} with user ${SEMAPHORE_DB_USER} ..."
|
||||
TIMEOUT=30
|
||||
|
||||
while ! $(nc -z "$SEMAPHORE_DB_HOST" "$SEMAPHORE_DB_PORT") >/dev/null 2>&1; do
|
||||
TIMEOUT=$(expr $TIMEOUT - 1)
|
||||
|
||||
if [ $TIMEOUT -eq 0 ]; then
|
||||
echoerr "Could not connect to database server. Exiting."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo -n "."
|
||||
sleep 1
|
||||
done
|
||||
fi
|
||||
|
||||
if [ -n "${SEMAPHORE_DB_PORT}" ]; then
|
||||
SEMAPHORE_DB_HOST="${SEMAPHORE_DB_HOST}:${SEMAPHORE_DB_PORT}"
|
||||
fi
|
||||
|
||||
case ${SEMAPHORE_DB_DIALECT} in
|
||||
mysql)
|
||||
SEMAPHORE_DB_DIALECT_ID=1
|
||||
;;
|
||||
bolt)
|
||||
SEMAPHORE_DB_DIALECT_ID=2
|
||||
;;
|
||||
postgres)
|
||||
SEMAPHORE_DB_DIALECT_ID=3
|
||||
;;
|
||||
*)
|
||||
echoerr "Unknown database dialect: ${SEMAPHORE_DB_DIALECT}"
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
|
||||
if [ ! -f "${SEMAPHORE_CONFIG_PATH}/config.json" ]; then
|
||||
echoerr "Generating ${SEMAPHORE_TMP_PATH}/config.stdin ..."
|
||||
cat << EOF > "${SEMAPHORE_TMP_PATH}/config.stdin"
|
||||
${SEMAPHORE_DB_DIALECT_ID}
|
||||
EOF
|
||||
|
||||
if [ "${SEMAPHORE_DB_DIALECT}" = "bolt" ]; then
|
||||
cat << EOF >> "${SEMAPHORE_TMP_PATH}/config.stdin"
|
||||
${SEMAPHORE_DB_PATH}/database.boltdb
|
||||
EOF
|
||||
else
|
||||
cat << EOF >> "${SEMAPHORE_TMP_PATH}/config.stdin"
|
||||
${SEMAPHORE_DB_HOST}
|
||||
${SEMAPHORE_DB_USER}
|
||||
${SEMAPHORE_DB_PASS}
|
||||
${SEMAPHORE_DB}
|
||||
EOF
|
||||
fi
|
||||
|
||||
cat << EOF >> "${SEMAPHORE_TMP_PATH}/config.stdin"
|
||||
${SEMAPHORE_TMP_PATH}
|
||||
${SEMAPHORE_WEB_ROOT}
|
||||
no
|
||||
no
|
||||
no
|
||||
no
|
||||
no
|
||||
${SEMAPHORE_LDAP_ACTIVATED}
|
||||
EOF
|
||||
|
||||
if [ "${SEMAPHORE_LDAP_ACTIVATED}" = "yes" ]; then
|
||||
cat << EOF >> "${SEMAPHORE_TMP_PATH}/config.stdin"
|
||||
${SEMAPHORE_LDAP_HOST}:${SEMAPHORE_LDAP_PORT}
|
||||
${SEMAPHORE_LDAP_NEEDTLS}
|
||||
${SEMAPHORE_LDAP_DN_BIND}
|
||||
${SEMAPHORE_LDAP_PASSWORD}
|
||||
${SEMAPHORE_LDAP_DN_SEARCH}
|
||||
${SEMAPHORE_LDAP_SEARCH_FILTER}
|
||||
${SEMAPHORE_LDAP_MAPPING_DN}
|
||||
${SEMAPHORE_LDAP_MAPPING_USERNAME}
|
||||
${SEMAPHORE_LDAP_MAPPING_FULLNAME}
|
||||
${SEMAPHORE_LDAP_MAPPING_EMAIL}
|
||||
EOF
|
||||
fi;
|
||||
|
||||
cat << EOF >> "${SEMAPHORE_TMP_PATH}/config.stdin"
|
||||
${SEMAPHORE_CONFIG_PATH}
|
||||
${SEMAPHORE_ADMIN}
|
||||
${SEMAPHORE_ADMIN_EMAIL}
|
||||
${SEMAPHORE_ADMIN_NAME}
|
||||
${SEMAPHORE_ADMIN_PASSWORD}
|
||||
EOF
|
||||
|
||||
echoerr "Executing semaphore setup"
|
||||
if test "$#" -ne 1; then
|
||||
/usr/local/bin/semaphore setup - < "${SEMAPHORE_TMP_PATH}/config.stdin"
|
||||
else
|
||||
"$1" setup - < "${SEMAPHORE_TMP_PATH}/config.stdin"
|
||||
fi
|
||||
fi
|
||||
|
||||
if test -f "${SEMAPHORE_CONFIG_PATH}/packages.txt"; then
|
||||
echoerr "Installing additional system dependencies"
|
||||
apk add --no-cache --upgrade \
|
||||
$(cat "${SEMAPHORE_CONFIG_PATH}/packages.txt" | xargs)
|
||||
else
|
||||
echoerr "No additional system dependencies to install"
|
||||
fi
|
||||
|
||||
if test -f "${SEMAPHORE_CONFIG_PATH}/requirements.txt"; then
|
||||
echoerr "Installing additional python dependencies"
|
||||
pip3 install --upgrade --user \
|
||||
-r "${SEMAPHORE_CONFIG_PATH}/requirements.txt"
|
||||
else
|
||||
echoerr "No additional python dependencies to install"
|
||||
fi
|
||||
|
||||
echoerr "Starting semaphore server"
|
||||
if test "$#" -ne 1; then
|
||||
exec /usr/local/bin/semaphore server --config "${SEMAPHORE_CONFIG_PATH}/config.json"
|
||||
else
|
||||
exec "$@"
|
||||
fi
|
@ -5,6 +5,7 @@ import (
|
||||
"fmt"
|
||||
"os"
|
||||
"strconv"
|
||||
"maps"
|
||||
|
||||
"github.com/ansible-semaphore/semaphore/db"
|
||||
"github.com/ansible-semaphore/semaphore/db_lib"
|
||||
@ -19,6 +20,7 @@ type LocalJob struct {
|
||||
Inventory db.Inventory
|
||||
Repository db.Repository
|
||||
Environment db.Environment
|
||||
Secret string
|
||||
Logger task_logger.Logger
|
||||
|
||||
App db_lib.LocalApp
|
||||
@ -90,6 +92,7 @@ func (t *LocalJob) getEnvironmentExtraVars(username string, incomingVersion *str
|
||||
|
||||
func (t *LocalJob) getEnvironmentExtraVarsJSON(username string, incomingVersion *string) (str string, err error) {
|
||||
extraVars := make(map[string]interface{})
|
||||
extraSecretVars := make(map[string]interface{})
|
||||
|
||||
if t.Environment.JSON != "" {
|
||||
err = json.Unmarshal([]byte(t.Environment.JSON), &extraVars)
|
||||
@ -97,6 +100,15 @@ func (t *LocalJob) getEnvironmentExtraVarsJSON(username string, incomingVersion
|
||||
return
|
||||
}
|
||||
}
|
||||
if t.Secret != "" {
|
||||
err = json.Unmarshal([]byte(t.Secret), &extraSecretVars)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
t.Secret = "{}"
|
||||
|
||||
maps.Copy(extraVars, extraSecretVars)
|
||||
|
||||
taskDetails := make(map[string]interface{})
|
||||
|
||||
|
@ -318,6 +318,8 @@ func (p *TaskPool) AddTask(taskObj db.Task, userID *int, projectID int) (newTask
|
||||
taskObj.Status = task_logger.TaskWaitingStatus
|
||||
taskObj.UserID = userID
|
||||
taskObj.ProjectID = projectID
|
||||
extraSecretVars := taskObj.Secret
|
||||
taskObj.Secret = "{}"
|
||||
|
||||
tpl, err := p.store.GetTemplate(projectID, taskObj.TemplateID)
|
||||
if err != nil {
|
||||
@ -375,6 +377,7 @@ func (p *TaskPool) AddTask(taskObj db.Task, userID *int, projectID int) (newTask
|
||||
Inventory: taskRunner.Inventory,
|
||||
Repository: taskRunner.Repository,
|
||||
Environment: taskRunner.Environment,
|
||||
Secret: extraSecretVars,
|
||||
Logger: app.SetLogger(&taskRunner),
|
||||
App: app,
|
||||
}
|
||||
|
@ -134,7 +134,7 @@ type ConfigType struct {
|
||||
|
||||
// SshConfigPath is a path to the custom SSH config file.
|
||||
// Default path is ~/.ssh/config.
|
||||
SshConfigPath string `json:"ssh_config_path" env:"SEMAPHORE_TMP_PATH"`
|
||||
SshConfigPath string `json:"ssh_config_path" env:"SEMAPHORE_SSH_PATH"`
|
||||
|
||||
GitClientId string `json:"git_client" rule:"^go_git|cmd_git$" env:"SEMAPHORE_GIT_CLIENT" default:"cmd_git"`
|
||||
|
||||
@ -598,7 +598,7 @@ func CheckUpdate() (updateAvailable *github.RepositoryRelease, err error) {
|
||||
}
|
||||
|
||||
updateAvailable = nil
|
||||
if (*releases[0].TagName)[1:] != Version {
|
||||
if (*releases[0].TagName)[1:] != Version() {
|
||||
updateAvailable = releases[0]
|
||||
}
|
||||
|
||||
|
@ -1,13 +0,0 @@
|
||||
[Unit]
|
||||
Description=Semaphore Ansible
|
||||
After=network.target
|
||||
|
||||
[Service]
|
||||
User=www-data
|
||||
Group=www-data
|
||||
ExecStart=/usr/bin/semaphore server --config /etc/semaphore/config.json
|
||||
ExecReload=/bin/kill -HUP $MAINPID
|
||||
Type=simple
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
19
util/version.go
Normal file
19
util/version.go
Normal file
@ -0,0 +1,19 @@
|
||||
package util
|
||||
|
||||
import (
|
||||
"strings"
|
||||
)
|
||||
|
||||
var (
|
||||
Ver = "undefined"
|
||||
Commit = "00000000"
|
||||
Date = ""
|
||||
)
|
||||
|
||||
func Version() string {
|
||||
return strings.Join([]string{
|
||||
Ver,
|
||||
Commit,
|
||||
Date,
|
||||
}, "-")
|
||||
}
|
@ -1,47 +0,0 @@
|
||||
// +build ignore
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"log"
|
||||
"os"
|
||||
"text/template"
|
||||
)
|
||||
|
||||
var versionTmpl = `package util
|
||||
|
||||
//Version is the Semaphore build version as a string
|
||||
var Version = "{{ .VERSION }}"
|
||||
`
|
||||
|
||||
func main(){
|
||||
|
||||
if len(os.Args) <= 1 {
|
||||
log.Fatalln("Must pass in version number")
|
||||
}
|
||||
|
||||
data := make(map[string]string)
|
||||
data["VERSION"] = os.Args[1]
|
||||
|
||||
tmpl := template.New("version")
|
||||
var err error
|
||||
if tmpl, err = tmpl.Parse(versionTmpl); err != nil {
|
||||
log.Fatalln(err)
|
||||
}
|
||||
|
||||
f, err := os.Create("util/version.go")
|
||||
if err != nil {
|
||||
log.Fatalln(err)
|
||||
}
|
||||
defer func(r *os.File) {
|
||||
err = r.Close()
|
||||
if err != nil {
|
||||
log.Fatalln(err)
|
||||
}
|
||||
}(f)
|
||||
|
||||
err = tmpl.Execute(f, data)
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
}
|
||||
}
|
38
web/package-lock.json
generated
38
web/package-lock.json
generated
@ -11441,15 +11441,21 @@
|
||||
}
|
||||
},
|
||||
"node_modules/nanoid": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/nanoid/-/nanoid-4.0.0.tgz",
|
||||
"integrity": "sha512-IgBP8piMxe/gf73RTQx7hmnhwz0aaEXYakvqZyE302IXW3HyVNhdNGC+O2MwMAVhLEnvXlvKtGbtJf6wvHihCg==",
|
||||
"version": "5.0.7",
|
||||
"resolved": "https://registry.npmjs.org/nanoid/-/nanoid-5.0.7.tgz",
|
||||
"integrity": "sha512-oLxFY2gd2IqnjcYyOXD8XGCftpGtZP2AbHbOkthDkvRywH5ayNtPVy9YlOPcHckXzbLTCHpkb7FB+yuxKV13pQ==",
|
||||
"dev": true,
|
||||
"funding": [
|
||||
{
|
||||
"type": "github",
|
||||
"url": "https://github.com/sponsors/ai"
|
||||
}
|
||||
],
|
||||
"bin": {
|
||||
"nanoid": "bin/nanoid.js"
|
||||
},
|
||||
"engines": {
|
||||
"node": "^14 || ^16 || >=18"
|
||||
"node": "^18 || >=20"
|
||||
}
|
||||
},
|
||||
"node_modules/nanomatch": {
|
||||
@ -13456,10 +13462,16 @@
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/postcss/node_modules/nanoid": {
|
||||
"version": "3.3.4",
|
||||
"resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.4.tgz",
|
||||
"integrity": "sha512-MqBkQh/OHTS2egovRtLk45wEyNXwF+cokD+1YPf9u5VfJiRdAiRwB2froX5Co9Rh20xs4siNPm8naNotSD6RBw==",
|
||||
"version": "3.3.7",
|
||||
"resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.7.tgz",
|
||||
"integrity": "sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==",
|
||||
"dev": true,
|
||||
"funding": [
|
||||
{
|
||||
"type": "github",
|
||||
"url": "https://github.com/sponsors/ai"
|
||||
}
|
||||
],
|
||||
"bin": {
|
||||
"nanoid": "bin/nanoid.cjs"
|
||||
},
|
||||
@ -27513,9 +27525,9 @@
|
||||
}
|
||||
},
|
||||
"nanoid": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/nanoid/-/nanoid-4.0.0.tgz",
|
||||
"integrity": "sha512-IgBP8piMxe/gf73RTQx7hmnhwz0aaEXYakvqZyE302IXW3HyVNhdNGC+O2MwMAVhLEnvXlvKtGbtJf6wvHihCg==",
|
||||
"version": "5.0.7",
|
||||
"resolved": "https://registry.npmjs.org/nanoid/-/nanoid-5.0.7.tgz",
|
||||
"integrity": "sha512-oLxFY2gd2IqnjcYyOXD8XGCftpGtZP2AbHbOkthDkvRywH5ayNtPVy9YlOPcHckXzbLTCHpkb7FB+yuxKV13pQ==",
|
||||
"dev": true
|
||||
},
|
||||
"nanomatch": {
|
||||
@ -28684,9 +28696,9 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"nanoid": {
|
||||
"version": "3.3.4",
|
||||
"resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.4.tgz",
|
||||
"integrity": "sha512-MqBkQh/OHTS2egovRtLk45wEyNXwF+cokD+1YPf9u5VfJiRdAiRwB2froX5Co9Rh20xs4siNPm8naNotSD6RBw==",
|
||||
"version": "3.3.7",
|
||||
"resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.7.tgz",
|
||||
"integrity": "sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==",
|
||||
"dev": true
|
||||
}
|
||||
}
|
||||
|
@ -13,6 +13,12 @@
|
||||
lazy-validation
|
||||
v-if="editedVar != null"
|
||||
>
|
||||
<v-alert
|
||||
:value="formError"
|
||||
color="error"
|
||||
>{{ formError }}
|
||||
</v-alert>
|
||||
|
||||
<v-text-field
|
||||
:label="$t('name2')"
|
||||
v-model.trim="editedVar.name"
|
||||
@ -39,6 +45,57 @@
|
||||
item-value="id"
|
||||
item-text="name"
|
||||
></v-select>
|
||||
|
||||
<v-data-table
|
||||
v-if="editedVar.type === 'enum'"
|
||||
:items="editedValues"
|
||||
:items-per-page="-1"
|
||||
class="elevation-1"
|
||||
hide-default-footer
|
||||
no-data-text="No values"
|
||||
>
|
||||
<template v-slot:item="props">
|
||||
<tr>
|
||||
<td class="pa-1">
|
||||
<v-text-field
|
||||
solo-inverted
|
||||
flat
|
||||
hide-details
|
||||
v-model="props.item.name"
|
||||
class="v-text-field--solo--no-min-height"
|
||||
></v-text-field>
|
||||
</td>
|
||||
<td class="pa-1">
|
||||
<v-text-field
|
||||
solo-inverted
|
||||
flat
|
||||
hide-details
|
||||
v-model="props.item.value"
|
||||
class="v-text-field--solo--no-min-height"
|
||||
></v-text-field>
|
||||
</td>
|
||||
<td style="width: 38px;">
|
||||
<v-icon
|
||||
small
|
||||
class="pa-1"
|
||||
@click="removeEditedVarValue(props.item)"
|
||||
>
|
||||
mdi-delete
|
||||
</v-icon>
|
||||
</td>
|
||||
</tr>
|
||||
</template>
|
||||
</v-data-table>
|
||||
|
||||
<div class="text-right mt-2">
|
||||
|
||||
<v-btn
|
||||
color="primary"
|
||||
v-if="editedVar.type === 'enum'"
|
||||
@click="addEditedVarValue()"
|
||||
>Add Value</v-btn>
|
||||
</div>
|
||||
|
||||
<v-checkbox
|
||||
:label="$t('required')"
|
||||
v-model="editedVar.required"
|
||||
@ -114,6 +171,7 @@ export default {
|
||||
return {
|
||||
editDialog: null,
|
||||
editedVar: null,
|
||||
editedValues: [],
|
||||
editedVarIndex: null,
|
||||
modifiedVars: null,
|
||||
varTypes: [{
|
||||
@ -122,29 +180,86 @@ export default {
|
||||
}, {
|
||||
id: 'int',
|
||||
name: 'Integer',
|
||||
}, {
|
||||
id: 'secret',
|
||||
name: 'Secret',
|
||||
}, {
|
||||
id: 'enum',
|
||||
name: 'Enum',
|
||||
}],
|
||||
formError: null,
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
addEditedVarValue() {
|
||||
this.editedValues.push({
|
||||
name: '',
|
||||
value: '',
|
||||
});
|
||||
},
|
||||
|
||||
removeEditedVarValue(val) {
|
||||
const i = this.editedValues.findIndex((v) => v.name === val.name);
|
||||
if (i > -1) {
|
||||
this.editedValues.splice(i, 1);
|
||||
}
|
||||
},
|
||||
|
||||
editVar(index) {
|
||||
this.editedVar = index != null ? { ...this.modifiedVars[index] } : {};
|
||||
|
||||
this.editedValues = [];
|
||||
this.editedValues.push(...(this.editedVar.values || []));
|
||||
this.editedVar.values = this.editedValues;
|
||||
|
||||
this.editedVarIndex = index;
|
||||
|
||||
if (this.$refs.form) {
|
||||
this.$refs.form.resetValidation();
|
||||
}
|
||||
|
||||
this.editDialog = true;
|
||||
},
|
||||
|
||||
saveVar() {
|
||||
this.formError = null;
|
||||
|
||||
if (!this.$refs.form.validate()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (this.editedVar.type === 'enum') {
|
||||
if (this.editedValues.length === 0) {
|
||||
this.formError = 'Enumeration must have values.';
|
||||
return;
|
||||
}
|
||||
|
||||
const uniq = new Set(this.editedValues.map((v) => v.name));
|
||||
|
||||
if (this.editedValues.length !== uniq.size) {
|
||||
this.formError = 'Enumeration values must have unique names.';
|
||||
return;
|
||||
}
|
||||
|
||||
this.editedValues.forEach((v) => {
|
||||
if (v.name === '') {
|
||||
this.formError = 'Value name cannot be empty.';
|
||||
}
|
||||
});
|
||||
|
||||
if (this.formError != null) {
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
this.editedVar.values = [];
|
||||
}
|
||||
|
||||
if (this.editedVarIndex != null) {
|
||||
this.modifiedVars[this.editedVarIndex] = this.editedVar;
|
||||
} else {
|
||||
this.modifiedVars.push(this.editedVar);
|
||||
}
|
||||
|
||||
this.editDialog = false;
|
||||
this.editedVar = null;
|
||||
this.$emit('change', this.modifiedVars);
|
||||
|
@ -45,19 +45,48 @@
|
||||
:disabled="formSaving"
|
||||
/>
|
||||
|
||||
<v-text-field
|
||||
v-for="(v) in template.survey_vars || []"
|
||||
:key="v.name"
|
||||
:label="v.title"
|
||||
:hint="v.description"
|
||||
v-model="editedEnvironment[v.name]"
|
||||
:required="v.required"
|
||||
:rules="[
|
||||
val => !v.required || !!val || v.title + $t('isRequired'),
|
||||
<div v-for="(v) in template.survey_vars || []" :key="v.name">
|
||||
|
||||
<v-text-field
|
||||
v-if="v.type === 'secret'"
|
||||
:label="v.title"
|
||||
:hint="v.description"
|
||||
v-model="editedSecretEnvironment[v.name]"
|
||||
:required="v.required"
|
||||
type="password"
|
||||
:rules="[
|
||||
val => !v.required || !!val || v.title + $t('isRequired'),
|
||||
]"
|
||||
/>
|
||||
|
||||
<v-select
|
||||
clearable
|
||||
v-else-if="v.type === 'enum'"
|
||||
:label="v.title + (v.required ? ' *' : '')"
|
||||
:hint="v.description"
|
||||
v-model="editedEnvironment[v.name]"
|
||||
:required="v.required"
|
||||
:rules="[
|
||||
val => !v.required || val != null || v.title + ' ' + $t('isRequired')
|
||||
]"
|
||||
:items="v.values"
|
||||
item-text="name"
|
||||
item-value="value"
|
||||
/>
|
||||
|
||||
<v-text-field
|
||||
v-else
|
||||
:label="v.title + (v.required ? ' *' : '')"
|
||||
:hint="v.description"
|
||||
v-model="editedEnvironment[v.name]"
|
||||
:required="v.required"
|
||||
:rules="[
|
||||
val => !v.required || !!val || v.title + ' ' + $t('isRequired'),
|
||||
val => !val || v.type !== 'int' || /^\d+$/.test(val) ||
|
||||
v.title + ' ' + $t('mustBeInteger'),
|
||||
]"
|
||||
/>
|
||||
/>
|
||||
</div>
|
||||
|
||||
<v-row no-gutters class="mt-6">
|
||||
<v-col cols="12" sm="6">
|
||||
@ -104,7 +133,6 @@
|
||||
text
|
||||
class="mb-2"
|
||||
>
|
||||
{{ $t('pleaseAllowOverridingCliArgumentInTaskTemplateSett') }}<br>
|
||||
<div style="position: relative; margin-top: 10px;">
|
||||
<video
|
||||
autoplay
|
||||
@ -155,6 +183,7 @@ export default {
|
||||
buildTasks: null,
|
||||
commitAvailable: null,
|
||||
editedEnvironment: null,
|
||||
editedSecretEnvironment: null,
|
||||
cmOptions: {
|
||||
tabSize: 2,
|
||||
mode: 'application/json',
|
||||
@ -214,6 +243,7 @@ export default {
|
||||
});
|
||||
|
||||
this.editedEnvironment = JSON.parse(v.environment || '{}');
|
||||
this.editedSecretEnvironment = JSON.parse(v.secret || '{}');
|
||||
this.commitAvailable = v.commit_hash != null;
|
||||
},
|
||||
|
||||
@ -225,6 +255,7 @@ export default {
|
||||
|
||||
beforeSave() {
|
||||
this.item.environment = JSON.stringify(this.editedEnvironment);
|
||||
this.item.secret = JSON.stringify(this.editedSecretEnvironment);
|
||||
},
|
||||
|
||||
async afterLoadData() {
|
||||
|
@ -130,7 +130,7 @@ export default {
|
||||
diff: 'Diff',
|
||||
advanced: 'Advanced',
|
||||
hide: 'Hide',
|
||||
pleaseAllowOverridingCliArgumentInTaskTemplateSett: 'Please allow overriding CLI argument in Task Template settings',
|
||||
pleaseAllowOverridingCliArgumentInTaskTemplateSett: 'To allow overriding CLI argument in Task Template settings',
|
||||
cliArgsJsonArrayExampleIMyinventoryshPrivatekeythe: 'CLI Args (JSON array). Example: [ "-i", "@myinventory.sh", "--private-key=/there/id_rsa", "-vvvv" ]',
|
||||
started: 'Started',
|
||||
author: 'Author',
|
||||
|
Loading…
Reference in New Issue
Block a user