Update action to update git stacks

This commit is contained in:
Julius Freudenberger 2023-08-17 19:17:58 +02:00
parent b779a44ee2
commit 646000f132
5 changed files with 59 additions and 104 deletions

View file

@ -1,6 +1,7 @@
# Portainer stack redeploy action # Portainer stack redeploy action
This action allows you to update the stack with pull new images if you can't use webhooks. For example, in Portainer Community Edition. This action allows you to update the stack with pull new images if you can't use webhooks. For example, in Portainer Community Edition.
This is a fork of [wirgen/portainer-stack-redeploy-action](https://github.com/wirgen/portainer-stack-redeploy-action) which allows to update stack deployed with a git repository hosting the `docker-compose.yaml`.
## Inputs ## Inputs
@ -20,13 +21,18 @@ This action allows you to update the stack with pull new images if you can't use
ID of endpoint (environment). Required if your stack is not in local environment ID of endpoint (environment). Required if your stack is not in local environment
### `environment`
Environment variables to set on the stack. When omitted, all existing variables will be cleared from the stack. Must be input as a JSON String; one array of objects each with the keys `name` and `value`
## Example usage ## Example usage
```yaml ```yaml
uses: wirgen/portainer-stack-redeploy-action@v1.1 uses: JuliusFreudenberger/portainer-stack-git-redeploy-action@v1.0
with: with:
portainerUrl: 'https://example.com:9443' portainerUrl: 'https://example.com:9443'
accessToken: 'ptr_XXXyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy' accessToken: 'ptr_XXXyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy'
stackId: 8 stackId: 8
endpointId: 3 endpointId: 3
environment: '[{"name":"image_version","value":"xxx"}]'
``` ```

View file

@ -1,6 +1,6 @@
name: Portainer Stack Redeploy name: Portainer Stack Git Redeploy
author: Dzianis Nikifaraŭ author: Julius Freudenberger
description: Action for request to Portainer API for redeploy stack with pull latest images description: Action for request to Portainer API for redeploy stack configured to use the docker-compose.yaml from a git repository with pull latest images and possibility to set environment variables
inputs: inputs:
portainerUrl: portainerUrl:
@ -16,6 +16,9 @@ inputs:
description: 'Endpoint ID' description: 'Endpoint ID'
required: false required: false
default: '' default: ''
environment:
description: 'Environment variables'
required: false
runs: runs:
using: 'node16' using: 'node16'

71
dist/index.js vendored
View file

@ -2823,6 +2823,7 @@ let portainerUrl = core.getInput("portainerUrl")
const accessToken = core.getInput("accessToken") const accessToken = core.getInput("accessToken")
const stackId = parseInt(core.getInput("stackId")) const stackId = parseInt(core.getInput("stackId"))
const endpointId = parseInt(core.getInput("endpointId")) const endpointId = parseInt(core.getInput("endpointId"))
const environmentVariables = core.getInput("environment")
if (isNaN(stackId)) { if (isNaN(stackId)) {
core.setFailed("Stack ID must be integer") core.setFailed("Stack ID must be integer")
@ -2848,67 +2849,39 @@ if (portainerUrl.substring(portainerUrl.length - 1) === "/") {
core.setSecret(portainerUrl) core.setSecret(portainerUrl)
core.setSecret(accessToken) core.setSecret(accessToken)
client.get(`${portainerUrl}/api/stacks/${stackId}/file`, { const postDataObject = {
pullImage: true,
}
console.dir(environmentVariables)
if (environmentVariables !== undefined && environmentVariables !== "") {
postDataObject.env = JSON.parse(environmentVariables)
}
const postData = JSON.stringify(postDataObject)
console.dir(postData)
const req = client.request(`${portainerUrl}/api/stacks/${stackId}/git/redeploy` + (isNaN(endpointId) ? "" : `?endpointId=${endpointId}`), {
method: "PUT",
headers: { headers: {
"X-API-Key": accessToken "X-API-Key": accessToken,
"Content-Type": "application/json",
"Content-Length": Buffer.byteLength(postData)
} }
}, (res) => { }, (res) => {
if (res.statusCode !== 200) { if (res.statusCode !== 200) {
core.setFailed(res.statusMessage) core.setFailed(res.statusMessage)
process.exit(2) process.exit(2)
} }
let result = ""
res.setEncoding("utf8")
res.on("data", (chunk) => result = result + chunk)
res.on("end", () => {
let stackFileContent
try {
// noinspection JSUnresolvedVariable
stackFileContent = JSON.parse(result).StackFileContent
if (stackFileContent === undefined) {
// noinspection ExceptionCaughtLocallyJS
throw Error("Wrong stack file content")
}
} catch (error) {
core.setFailed(error.message)
process.exit(4)
}
const postData = JSON.stringify({
pullImage: true,
stackFileContent
})
const req = client.request(`${portainerUrl}/api/stacks/${stackId}` + (isNaN(endpointId) ? "" : `?endpointId=${endpointId}`), {
method: "PUT",
headers: {
"X-API-Key": accessToken,
"Content-Type": "application/json",
"Content-Length": Buffer.byteLength(postData)
}
}, (res) => {
if (res.statusCode !== 200) {
core.setFailed(res.statusMessage)
process.exit(2)
}
})
.on("error", (error) => {
core.setFailed(error.message)
process.exit(3)
})
req.write(postData)
req.end()
})
}) })
.on("error", (error) => { .on("error", (error) => {
core.setFailed(error.message) core.setFailed(error.message)
process.exit(3) process.exit(3)
}) })
.end()
req.write(postData)
req.end()
})(); })();

