Compare commits
34 Commits
84bac2f1ef
...
main
Author | SHA1 | Date | |
---|---|---|---|
b125237880 | |||
711f36f4da | |||
5ad147032e | |||
68ce724d31 | |||
a54002252c | |||
af00f3729d | |||
2f141ba9c1 | |||
3a32158272 | |||
612b1e078c | |||
5b0e7641b8 | |||
fd15ed45ee | |||
eb0a6d9483 | |||
4ead2aa92d | |||
28f45e37ee | |||
280a2d6c92 | |||
e8fd475820 | |||
58381805e9 | |||
ab47ee2e18 | |||
1d42c7f95c | |||
398db54e15 | |||
c6f62df2c2 | |||
3a5b246220 | |||
00e89bdc64 | |||
cc61dba1a8 | |||
ffed04c846 | |||
fd6520128e | |||
90dbbc1239 | |||
|
3c163b391c | ||
b380440f5a | |||
|
39ee09787c | ||
87e1749d49 | |||
64363a929c | |||
521b046940 | |||
e8b353b28d |
54
.drone.yml
54
.drone.yml
@@ -1,54 +0,0 @@
|
|||||||
kind: pipeline
|
|
||||||
type: docker
|
|
||||||
name: deploy
|
|
||||||
|
|
||||||
steps:
|
|
||||||
- name: Deploy to Portainer
|
|
||||||
image: alpine
|
|
||||||
commands:
|
|
||||||
- apk update
|
|
||||||
- apk add envsubst curl python3
|
|
||||||
- python3 -m ensurepip
|
|
||||||
- pip3 install requests python-dotenv --quiet
|
|
||||||
- python3 deploy/portainer/deploy.py
|
|
||||||
--PORTAINER https://dvportainer.privatedns.org
|
|
||||||
--PORTAINER_API_KEY=ptr_RwxH2Cd+htdD2FoFiG46erT9beyvj9VoF3BrQPtDH3Q=
|
|
||||||
--PORTAINER_EP=CICD-runner
|
|
||||||
--GITEA_API_KEY=f449c74ec7f04e54fe1e481eae43492b34cea406
|
|
||||||
--DEPLOY_REPO_URL=${DRONE_REPO_LINK}
|
|
||||||
--DEPLOY_BRANCH=${DRONE_SOURCE_BRANCH}
|
|
||||||
--DEPLOY_HOST=dvdemo.privatedns.org
|
|
||||||
|
|
||||||
trigger:
|
|
||||||
event:
|
|
||||||
- pull_request
|
|
||||||
action:
|
|
||||||
- opened
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
kind: pipeline
|
|
||||||
type: docker
|
|
||||||
name: undeploy
|
|
||||||
|
|
||||||
steps:
|
|
||||||
- name: Undeploy from Portainer
|
|
||||||
image: alpine
|
|
||||||
commands:
|
|
||||||
- apk update
|
|
||||||
- apk add envsubst curl python3
|
|
||||||
- python3 -m ensurepip
|
|
||||||
- pip3 install requests python-dotenv --quiet
|
|
||||||
- python3 deploy/portainer/undeploy.py
|
|
||||||
--PORTAINER https://dvportainer.privatedns.org
|
|
||||||
--PORTAINER_API_KEY=ptr_RwxH2Cd+htdD2FoFiG46erT9beyvj9VoF3BrQPtDH3Q=
|
|
||||||
--PORTAINER_EP=CICD-runner
|
|
||||||
--GITEA_API_KEY=f449c74ec7f04e54fe1e481eae43492b34cea406
|
|
||||||
--DEPLOY_REPO_URL=${DRONE_REPO_LINK}
|
|
||||||
--DEPLOY_BRANCH=${DRONE_COMMIT_BRANCH}
|
|
||||||
|
|
||||||
trigger:
|
|
||||||
event:
|
|
||||||
- pull_request
|
|
||||||
action:
|
|
||||||
- closed, merged
|
|
27
.gitea/workflows/DeployPR.yaml
Normal file
27
.gitea/workflows/DeployPR.yaml
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
name: Deploy PR
|
||||||
|
run-name: ${{ gitea.actor }} is deploying a PR
|
||||||
|
on:
|
||||||
|
pull_request:
|
||||||
|
types: [ opened, reopened ]
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
Deploy PR:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
container: catthehacker/ubuntu:act-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
- uses: actions/setup-python@v4
|
||||||
|
with:
|
||||||
|
python-version: '3.12.0'
|
||||||
|
- name: Install pip packages
|
||||||
|
run: pip install requests python-dotenv --quiet
|
||||||
|
- name: Run Deploy script
|
||||||
|
run: >
|
||||||
|
python deploy/portainer/deploy.py
|
||||||
|
--PORTAINER https://dvportainer.privatedns.org
|
||||||
|
--PORTAINER_API_KEY=ptr_RwxH2Cd+htdD2FoFiG46erT9beyvj9VoF3BrQPtDH3Q=
|
||||||
|
--PORTAINER_EP=CICD-runner
|
||||||
|
--GITEA_API_KEY=f449c74ec7f04e54fe1e481eae43492b34cea406
|
||||||
|
--DEPLOY_REPO_URL=${GITHUB_SERVER_URL}/${GITHUB_REPOSITORY}
|
||||||
|
--DEPLOY_BRANCH=${GITHUB_HEAD_REF}
|
||||||
|
--DEPLOY_HOST=dvdemo.privatedns.org
|
27
.gitea/workflows/UndeployPR.yaml
Normal file
27
.gitea/workflows/UndeployPR.yaml
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
name: Undeploy PR
|
||||||
|
run-name: ${{ gitea.actor }} is undeploying a PR
|
||||||
|
on:
|
||||||
|
pull_request:
|
||||||
|
types: [ closed ]
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
Deploy PR:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
container: catthehacker/ubuntu:act-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
- uses: actions/setup-python@v4
|
||||||
|
with:
|
||||||
|
python-version: '3.12.0'
|
||||||
|
- name: Install pip packages
|
||||||
|
run: pip install requests python-dotenv --quiet
|
||||||
|
- name: Run Undeploy script
|
||||||
|
run: >
|
||||||
|
python deploy/portainer/undeploy.py
|
||||||
|
--PORTAINER https://dvportainer.privatedns.org
|
||||||
|
--PORTAINER_API_KEY=ptr_RwxH2Cd+htdD2FoFiG46erT9beyvj9VoF3BrQPtDH3Q=
|
||||||
|
--PORTAINER_EP=CICD-runner
|
||||||
|
--GITEA_API_KEY=f449c74ec7f04e54fe1e481eae43492b34cea406
|
||||||
|
--DEPLOY_REPO_URL=${GITHUB_SERVER_URL}/${GITHUB_REPOSITORY}
|
||||||
|
--DEPLOY_BRANCH=${GITHUB_HEAD_REF}
|
||||||
|
|
1
deploy/portainer/.env.app
Normal file
1
deploy/portainer/.env.app
Normal file
@@ -0,0 +1 @@
|
|||||||
|
HOST=dvdemo.privatedns.org
|
@@ -3,5 +3,4 @@ PORTAINER_API_KEY=ptr_RwxH2Cd+htdD2FoFiG46erT9beyvj9VoF3BrQPtDH3Q=
|
|||||||
PORTAINER_EP=CICD-runner
|
PORTAINER_EP=CICD-runner
|
||||||
GITEA_API_KEY=f449c74ec7f04e54fe1e481eae43492b34cea406
|
GITEA_API_KEY=f449c74ec7f04e54fe1e481eae43492b34cea406
|
||||||
DEPLOY_REPO_URL=https://dvgit.privatedns.org/lars/DeployTests
|
DEPLOY_REPO_URL=https://dvgit.privatedns.org/lars/DeployTests
|
||||||
DEPLOY_BRANCH=main
|
DEPLOY_BRANCH=main
|
||||||
DEPLOY_HOST=dvdemo.privatedns.org
|
|
@@ -6,12 +6,12 @@ import argparse
|
|||||||
import requests
|
import requests
|
||||||
import json
|
import json
|
||||||
import uuid
|
import uuid
|
||||||
from dotenv import load_dotenv
|
from dotenv import load_dotenv, dotenv_values
|
||||||
from string import Template
|
from string import Template
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from urllib.parse import urlparse
|
from urllib.parse import urlparse
|
||||||
|
|
||||||
load_dotenv()
|
load_dotenv('.env.deploy')
|
||||||
|
|
||||||
required_env_vars = {
|
required_env_vars = {
|
||||||
'PORTAINER': 'The portainer instance to deploy to',
|
'PORTAINER': 'The portainer instance to deploy to',
|
||||||
@@ -20,7 +20,6 @@ required_env_vars = {
|
|||||||
'GITEA_API_KEY': 'API-Key to access Gitea instance',
|
'GITEA_API_KEY': 'API-Key to access Gitea instance',
|
||||||
'DEPLOY_REPO_URL': 'The repository URL to deploy',
|
'DEPLOY_REPO_URL': 'The repository URL to deploy',
|
||||||
'DEPLOY_BRANCH': 'The branch to deploy',
|
'DEPLOY_BRANCH': 'The branch to deploy',
|
||||||
'DEPLOY_HOST': 'The host name under which the deployment will be reachable',
|
|
||||||
}
|
}
|
||||||
|
|
||||||
# Try getting all arguments from (in order): 1 command line, 2 .env file, 3 Environment
|
# Try getting all arguments from (in order): 1 command line, 2 .env file, 3 Environment
|
||||||
@@ -58,7 +57,7 @@ try:
|
|||||||
json_endpoints = response.json()
|
json_endpoints = response.json()
|
||||||
|
|
||||||
except requests.exceptions.RequestException as err:
|
except requests.exceptions.RequestException as err:
|
||||||
raise Exception(f'Could not retrieve portainer endpoints: {err}')
|
raise Exception(f'Could not retrieve portainer endpoints: {err}. \n\n Response: {response.content}')
|
||||||
|
|
||||||
endpoint_id = None
|
endpoint_id = None
|
||||||
for endpoint in json_endpoints:
|
for endpoint in json_endpoints:
|
||||||
@@ -78,6 +77,17 @@ owner = repo_parts[0]
|
|||||||
repo = repo_parts[1]
|
repo = repo_parts[1]
|
||||||
|
|
||||||
### Template substitution for the portainer stack deployment ###
|
### Template substitution for the portainer stack deployment ###
|
||||||
|
|
||||||
|
app_env = dotenv_values('.env.app')
|
||||||
|
portainer_deploy_env = [{
|
||||||
|
"name": "COMPOSE_PROJECT_NAME",
|
||||||
|
"value": args.DEPLOY_BRANCH
|
||||||
|
}]
|
||||||
|
for key, value in app_env.items():
|
||||||
|
portainer_deploy_env.append({
|
||||||
|
"name": key,
|
||||||
|
"value": os.getenv(value) if value.startswith("$") else value
|
||||||
|
})
|
||||||
portainer_deploy_payload = {
|
portainer_deploy_payload = {
|
||||||
"additionalFiles": [
|
"additionalFiles": [
|
||||||
"deploy/portainer/portainer_deploy.docker-compose.yml"
|
"deploy/portainer/portainer_deploy.docker-compose.yml"
|
||||||
@@ -86,16 +96,7 @@ portainer_deploy_payload = {
|
|||||||
"webhook": deploy_webhook
|
"webhook": deploy_webhook
|
||||||
},
|
},
|
||||||
"composeFile": "docker-compose.yml",
|
"composeFile": "docker-compose.yml",
|
||||||
"env": [
|
"env": portainer_deploy_env,
|
||||||
{
|
|
||||||
"name": "HOST",
|
|
||||||
"value": args.DEPLOY_HOST
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "COMPOSE_PROJECT_NAME",
|
|
||||||
"value": args.DEPLOY_BRANCH
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"fromAppTemplate": False,
|
"fromAppTemplate": False,
|
||||||
"name": f"{owner}_{repo}_{args.DEPLOY_BRANCH.replace('/', '_')}".lower(),
|
"name": f"{owner}_{repo}_{args.DEPLOY_BRANCH.replace('/', '_')}".lower(),
|
||||||
"repositoryAuthentication": True,
|
"repositoryAuthentication": True,
|
||||||
@@ -114,7 +115,7 @@ try:
|
|||||||
deploy_response = response.json()
|
deploy_response = response.json()
|
||||||
|
|
||||||
except requests.exceptions.RequestException as err:
|
except requests.exceptions.RequestException as err:
|
||||||
raise Exception(f'Could not deploy portainer stack: {err}')
|
raise Exception(f'Could not deploy portainer stack: {err}.\n\n Response: {response.content}')
|
||||||
|
|
||||||
### Add Webhook to Gitea ###
|
### Add Webhook to Gitea ###
|
||||||
webhook_payload = {
|
webhook_payload = {
|
||||||
@@ -138,5 +139,5 @@ try:
|
|||||||
webhook_response = response.json()
|
webhook_response = response.json()
|
||||||
|
|
||||||
except requests.exceptions.RequestException as err:
|
except requests.exceptions.RequestException as err:
|
||||||
raise Exception(f'Could not add webhook to Gitea: {err}')
|
raise Exception(f'Could not add webhook to Gitea: {err}.\n\n Response: {response.content}')
|
||||||
print(f'Successfully deployed project')
|
print(f'Successfully deployed project')
|
@@ -1,10 +1,10 @@
|
|||||||
version: '3.4'
|
version: '3'
|
||||||
|
|
||||||
services:
|
services:
|
||||||
http-echo:
|
http-echo:
|
||||||
networks:
|
networks:
|
||||||
- cicd
|
- cicd
|
||||||
|
|
||||||
networks:
|
networks:
|
||||||
cicd:
|
cicd:
|
||||||
driver: bridge
|
driver: bridge
|
||||||
|
@@ -11,7 +11,7 @@ from string import Template
|
|||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from urllib.parse import urlparse
|
from urllib.parse import urlparse
|
||||||
|
|
||||||
load_dotenv()
|
load_dotenv('.env.deploy')
|
||||||
|
|
||||||
required_env_vars = {
|
required_env_vars = {
|
||||||
'PORTAINER': 'The portainer instance to deploy to',
|
'PORTAINER': 'The portainer instance to deploy to',
|
||||||
@@ -53,7 +53,7 @@ try:
|
|||||||
json_endpoints = endpoint_response.json()
|
json_endpoints = endpoint_response.json()
|
||||||
|
|
||||||
except requests.exceptions.RequestException as err:
|
except requests.exceptions.RequestException as err:
|
||||||
raise Exception(f'Could not retrieve portainer endpoints: {err}')
|
raise Exception(f'Could not retrieve portainer endpoints: {err}.\n\n Response: {endpoint_response.content}')
|
||||||
|
|
||||||
endpoint_id = None
|
endpoint_id = None
|
||||||
for endpoint in json_endpoints:
|
for endpoint in json_endpoints:
|
||||||
@@ -73,7 +73,7 @@ try:
|
|||||||
json_stacks = stacks_response.json()
|
json_stacks = stacks_response.json()
|
||||||
|
|
||||||
except requests.exceptions.RequestException as err:
|
except requests.exceptions.RequestException as err:
|
||||||
raise Exception(f'Could not retrieve portainer stacks: {err}')
|
raise Exception(f'Could not retrieve portainer stacks: {err}.\n\n Response: {stacks_response.content}')
|
||||||
|
|
||||||
stack_id = None
|
stack_id = None
|
||||||
stack_webhook = None
|
stack_webhook = None
|
||||||
@@ -112,7 +112,7 @@ try:
|
|||||||
json_webhooks = get_webhooks_response.json()
|
json_webhooks = get_webhooks_response.json()
|
||||||
|
|
||||||
except requests.exceptions.RequestException as err:
|
except requests.exceptions.RequestException as err:
|
||||||
raise Exception(f'Could not get webhooks from Gitea: {err}')
|
raise Exception(f'Could not get webhooks from Gitea: {err}.\n\n Response:{get_webhooks_response.content}')
|
||||||
|
|
||||||
webhook_id = None
|
webhook_id = None
|
||||||
for webhook in json_webhooks:
|
for webhook in json_webhooks:
|
||||||
@@ -128,21 +128,19 @@ else:
|
|||||||
### Remove Webhook from Gitea ###
|
### Remove Webhook from Gitea ###
|
||||||
remove_webhook_url = f"{gitea}/api/v1/repos/{repo_path}/hooks/{webhook_id}"
|
remove_webhook_url = f"{gitea}/api/v1/repos/{repo_path}/hooks/{webhook_id}"
|
||||||
try:
|
try:
|
||||||
#TODO: Webhooks are returned paginated, this only checks first page
|
|
||||||
del_webhooks_response = requests.delete(remove_webhook_url, headers=gitea_headers)
|
del_webhooks_response = requests.delete(remove_webhook_url, headers=gitea_headers)
|
||||||
del_webhooks_response.raise_for_status() # Raise HTTPError for bad requests
|
del_webhooks_response.raise_for_status() # Raise HTTPError for bad requests
|
||||||
|
|
||||||
except requests.exceptions.RequestException as err:
|
except requests.exceptions.RequestException as err:
|
||||||
raise Exception(f"Could not delete webhook '{webhook_id}' from Gitea: {err}")
|
raise Exception(f"Could not delete webhook '{webhook_id}' from Gitea: {err}.\n\n Response: {del_webhooks_response.content}")
|
||||||
|
|
||||||
## Remove Stack from Portainer ###
|
## Remove Stack from Portainer ###
|
||||||
remove_stack_url = f"{args.PORTAINER}/api/stacks/{stack_id}?endpointId={endpoint_id}"
|
remove_stack_url = f"{args.PORTAINER}/api/stacks/{stack_id}?endpointId={endpoint_id}"
|
||||||
try:
|
try:
|
||||||
#TODO: Webhooks are returned paginated, this only checks first page
|
|
||||||
del_stack_response = requests.delete(remove_stack_url, headers=portainer_headers)
|
del_stack_response = requests.delete(remove_stack_url, headers=portainer_headers)
|
||||||
del_stack_response.raise_for_status() # Raise HTTPError for bad requests
|
del_stack_response.raise_for_status() # Raise HTTPError for bad requests
|
||||||
|
|
||||||
except requests.exceptions.RequestException as err:
|
except requests.exceptions.RequestException as err:
|
||||||
raise Exception(f"Could not delete stack '{stack_id}' from Portainer: {err}")
|
raise Exception(f"Could not delete stack '{stack_id}' from Portainer: {err}.\n\n Response: {del_stack_response.content}")
|
||||||
|
|
||||||
print(f'Successfully undeployed project')
|
print(f'Successfully undeployed project')
|
@@ -1,8 +1,11 @@
|
|||||||
version: '3.4'
|
version: '3.4'
|
||||||
|
|
||||||
services:
|
services:
|
||||||
http-echo:
|
http-echo:
|
||||||
image: mendhak/http-https-echo:latest
|
build:
|
||||||
|
image: ${COMPOSE_PROJECT_NAME}_httpecho
|
||||||
|
context: ./
|
||||||
|
dockerfile: httpecho.Dockerfile
|
||||||
expose:
|
expose:
|
||||||
- 8080
|
- 8080
|
||||||
environment:
|
environment:
|
||||||
|
2
httpecho.Dockerfile
Normal file
2
httpecho.Dockerfile
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
FROM mendhak/http-https-echo:latest
|
||||||
|
RUN echo "Hello"
|
Reference in New Issue
Block a user