Compare commits

...

45 Commits

Author SHA1 Message Date
b125237880 Compose image 2023-10-06 15:55:37 -05:00
711f36f4da Do triggeredoo 2023-10-06 15:53:49 -05:00
5ad147032e Fix again 2023-10-06 15:52:33 -05:00
68ce724d31 Fix 'content' 2023-10-06 15:51:01 -05:00
a54002252c Some deploy updates 2023-10-06 15:40:34 -05:00
af00f3729d Use build in compose 2023-10-06 15:37:44 -05:00
2f141ba9c1 Update .gitea/workflows/UndeployPR.yaml
All checks were successful
Deploy PR / Deploy PR (pull_request) Successful in 30s
Undeploy PR / Deploy PR (pull_request) Successful in 31s
2023-10-05 02:09:03 +00:00
3a32158272 Update .gitea/workflows/DeployPR.yaml 2023-10-05 02:08:53 +00:00
612b1e078c Update .gitea/workflows/UndeployPR.yaml
Some checks failed
Deploy PR / Deploy PR (pull_request) Failing after 27s
Undeploy PR / Deploy PR (pull_request) Failing after 30s
2023-10-05 02:05:13 +00:00
5b0e7641b8 Update .gitea/workflows/DeployPR.yaml 2023-10-05 02:04:57 +00:00
fd15ed45ee Update .gitea/workflows/UndeployPR.yaml
Some checks failed
Deploy PR / Deploy PR (pull_request) Failing after 1m5s
Undeploy PR / Deploy PR (pull_request) Failing after 26s
2023-10-05 01:45:20 +00:00
eb0a6d9483 Update .gitea/workflows/DeployPR.yaml 2023-10-05 01:45:11 +00:00
4ead2aa92d Update .gitea/workflows/UndeployPR.yaml
Some checks failed
Deploy PR / Deploy PR (pull_request) Failing after 1m3s
Undeploy PR / Deploy PR (pull_request) Failing after 6s
2023-10-05 01:35:30 +00:00
28f45e37ee Update .gitea/workflows/DeployPR.yaml 2023-10-05 01:35:19 +00:00
280a2d6c92 Update .gitea/workflows/UndeployPR.yaml
Some checks failed
Deploy PR / Deploy PR (pull_request) Failing after 5s
Undeploy PR / Deploy PR (pull_request) Failing after 51s
2023-10-05 01:22:54 +00:00
e8fd475820 Update .gitea/workflows/DeployPR.yaml 2023-10-05 01:22:40 +00:00
58381805e9 Update .gitea/workflows/UndeployPR.yaml
Some checks failed
Deploy PR / Deploy PR (pull_request) Failing after 5s
Undeploy PR / Deploy PR (pull_request) Failing after 6s
2023-10-05 01:14:17 +00:00
ab47ee2e18 Update .gitea/workflows/DeployPR.yaml 2023-10-05 01:13:50 +00:00
1d42c7f95c Update .gitea/workflows/DeployPR.yaml
Some checks failed
Deploy PR / Deploy PR (pull_request) Failing after 5s
2023-10-05 01:09:15 +00:00
398db54e15 Update .gitea/workflows/UndeployPR.yaml
Some checks failed
Deploy PR / Deploy PR (pull_request) Failing after 5s
Undeploy PR / Deploy PR (pull_request) Failing after 5s
2023-10-05 01:02:32 +00:00
c6f62df2c2 Update .gitea/workflows/DeployPR.yaml 2023-10-05 01:02:21 +00:00
3a5b246220 Merge pull request 'ActRunner' (#8) from ActRunner into main
Reviewed-on: #8
2023-10-05 00:59:46 +00:00
00e89bdc64 Update .gitea/workflows/UndeployPR.yaml
Some checks failed
Undeploy PR / Deploy PR (pull_request) Failing after 52s
2023-10-05 00:59:08 +00:00
cc61dba1a8 Update .gitea/workflows/DeployPR.yaml 2023-10-05 00:58:47 +00:00
ffed04c846 Delete .drone.yml 2023-10-05 00:56:03 +00:00
fd6520128e Merge branch 'ActRunner' of http://localhost:3000/larsito/DeployTests into ActRunner
All checks were successful
continuous-integration/drone/pr Build is passing
2023-10-04 15:36:22 -05:00
90dbbc1239 Try multiline run block 2023-10-04 15:35:58 -05:00
larsito
3c163b391c Merge branch 'main' into ActRunner 2023-10-04 20:33:50 +00:00
b380440f5a Fix steps syntax in workflow 2023-10-04 15:33:02 -05:00
larsito
39ee09787c Merge pull request 'Add Gitea workflow' (#1) from ActRunner into main
Reviewed-on: http://localhost:3000/larsito/DeployTests/pulls/1
2023-10-04 20:30:22 +00:00
87e1749d49 Add Gitea workflow 2023-10-04 15:29:08 -05:00
64363a929c Remove whiteline to recognize pipeline 2023-10-03 21:34:15 -05:00
521b046940 Merge branch 'main' of https://dvgit.privatedns.org/lars/DeployTests
All checks were successful
continuous-integration/drone/pr Build is passing
2023-10-03 21:22:04 -05:00
e8b353b28d Trigger on closed 2023-10-03 21:21:54 -05:00
84bac2f1ef Merge pull request 'NewBranch' (#4) from NewBranch into main
Reviewed-on: #4
2023-10-04 02:19:22 +00:00
12255dad5f Back to 8080 2023-10-04 02:18:41 +00:00
d165ef0e20 Merge branch 'main' into NewBranch 2023-10-04 02:17:56 +00:00
8d86f4beac Add undeploy 2023-10-03 21:17:38 -05:00
6d58f79915 Expose 8081 2023-10-03 20:18:25 +00:00
97e02bea1b Use Source branch
All checks were successful
continuous-integration/drone/pr Build is passing
2023-10-03 15:16:09 -05:00
5b28a51b97 Update .env
All checks were successful
continuous-integration/drone/pr Build is passing
2023-10-03 20:11:09 +00:00
eb5d075aed Update .env 2023-10-03 20:10:35 +00:00
b9fe963cab Update .env 2023-10-03 20:10:15 +00:00
0ad30129c4 Use Branch instead of Ref 2023-10-03 15:09:43 -05:00
7f1796bd31 Add Branch Name param 2023-10-03 14:58:51 -05:00
11 changed files with 269 additions and 109 deletions

View File

@@ -1,27 +0,0 @@
kind: pipeline
type: docker
name: deploy
steps:
- name: Push 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_REF=${DRONE_COMMIT_REF}
--DEPLOY_HOST=dvdemo.privatedns.org
--DEPLOY_NAME=${DRONE_COMMIT_SHA}
trigger:
event:
- pull_request
action:
- opened

2
.env
View File

@@ -1,2 +1,2 @@
HOST=dvdemo.localhost
HOST=dvdemo1.localhost
ECHO_PATH=echo

View 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

View 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}

View File

@@ -0,0 +1 @@
HOST=dvdemo.privatedns.org

View File

@@ -3,7 +3,4 @@ PORTAINER_API_KEY=ptr_RwxH2Cd+htdD2FoFiG46erT9beyvj9VoF3BrQPtDH3Q=
PORTAINER_EP=CICD-runner
GITEA_API_KEY=f449c74ec7f04e54fe1e481eae43492b34cea406
DEPLOY_REPO_URL=https://dvgit.privatedns.org/lars/DeployTests
DEPLOY_REF=refs/heads/main
DEPLOY_HOST=dvdemo.privatedns.org
DEPLOY_PROJECT=ManualDeployTests
DEPLOY_NAME=ManualDeploy
DEPLOY_BRANCH=main

View File

@@ -6,12 +6,12 @@ import argparse
import requests
import json
import uuid
from dotenv import load_dotenv
from dotenv import load_dotenv, dotenv_values
from string import Template
from pathlib import Path
from urllib.parse import urlparse
load_dotenv()
load_dotenv('.env.deploy')
required_env_vars = {
'PORTAINER': 'The portainer instance to deploy to',
@@ -19,9 +19,7 @@ required_env_vars = {
'PORTAINER_EP': 'Portainer Environment EndPoint to deploy to',
'GITEA_API_KEY': 'API-Key to access Gitea instance',
'DEPLOY_REPO_URL': 'The repository URL to deploy',
'DEPLOY_REF': 'The git ref to deploy',
'DEPLOY_HOST': 'The host name under which the deployment will be reachable',
'DEPLOY_NAME': 'Custom name to use as the deployment name',
'DEPLOY_BRANCH': 'The branch to deploy',
}
# Try getting all arguments from (in order): 1 command line, 2 .env file, 3 Environment
@@ -44,26 +42,14 @@ if not_parsed:
parser.print_help()
sys.exit(1)
# Deploy variables to substitute in portainer deploy template
deploy_variables = {key: getattr(args, key) for key in
['DEPLOY_REPO_URL', 'DEPLOY_HOST', 'DEPLOY_NAME', 'DEPLOY_REF']
}
deploy_variables['DEPLOY_WEBHOOK'] = str(uuid.uuid4())
portainer=args.PORTAINER
portainer_api_key=args.PORTAINER_API_KEY
portainer_ep=args.PORTAINER_EP
gitea_api_key=args.GITEA_API_KEY
deploy_repo=deploy_variables['DEPLOY_REPO_URL']
deploy_webhook=deploy_variables['DEPLOY_WEBHOOK']
deploy_ref=deploy_variables['DEPLOY_REF']
deploy_webhook = str(uuid.uuid4())
### Find CICD-runner portainer environment endpointId ###
portainer_headers = {
'Content-Type': 'application/json',
'X-API-Key': portainer_api_key,
'X-API-Key': args.PORTAINER_API_KEY
}
endpoint_url = f'{portainer}/api/endpoints'
endpoint_url = f'{args.PORTAINER}/api/endpoints'
json_endpoints = None
try:
response = requests.get(endpoint_url, headers=portainer_headers)
@@ -71,83 +57,81 @@ try:
json_endpoints = response.json()
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
for endpoint in json_endpoints:
if endpoint["Name"] == portainer_ep:
if endpoint["Name"] == args.PORTAINER_EP:
endpoint_id = endpoint["Id"]
break
if endpoint_id is None:
raise Exception(f'Portainer endpoint \'{portainer_ep}\' not found.')
raise Exception(f'Portainer endpoint \'{args.PORTAINER_EP}\' not found.')
else:
print(f'Found portainer endpoint \'{portainer_ep}\' has id: \'{endpoint_id}\'.')
print(f'Found portainer endpoint \'{args.PORTAINER_EP}\' has id: \'{endpoint_id}\'.')
### Template substitution for the portainer stack deployment ###
portainer_deploy_payload = {
"additionalFiles": [
"deploy/portainer/portainer_deploy.docker-compose.yml"
],
"autoUpdate": {
"webhook": f"{deploy_variables['DEPLOY_WEBHOOK']}"
},
"composeFile": "docker-compose.yml",
"env": [
{
"name": "HOST",
"value": f"{deploy_variables['DEPLOY_HOST']}"
},
{
"name": "COMPOSE_PROJECT_NAME",
"value": f"{deploy_variables['DEPLOY_NAME']}"
}
],
"fromAppTemplate": False,
"name": f"{deploy_variables['DEPLOY_NAME']}",
"repositoryAuthentication": True,
"repositoryUsername": "cicd",
"repositoryPassword": "gJ6@$7ZjWGyV4%i",
"repositoryReferenceName": f"{deploy_variables['DEPLOY_REF']}",
"repositoryURL": f"{deploy_variables['DEPLOY_REPO_URL']}",
"tlsskipVerify": False
}
### Deploy to portainer ###
deploy_url = f'{portainer}/api/stacks/create/standalone/repository?endpointId={endpoint_id}'
try:
response = requests.post(deploy_url, headers=portainer_headers, json=portainer_deploy_payload)
response.raise_for_status() # Raise HTTPError for bad requests
deploy_response = response.json()
except requests.exceptions.RequestException as err:
raise Exception(f'Could not deploy portainer stack: {err}')
### Add Webhook to Gitea ###
repo_url = urlparse(deploy_repo)
repo_url = urlparse(args.DEPLOY_REPO_URL)
gitea = f"{repo_url.scheme}://{repo_url.netloc}"
repo_path = repo_url.path
repo_parts = repo_path.strip('/').split('/')
owner = repo_parts[0]
repo = repo_parts[1]
ref_parts = deploy_ref.strip('/').split('/')
branch = ref_parts[-1]
### 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 = {
"additionalFiles": [
"deploy/portainer/portainer_deploy.docker-compose.yml"
],
"autoUpdate": {
"webhook": deploy_webhook
},
"composeFile": "docker-compose.yml",
"env": portainer_deploy_env,
"fromAppTemplate": False,
"name": f"{owner}_{repo}_{args.DEPLOY_BRANCH.replace('/', '_')}".lower(),
"repositoryAuthentication": True,
"repositoryUsername": "cicd",
"repositoryPassword": "gJ6@$7ZjWGyV4%i",
"repositoryReferenceName": f"refs/heads/{args.DEPLOY_BRANCH}",
"repositoryURL": args.DEPLOY_REPO_URL,
"tlsskipVerify": False
}
### Deploy to portainer ###
deploy_url = f'{args.PORTAINER}/api/stacks/create/standalone/repository?endpointId={endpoint_id}'
try:
response = requests.post(deploy_url, headers=portainer_headers, json=portainer_deploy_payload)
response.raise_for_status() # Raise HTTPError for bad requests
deploy_response = response.json()
except requests.exceptions.RequestException as err:
raise Exception(f'Could not deploy portainer stack: {err}.\n\n Response: {response.content}')
### Add Webhook to Gitea ###
webhook_payload = {
"type": "gitea",
"branch_filter": f"{branch}",
"branch_filter": f"{args.DEPLOY_BRANCH}",
"config": {
"url": f"{portainer}/api/stacks/webhooks/{deploy_webhook}",
"url": f"{args.PORTAINER}/api/stacks/webhooks/{deploy_webhook}",
"content_type": "json"
},
"events": ["push"], # You can specify other events as needed
"active": True
}
webhook_url = f'{gitea}/api/v1/repos/{owner}/{repo}/hooks'
webhook_url = f'{gitea}/api/v1/repos/{repo_path}/hooks'
webhook_headers = {
"Authorization": f"token {gitea_api_key}"
"Authorization": f"token {args.GITEA_API_KEY}"
}
try:
response = requests.post(webhook_url, headers=webhook_headers, json=webhook_payload)
@@ -155,5 +139,5 @@ try:
webhook_response = response.json()
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')

View File

@@ -1,4 +1,4 @@
version: '3.4'
version: '3'
services:
http-echo:

View File

@@ -0,0 +1,146 @@
#!/usr/bin/env python3
import os
import sys
import argparse
import requests
import json
import uuid
from dotenv import load_dotenv
from string import Template
from pathlib import Path
from urllib.parse import urlparse
load_dotenv('.env.deploy')
required_env_vars = {
'PORTAINER': 'The portainer instance to deploy to',
'PORTAINER_API_KEY': 'API-Key to access portainer instance',
'PORTAINER_EP': 'Portainer Environment EndPoint to deploy to',
'GITEA_API_KEY': 'API-Key to access Gitea instance',
'DEPLOY_REPO_URL': 'The repository URL to deploy',
'DEPLOY_BRANCH': 'The branch to deploy'
}
# Try getting all arguments from (in order): 1 command line, 2 .env file, 3 Environment
parser = argparse.ArgumentParser(description='Deploys a docker compose application to portainer.')
for var, usage in required_env_vars.items():
parser.add_argument(f'--{var}', default=os.getenv(var, None), help=usage)
args = parser.parse_args()
# Check if all were parsed
not_parsed = []
for var, usage in required_env_vars.items():
if not getattr(args, var):
not_parsed.append(var)
else:
print(f'--{var}: {getattr(args, var)}')
if not_parsed:
print(f"Error: The following required environment variables were not provided: {', '.join(not_parsed)}")
parser.print_help()
sys.exit(1)
portainer_headers = {
'Content-Type': 'application/json',
'X-API-Key': args.PORTAINER_API_KEY
}
endpoint_url = f'{args.PORTAINER}/api/endpoints'
try:
endpoint_response = requests.get(endpoint_url, headers=portainer_headers)
endpoint_response.raise_for_status() # Raise HTTPError for bad requests
json_endpoints = endpoint_response.json()
except requests.exceptions.RequestException as err:
raise Exception(f'Could not retrieve portainer endpoints: {err}.\n\n Response: {endpoint_response.content}')
endpoint_id = None
for endpoint in json_endpoints:
if endpoint["Name"] == args.PORTAINER_EP:
endpoint_id = endpoint["Id"]
break
if endpoint_id is None:
raise Exception(f'Portainer endpoint \'{args.PORTAINER_EP}\' not found.')
else:
print(f'Found portainer endpoint \'{args.PORTAINER_EP}\' has id: \'{endpoint_id}\'.')
# ?filters=\{'EndpointId':'{endpoint_id}'\}
stacks_url = f"{args.PORTAINER}/api/stacks"
try:
stacks_response = requests.get(stacks_url, headers=portainer_headers)
stacks_response.raise_for_status() # Raise HTTPError for bad requests
json_stacks = stacks_response.json()
except requests.exceptions.RequestException as err:
raise Exception(f'Could not retrieve portainer stacks: {err}.\n\n Response: {stacks_response.content}')
stack_id = None
stack_webhook = None
for stack in json_stacks:
if (
stack['GitConfig'] is not None
and stack['GitConfig']['URL'] == args.DEPLOY_REPO_URL
and stack['GitConfig']['ReferenceName'] == f"refs/heads/{args.DEPLOY_BRANCH}"
):
stack_id = stack["Id"]
stack_webhook = stack["AutoUpdate"]["Webhook"]
break;
if stack_id is None or stack_webhook is None:
raise Exception(f"Portainer stack with url:'{args.DEPLOY_REPO_URL}' and branch:'{args.DEPLOY_BRANCH}' not found.")
else:
print(f"Found portainer stack to remove with url:'{args.DEPLOY_REPO_URL}' and branch:'{args.DEPLOY_BRANCH}', stack has id: '{stack_id}' and webhook: '{stack_webhook}'")
### Find correct webhook in gitea
repo_url = urlparse(args.DEPLOY_REPO_URL)
gitea = f"{repo_url.scheme}://{repo_url.netloc}"
repo_path = repo_url.path
repo_parts = repo_path.strip('/').split('/')
owner = repo_parts[0]
repo = repo_parts[1]
gitea_headers = {
"Authorization": f"token {args.GITEA_API_KEY}"
}
webhook_url = f'{gitea}/api/v1/repos/{repo_path}/hooks'
try:
#TODO: Webhooks are returned paginated, this only checks first page
get_webhooks_response = requests.get(webhook_url, headers=gitea_headers)
get_webhooks_response.raise_for_status() # Raise HTTPError for bad requests
json_webhooks = get_webhooks_response.json()
except requests.exceptions.RequestException as err:
raise Exception(f'Could not get webhooks from Gitea: {err}.\n\n Response:{get_webhooks_response.content}')
webhook_id = None
for webhook in json_webhooks:
if webhook["config"]["url"] == f"{args.PORTAINER}/api/stacks/webhooks/{stack_webhook}":
webhook_id = webhook["id"]
break
if webhook_id is None:
raise Exception(f"Gitea webhook pointing to Portainer webhook '{stack_webhook}' not found.")
else:
print(f"Found Gitea webhook pointing to Portainer webhook '{stack_webhook}\' has id: '{webhook_id}'.")
### Remove Webhook from Gitea ###
remove_webhook_url = f"{gitea}/api/v1/repos/{repo_path}/hooks/{webhook_id}"
try:
del_webhooks_response = requests.delete(remove_webhook_url, headers=gitea_headers)
del_webhooks_response.raise_for_status() # Raise HTTPError for bad requests
except requests.exceptions.RequestException as 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_url = f"{args.PORTAINER}/api/stacks/{stack_id}?endpointId={endpoint_id}"
try:
del_stack_response = requests.delete(remove_stack_url, headers=portainer_headers)
del_stack_response.raise_for_status() # Raise HTTPError for bad requests
except requests.exceptions.RequestException as 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')

View File

@@ -2,7 +2,10 @@ version: '3.4'
services:
http-echo:
image: mendhak/http-https-echo:latest
build:
image: ${COMPOSE_PROJECT_NAME}_httpecho
context: ./
dockerfile: httpecho.Dockerfile
expose:
- 8080
environment:

2
httpecho.Dockerfile Normal file
View File

@@ -0,0 +1,2 @@
FROM mendhak/http-https-echo:latest
RUN echo "Hello"