View file

@ -4,6 +4,7 @@ let portainerUrl = core.getInput("portainerUrl")
const accessToken = core.getInput("accessToken") const accessToken = core.getInput("accessToken")
const stackId = parseInt(core.getInput("stackId")) const stackId = parseInt(core.getInput("stackId"))
const endpointId = parseInt(core.getInput("endpointId")) const endpointId = parseInt(core.getInput("endpointId"))
const environmentVariables = core.getInput("environment")
if (isNaN(stackId)) { if (isNaN(stackId)) {
core.setFailed("Stack ID must be integer") core.setFailed("Stack ID must be integer")
@ -29,64 +30,36 @@ if (portainerUrl.substring(portainerUrl.length - 1) === "/") {
core.setSecret(portainerUrl) core.setSecret(portainerUrl)
core.setSecret(accessToken) core.setSecret(accessToken)
client.get(`${portainerUrl}/api/stacks/${stackId}/file`, { const postDataObject = {
pullImage: true,
}
console.dir(environmentVariables)
if (environmentVariables !== undefined && environmentVariables !== "") {
postDataObject.env = JSON.parse(environmentVariables)
}
const postData = JSON.stringify(postDataObject)
console.dir(postData)
const req = client.request(`${portainerUrl}/api/stacks/${stackId}/git/redeploy` + (isNaN(endpointId) ? "" : `?endpointId=${endpointId}`), {
method: "PUT",
headers: { headers: {
"X-API-Key": accessToken "X-API-Key": accessToken,
"Content-Type": "application/json",
"Content-Length": Buffer.byteLength(postData)
} }
}, (res) => { }, (res) => {
if (res.statusCode !== 200) { if (res.statusCode !== 200) {
core.setFailed(res.statusMessage) core.setFailed(res.statusMessage)
process.exit(2) process.exit(2)
} }
let result = ""
res.setEncoding("utf8")
res.on("data", (chunk) => result = result + chunk)
res.on("end", () => {
let stackFileContent
try {
// noinspection JSUnresolvedVariable
stackFileContent = JSON.parse(result).StackFileContent
if (stackFileContent === undefined) {
// noinspection ExceptionCaughtLocallyJS
throw Error("Wrong stack file content")
}
} catch (error) {
core.setFailed(error.message)
process.exit(4)
}
const postData = JSON.stringify({
pullImage: true,
stackFileContent
})
const req = client.request(`${portainerUrl}/api/stacks/${stackId}` + (isNaN(endpointId) ? "" : `?endpointId=${endpointId}`), {
method: "PUT",
headers: {
"X-API-Key": accessToken,
"Content-Type": "application/json",
"Content-Length": Buffer.byteLength(postData)
}
}, (res) => {
if (res.statusCode !== 200) {
core.setFailed(res.statusMessage)
process.exit(2)
}
})
.on("error", (error) => {
core.setFailed(error.message)
process.exit(3)
})
req.write(postData)
req.end()
})
}) })
.on("error", (error) => { .on("error", (error) => {
core.setFailed(error.message) core.setFailed(error.message)
process.exit(3) process.exit(3)
}) })
.end()
req.write(postData)
req.end()

View file

@ -12,8 +12,8 @@
"Portainer" "Portainer"
], ],
"author": { "author": {
"name": "Dzianis Nikifaraŭ", "name": "Julius Freudenberger",
"email": "dzianis@wirgen.by" "email": "contact@jfreudenberger.de"
}, },
"license": "MIT", "license": "MIT",
"devDependencies": { "devDependencies": {