forked from forkanization/Proxmox-arm64
update gh workflows
This commit is contained in:
@@ -1,68 +0,0 @@
|
|||||||
FROM mcr.microsoft.com/dotnet/runtime-deps:8.0-jammy as build
|
|
||||||
|
|
||||||
ARG TARGETOS
|
|
||||||
ARG TARGETARCH
|
|
||||||
ARG DOCKER_VERSION=27.5.1
|
|
||||||
ARG BUILDX_VERSION=0.20.1
|
|
||||||
ARG RUNNER_ARCH="x64"
|
|
||||||
|
|
||||||
RUN apt update -y && apt install sudo curl unzip -y
|
|
||||||
|
|
||||||
WORKDIR /actions-runner
|
|
||||||
|
|
||||||
RUN RUNNER_VERSION=$(curl -s https://api.github.com/repos/actions/runner/releases/latest | grep "tag_name" | head -n 1 | awk '{print substr($2, 3, length($2)-4)}') \
|
|
||||||
&& curl -f -L -o runner.tar.gz https://github.com/actions/runner/releases/download/v${RUNNER_VERSION}/actions-runner-linux-${RUNNER_ARCH}-${RUNNER_VERSION}.tar.gz \
|
|
||||||
&& tar xzf ./runner.tar.gz \
|
|
||||||
&& rm runner.tar.gz
|
|
||||||
|
|
||||||
RUN RUNNER_CONTAINER_HOOKS_VERSION=$(curl -s https://api.github.com/repos/actions/runner-container-hooks/releases/latest | grep "tag_name" | head -n 1 | awk '{print substr($2, 3, length($2)-4)}') \
|
|
||||||
&& curl -f -L -o runner-container-hooks.zip https://github.com/actions/runner-container-hooks/releases/download/v${RUNNER_CONTAINER_HOOKS_VERSION}/actions-runner-hooks-k8s-${RUNNER_CONTAINER_HOOKS_VERSION}.zip \
|
|
||||||
&& unzip ./runner-container-hooks.zip -d ./k8s \
|
|
||||||
&& rm runner-container-hooks.zip
|
|
||||||
|
|
||||||
RUN export RUNNER_ARCH=${TARGETARCH} \
|
|
||||||
&& if [ "$RUNNER_ARCH" = "amd64" ]; then export DOCKER_ARCH=x86_64 ; fi \
|
|
||||||
&& if [ "$RUNNER_ARCH" = "arm64" ]; then export DOCKER_ARCH=aarch64 ; fi \
|
|
||||||
&& curl -fLo docker.tgz https://download.docker.com/${TARGETOS}/static/stable/${DOCKER_ARCH}/docker-${DOCKER_VERSION}.tgz \
|
|
||||||
&& tar zxvf docker.tgz \
|
|
||||||
&& rm -rf docker.tgz \
|
|
||||||
&& mkdir -p /usr/local/lib/docker/cli-plugins \
|
|
||||||
&& curl -fLo /usr/local/lib/docker/cli-plugins/docker-buildx \
|
|
||||||
"https://github.com/docker/buildx/releases/download/v${BUILDX_VERSION}/buildx-v${BUILDX_VERSION}.linux-${TARGETARCH}" \
|
|
||||||
&& chmod +x /usr/local/lib/docker/cli-plugins/docker-buildx
|
|
||||||
|
|
||||||
FROM mcr.microsoft.com/dotnet/runtime-deps:8.0-jammy
|
|
||||||
|
|
||||||
ENV DEBIAN_FRONTEND=noninteractive
|
|
||||||
ENV RUNNER_MANUALLY_TRAP_SIG=1
|
|
||||||
ENV ACTIONS_RUNNER_PRINT_LOG_TO_STDOUT=1
|
|
||||||
ENV ImageOS=ubuntu22
|
|
||||||
|
|
||||||
RUN apt update -y \
|
|
||||||
&& apt install -y --no-install-recommends sudo lsb-release gpg-agent software-properties-common curl jq unzip \
|
|
||||||
&& rm -rf /var/lib/apt/lists/*
|
|
||||||
|
|
||||||
RUN add-apt-repository ppa:git-core/ppa \
|
|
||||||
&& apt update -y \
|
|
||||||
&& apt install -y git \
|
|
||||||
&& rm -rf /var/lib/apt/lists/*
|
|
||||||
|
|
||||||
RUN adduser --disabled-password --gecos "" --uid 1001 runner \
|
|
||||||
&& groupadd docker --gid 123 \
|
|
||||||
&& usermod -aG sudo runner \
|
|
||||||
&& usermod -aG docker runner \
|
|
||||||
&& echo "%sudo ALL=(ALL:ALL) NOPASSWD:ALL" > /etc/sudoers \
|
|
||||||
&& echo "Defaults env_keep += \"DEBIAN_FRONTEND\"" >> /etc/sudoers
|
|
||||||
|
|
||||||
# Install own dependencies in final image
|
|
||||||
RUN curl -fsSL https://deb.nodesource.com/setup_22.x | bash - \
|
|
||||||
&& apt-get install -y nodejs \
|
|
||||||
&& apt-get install -y gh jq git
|
|
||||||
|
|
||||||
WORKDIR /home/runner
|
|
||||||
|
|
||||||
COPY --chown=runner:docker --from=build /actions-runner .
|
|
||||||
COPY --from=build /usr/local/lib/docker/cli-plugins/docker-buildx /usr/local/lib/docker/cli-plugins/docker-buildx
|
|
||||||
RUN install -o root -g root -m 755 docker/* /usr/bin/ && rm -rf docker
|
|
||||||
|
|
||||||
USER runner
|
|
||||||
@@ -1,106 +0,0 @@
|
|||||||
name: Auto Update .app-files
|
|
||||||
|
|
||||||
on:
|
|
||||||
push:
|
|
||||||
branches:
|
|
||||||
- main
|
|
||||||
paths:
|
|
||||||
- 'ct/**.sh'
|
|
||||||
workflow_dispatch:
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
update-app-files:
|
|
||||||
runs-on: runner-cluster-htl-set
|
|
||||||
|
|
||||||
permissions:
|
|
||||||
contents: write
|
|
||||||
pull-requests: write
|
|
||||||
|
|
||||||
steps:
|
|
||||||
- name: Generate a token
|
|
||||||
id: generate-token
|
|
||||||
uses: actions/create-github-app-token@v1
|
|
||||||
with:
|
|
||||||
app-id: ${{ vars.APP_ID }}
|
|
||||||
private-key: ${{ secrets.APP_PRIVATE_KEY }}
|
|
||||||
|
|
||||||
# Step 1: Checkout repository
|
|
||||||
- name: Checkout repository
|
|
||||||
uses: actions/checkout@v2
|
|
||||||
|
|
||||||
# Step 2: Disable file mode changes detection
|
|
||||||
- name: Disable file mode changes
|
|
||||||
run: git config core.fileMode false
|
|
||||||
|
|
||||||
# Step 3: Set up Git user for committing changes
|
|
||||||
- name: Set up Git
|
|
||||||
run: |
|
|
||||||
git config --global user.name "GitHub Actions"
|
|
||||||
git config --global user.email "github-actions[bot]@users.noreply.github.com"
|
|
||||||
|
|
||||||
# Step 4: Install figlet
|
|
||||||
- name: Install figlet
|
|
||||||
run: sudo apt-get install -y figlet
|
|
||||||
|
|
||||||
# Step 5: Run the updated generate-app-files.sh script
|
|
||||||
- name: Run generate-app-files.sh
|
|
||||||
run: |
|
|
||||||
chmod +x .github/workflows/scripts/generate-app-headers.sh
|
|
||||||
.github/workflows/scripts/generate-app-headers.sh
|
|
||||||
env:
|
|
||||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
||||||
|
|
||||||
# Step 6: Check if there are any changes
|
|
||||||
- name: Check if there are any changes
|
|
||||||
run: |
|
|
||||||
echo "Checking for changes..."
|
|
||||||
git add -A # Untracked Dateien aufnehmen
|
|
||||||
git status
|
|
||||||
if git diff --cached --quiet; then
|
|
||||||
echo "No changes detected."
|
|
||||||
echo "changed=false" >> "$GITHUB_ENV"
|
|
||||||
else
|
|
||||||
echo "Changes detected:"
|
|
||||||
git diff --stat --cached
|
|
||||||
echo "changed=true" >> "$GITHUB_ENV"
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Step 7: Commit and create PR if changes exist
|
|
||||||
- name: Commit and create PR if changes exist
|
|
||||||
if: env.changed == 'true'
|
|
||||||
run: |
|
|
||||||
git commit -m "Update .app files"
|
|
||||||
git checkout -b pr-update-app-files
|
|
||||||
git push origin pr-update-app-files --force
|
|
||||||
gh pr create --title "[core] update .app files" \
|
|
||||||
--body "This PR is auto-generated by a GitHub Action to update the .app files." \
|
|
||||||
--head pr-update-app-files \
|
|
||||||
--base main \
|
|
||||||
--label "automated pr"
|
|
||||||
env:
|
|
||||||
GH_TOKEN: ${{ steps.generate-token.outputs.token }}
|
|
||||||
|
|
||||||
- name: Approve pull request
|
|
||||||
if: env.changed == 'true'
|
|
||||||
env:
|
|
||||||
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
||||||
run: |
|
|
||||||
PR_NUMBER=$(gh pr list --head "pr-update-app-files" --json number --jq '.[].number')
|
|
||||||
if [ -n "$PR_NUMBER" ]; then
|
|
||||||
gh pr review $PR_NUMBER --approve
|
|
||||||
fi
|
|
||||||
|
|
||||||
- name: Re-approve pull request after update
|
|
||||||
if: env.changed == 'true'
|
|
||||||
env:
|
|
||||||
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
||||||
run: |
|
|
||||||
PR_NUMBER=$(gh pr list --head "pr-update-app-files" --json number --jq '.[].number')
|
|
||||||
if [ -n "$PR_NUMBER" ]; then
|
|
||||||
gh pr review $PR_NUMBER --approve
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Step 8: Output success message when no changes
|
|
||||||
- name: No changes detected
|
|
||||||
if: env.changed == 'false'
|
|
||||||
run: echo "No changes to commit. Workflow completed successfully."
|
|
||||||
@@ -1,60 +0,0 @@
|
|||||||
name: Update date_created in JSON files
|
|
||||||
|
|
||||||
on:
|
|
||||||
# Dieser Trigger wird für das Öffnen von PRs sowie für das Aktualisieren von offenen PRs verwendet
|
|
||||||
pull_request:
|
|
||||||
types: [opened, synchronize]
|
|
||||||
schedule:
|
|
||||||
# Dieser Trigger wird 4x am Tag ausgelöst, um sicherzustellen, dass das Datum aktualisiert wird
|
|
||||||
- cron: "0 0,6,12,18 * * *" # Führt alle 6 Stunden aus
|
|
||||||
workflow_dispatch: # Manuelle Ausführung des Workflows möglich
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
update-date:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
|
|
||||||
steps:
|
|
||||||
- name: Checkout repository
|
|
||||||
uses: actions/checkout@v4
|
|
||||||
|
|
||||||
- name: Install yq
|
|
||||||
run: |
|
|
||||||
sudo apt-get update
|
|
||||||
sudo apt-get install -y yq
|
|
||||||
|
|
||||||
- name: Set the current date
|
|
||||||
id: set_date
|
|
||||||
run: echo "TODAY=$(date -u +%Y-%m-%d)" >> $GITHUB_ENV
|
|
||||||
|
|
||||||
- name: Check for changes in PR
|
|
||||||
run: |
|
|
||||||
# Hole den PR-Branch
|
|
||||||
PR_BRANCH="refs/pull/${{ github.event.pull_request.number }}/merge"
|
|
||||||
git fetch origin $PR_BRANCH
|
|
||||||
|
|
||||||
# Liste alle JSON-Dateien im PR auf, die geändert wurden
|
|
||||||
CHANGED_JSON_FILES=$(git diff --name-only origin/main...$PR_BRANCH | grep '.json')
|
|
||||||
|
|
||||||
if [ -z "$CHANGED_JSON_FILES" ]; then
|
|
||||||
echo "No JSON files changed in this PR."
|
|
||||||
exit 0
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Gehe alle geänderten JSON-Dateien durch und aktualisiere das Datum
|
|
||||||
for file in $CHANGED_JSON_FILES; do
|
|
||||||
echo "Updating date_created in $file"
|
|
||||||
# Setze das aktuelle Datum
|
|
||||||
yq eval ".date_created = \"${{ env.TODAY }}\"" -i "$file"
|
|
||||||
git add "$file"
|
|
||||||
done
|
|
||||||
|
|
||||||
- name: Commit and push changes
|
|
||||||
run: |
|
|
||||||
# Prüfe, ob es Änderungen gibt und committe sie
|
|
||||||
git config user.name "json-updater-bot"
|
|
||||||
git config user.email "github-actions[bot]@users.noreply.github.com"
|
|
||||||
|
|
||||||
git commit -m "Update date_created to ${{ env.TODAY }}" || echo "No changes to commit"
|
|
||||||
|
|
||||||
# Push zurück in den PR-Branch
|
|
||||||
git push origin $PR_BRANCH
|
|
||||||
@@ -1,60 +0,0 @@
|
|||||||
name: Shellcheck
|
|
||||||
|
|
||||||
on:
|
|
||||||
push:
|
|
||||||
branches:
|
|
||||||
- main
|
|
||||||
pull_request:
|
|
||||||
workflow_dispatch:
|
|
||||||
schedule:
|
|
||||||
- cron: "5 1 * * *"
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
shellcheck:
|
|
||||||
name: Shellcheck
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
|
|
||||||
- name: Get changed files
|
|
||||||
id: changed-files
|
|
||||||
uses: tj-actions/changed-files@v45
|
|
||||||
with:
|
|
||||||
files: |
|
|
||||||
**.sh
|
|
||||||
|
|
||||||
- name: Download ShellCheck
|
|
||||||
shell: bash
|
|
||||||
env:
|
|
||||||
INPUT_VERSION: "v0.10.0"
|
|
||||||
run: |
|
|
||||||
set -euo pipefail
|
|
||||||
if [[ "${{ runner.os }}" == "macOS" ]]; then
|
|
||||||
osvariant="darwin"
|
|
||||||
else
|
|
||||||
osvariant="linux"
|
|
||||||
fi
|
|
||||||
|
|
||||||
baseurl="https://github.com/koalaman/shellcheck/releases/download"
|
|
||||||
curl -Lso "${{ github.workspace }}/sc.tar.xz" \
|
|
||||||
"${baseurl}/${INPUT_VERSION}/shellcheck-${INPUT_VERSION}.${osvariant}.x86_64.tar.xz"
|
|
||||||
|
|
||||||
tar -xf "${{ github.workspace }}/sc.tar.xz" -C "${{ github.workspace }}"
|
|
||||||
mv "${{ github.workspace }}/shellcheck-${INPUT_VERSION}/shellcheck" \
|
|
||||||
"${{ github.workspace }}/shellcheck"
|
|
||||||
|
|
||||||
- name: Verify ShellCheck binary
|
|
||||||
run: |
|
|
||||||
ls -l "${{ github.workspace }}/shellcheck"
|
|
||||||
|
|
||||||
- name: Display ShellCheck version
|
|
||||||
run: |
|
|
||||||
"${{ github.workspace }}/shellcheck" --version
|
|
||||||
|
|
||||||
- name: Run ShellCheck
|
|
||||||
if: steps.changed-files.outputs.any_changed == 'true'
|
|
||||||
env:
|
|
||||||
ALL_CHANGED_FILES: ${{ steps.changed-files.outputs.all_changed_files }}
|
|
||||||
run: |
|
|
||||||
echo "${ALL_CHANGED_FILES}" | xargs "${{ github.workspace }}/shellcheck"
|
|
||||||
@@ -1,88 +0,0 @@
|
|||||||
name: Auto Update JSON-Date
|
|
||||||
|
|
||||||
on:
|
|
||||||
push:
|
|
||||||
branches:
|
|
||||||
- main
|
|
||||||
workflow_dispatch:
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
update-json-dates:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
|
|
||||||
permissions:
|
|
||||||
contents: write
|
|
||||||
pull-requests: write
|
|
||||||
|
|
||||||
steps:
|
|
||||||
- name: Generate a token
|
|
||||||
id: generate-token
|
|
||||||
uses: actions/create-github-app-token@v1
|
|
||||||
with:
|
|
||||||
app-id: ${{ vars.APP_ID }}
|
|
||||||
private-key: ${{ secrets.APP_PRIVATE_KEY }}
|
|
||||||
|
|
||||||
- name: Checkout repository
|
|
||||||
uses: actions/checkout@v4
|
|
||||||
with:
|
|
||||||
fetch-depth: 0 # Full history for proper detection
|
|
||||||
|
|
||||||
- name: Set up Git
|
|
||||||
run: |
|
|
||||||
git config --global user.name "GitHub Actions"
|
|
||||||
git config --global user.email "github-actions[bot]@users.noreply.github.com"
|
|
||||||
|
|
||||||
- name: Find JSON files with incorrect date_created
|
|
||||||
id: find_wrong_json
|
|
||||||
run: |
|
|
||||||
TODAY=$(date -u +"%Y-%m-%d")
|
|
||||||
> incorrect_json_files.txt
|
|
||||||
|
|
||||||
for FILE in json/*.json; do
|
|
||||||
if [[ -f "$FILE" ]]; then
|
|
||||||
DATE_IN_JSON=$(jq -r '.date_created' "$FILE" 2>/dev/null || echo "")
|
|
||||||
|
|
||||||
if [[ "$DATE_IN_JSON" != "$TODAY" ]]; then
|
|
||||||
echo "$FILE" >> incorrect_json_files.txt
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
|
|
||||||
if [[ -s incorrect_json_files.txt ]]; then
|
|
||||||
echo "CHANGED=true" >> $GITHUB_ENV
|
|
||||||
else
|
|
||||||
echo "CHANGED=false" >> $GITHUB_ENV
|
|
||||||
fi
|
|
||||||
|
|
||||||
- name: Run update script
|
|
||||||
if: env.CHANGED == 'true'
|
|
||||||
run: |
|
|
||||||
chmod +x .github/workflows/scripts/update-json.sh
|
|
||||||
while read -r FILE; do
|
|
||||||
.github/workflows/scripts/update-json.sh "$FILE"
|
|
||||||
done < incorrect_json_files.txt
|
|
||||||
|
|
||||||
- name: Commit and create PR if changes exist
|
|
||||||
if: env.CHANGED == 'true'
|
|
||||||
run: |
|
|
||||||
git add json/*.json
|
|
||||||
git commit -m "Auto-update date_created in incorrect JSON files"
|
|
||||||
git checkout -b pr-fix-json-dates
|
|
||||||
git push origin pr-fix-json-dates --force
|
|
||||||
gh pr create --title "[core] Fix incorrect JSON date_created fields" \
|
|
||||||
--body "This PR is auto-generated to fix incorrect `date_created` fields in JSON files." \
|
|
||||||
--head pr-fix-json-dates \
|
|
||||||
--base main \
|
|
||||||
--label "automated pr"
|
|
||||||
env:
|
|
||||||
GH_TOKEN: ${{ steps.generate-token.outputs.token }}
|
|
||||||
|
|
||||||
- name: Approve pull request
|
|
||||||
if: env.CHANGED == 'true'
|
|
||||||
env:
|
|
||||||
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
||||||
run: |
|
|
||||||
PR_NUMBER=$(gh pr list --head "pr-fix-json-dates" --json number --jq '.[].number')
|
|
||||||
if [ -n "$PR_NUMBER" ]; then
|
|
||||||
gh pr review $PR_NUMBER --approve
|
|
||||||
fi
|
|
||||||
@@ -1,122 +0,0 @@
|
|||||||
name: Close Discussion on PR Merge
|
|
||||||
|
|
||||||
on:
|
|
||||||
pull_request:
|
|
||||||
types: [closed]
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
close-discussion:
|
|
||||||
runs-on: runner-cluster-htl-set
|
|
||||||
|
|
||||||
steps:
|
|
||||||
- name: Checkout Repository
|
|
||||||
uses: actions/checkout@v4
|
|
||||||
|
|
||||||
- name: Set Up Node.js
|
|
||||||
uses: actions/setup-node@v4
|
|
||||||
with:
|
|
||||||
node-version: "20"
|
|
||||||
- name: Install Dependencies
|
|
||||||
run: npm install zx @octokit/graphql
|
|
||||||
|
|
||||||
- name: Close Discussion
|
|
||||||
env:
|
|
||||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
||||||
PR_BODY: ${{ github.event.pull_request.body }}
|
|
||||||
PR_NUMBER: ${{ github.event.pull_request.number }}
|
|
||||||
REPO_OWNER: ${{ github.repository_owner }}
|
|
||||||
REPO_NAME: ${{ github.event.repository.name }}
|
|
||||||
run: |
|
|
||||||
npx zx << 'EOF'
|
|
||||||
import { graphql } from "@octokit/graphql";
|
|
||||||
(async function() {
|
|
||||||
try {
|
|
||||||
const token = process.env.GITHUB_TOKEN;
|
|
||||||
const prBody = process.env.PR_BODY;
|
|
||||||
const prNumber = process.env.PR_NUMBER;
|
|
||||||
const owner = process.env.REPO_OWNER;
|
|
||||||
const repo = process.env.REPO_NAME;
|
|
||||||
|
|
||||||
if (!token || !prBody || !prNumber || !owner || !repo) {
|
|
||||||
console.log("Missing required environment variables.");
|
|
||||||
process.exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
const match = prBody.match(/#(\d+)/);
|
|
||||||
if (!match) {
|
|
||||||
console.log("No discussion ID found in PR body.");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
const discussionNumber = match[1];
|
|
||||||
|
|
||||||
console.log(`Extracted Discussion Number: ${discussionNumber}`);
|
|
||||||
console.log(`PR Number: ${prNumber}`);
|
|
||||||
console.log(`Repository: ${owner}/${repo}`);
|
|
||||||
|
|
||||||
const graphqlWithAuth = graphql.defaults({
|
|
||||||
headers: { authorization: `Bearer ${token}` },
|
|
||||||
});
|
|
||||||
|
|
||||||
const discussionQuery = `
|
|
||||||
query($owner: String!, $repo: String!, $number: Int!) {
|
|
||||||
repository(owner: $owner, name: $repo) {
|
|
||||||
discussion(number: $number) {
|
|
||||||
id
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
`;
|
|
||||||
|
|
||||||
const discussionResponse = await graphqlWithAuth(discussionQuery, {
|
|
||||||
owner,
|
|
||||||
repo,
|
|
||||||
number: parseInt(discussionNumber, 10),
|
|
||||||
});
|
|
||||||
|
|
||||||
const discussionQLId = discussionResponse.repository.discussion.id;
|
|
||||||
if (!discussionQLId) {
|
|
||||||
console.log("Failed to fetch discussion GraphQL ID.");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
console.log(`GraphQL Discussion ID: ${discussionQLId}`);
|
|
||||||
|
|
||||||
const commentMutation = `
|
|
||||||
mutation($discussionId: ID!, $body: String!) {
|
|
||||||
addDiscussionComment(input: { discussionId: $discussionId, body: $body }) {
|
|
||||||
comment { id body }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
`;
|
|
||||||
|
|
||||||
const commentResponse = await graphqlWithAuth(commentMutation, {
|
|
||||||
discussionId: discussionQLId,
|
|
||||||
body: `Merged with PR #${prNumber}`,
|
|
||||||
});
|
|
||||||
|
|
||||||
const commentId = commentResponse.addDiscussionComment.comment.id;
|
|
||||||
if (!commentId) {
|
|
||||||
console.log("Failed to post the comment.");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
console.log(`Comment Posted Successfully! Comment ID: ${commentId}`);
|
|
||||||
|
|
||||||
const markAnswerMutation = `
|
|
||||||
mutation($id: ID!) {
|
|
||||||
markDiscussionCommentAsAnswer(input: { id: $id }) {
|
|
||||||
discussion { id title }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
`;
|
|
||||||
|
|
||||||
await graphqlWithAuth(markAnswerMutation, { id: commentId });
|
|
||||||
|
|
||||||
console.log("Comment marked as answer successfully!");
|
|
||||||
|
|
||||||
} catch (error) {
|
|
||||||
console.error("Error:", error);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
})();
|
|
||||||
EOF
|
|
||||||
@@ -1,37 +0,0 @@
|
|||||||
name: Build and Publish Docker Image
|
|
||||||
|
|
||||||
on:
|
|
||||||
push:
|
|
||||||
branches:
|
|
||||||
- main
|
|
||||||
paths:
|
|
||||||
- '.github/runner/docker/**'
|
|
||||||
schedule:
|
|
||||||
- cron: '0 0 * * *'
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
build:
|
|
||||||
runs-on: ubuntu-latest #To ensure it always builds we use the github runner with all the right tooling
|
|
||||||
|
|
||||||
steps:
|
|
||||||
- name: Checkout code
|
|
||||||
uses: actions/checkout@v3
|
|
||||||
|
|
||||||
- name: Log in to GHCR
|
|
||||||
uses: docker/login-action@v2
|
|
||||||
with:
|
|
||||||
registry: ghcr.io
|
|
||||||
username: ${{ github.actor }}
|
|
||||||
password: ${{ secrets.GITHUB_TOKEN }}
|
|
||||||
|
|
||||||
- name: Build Docker image
|
|
||||||
run: |
|
|
||||||
repo_name=${{ github.repository }} # Get repository name
|
|
||||||
repo_name_lower=$(echo $repo_name | tr '[:upper:]' '[:lower:]') # Convert to lowercase
|
|
||||||
docker build -t ghcr.io/$repo_name_lower/gh-runner-self:latest -f .github/runner/docker/gh-runner-self.dockerfile .
|
|
||||||
|
|
||||||
- name: Push Docker image to GHCR
|
|
||||||
run: |
|
|
||||||
repo_name=${{ github.repository }} # Get repository name
|
|
||||||
repo_name_lower=$(echo $repo_name | tr '[:upper:]' '[:lower:]') # Convert to lowercase
|
|
||||||
docker push ghcr.io/$repo_name_lower/gh-runner-self:latest
|
|
||||||
@@ -1,28 +0,0 @@
|
|||||||
|
|
||||||
name: Delete JSON date PR Branch
|
|
||||||
|
|
||||||
on:
|
|
||||||
pull_request:
|
|
||||||
types: [closed]
|
|
||||||
branches:
|
|
||||||
- main
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
delete_branch:
|
|
||||||
runs-on: runner-cluster-htl-set
|
|
||||||
steps:
|
|
||||||
- name: Checkout the code
|
|
||||||
uses: actions/checkout@v3
|
|
||||||
|
|
||||||
- name: Delete PR Update Branch
|
|
||||||
if: github.event.pull_request.merged == true && startsWith(github.event.pull_request.head.ref, 'pr-update-json-')
|
|
||||||
run: |
|
|
||||||
PR_BRANCH="${{ github.event.pull_request.head.ref }}"
|
|
||||||
echo "Deleting branch $PR_BRANCH..."
|
|
||||||
|
|
||||||
# Avoid deleting the default branch (e.g., main)
|
|
||||||
if [[ "$PR_BRANCH" != "main" ]]; then
|
|
||||||
git push origin --delete "$PR_BRANCH"
|
|
||||||
else
|
|
||||||
echo "Skipping deletion of the main branch"
|
|
||||||
fi
|
|
||||||
@@ -1,177 +0,0 @@
|
|||||||
name: Run Scripts on PVE Node for testing
|
|
||||||
permissions:
|
|
||||||
pull-requests: write
|
|
||||||
on:
|
|
||||||
pull_request_target:
|
|
||||||
branches:
|
|
||||||
- main
|
|
||||||
paths:
|
|
||||||
- 'install/**.sh'
|
|
||||||
- 'ct/**.sh'
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
run-install-script:
|
|
||||||
runs-on: pvenode
|
|
||||||
steps:
|
|
||||||
- name: Checkout PR branch
|
|
||||||
uses: actions/checkout@v4
|
|
||||||
with:
|
|
||||||
ref: ${{ github.event.pull_request.head.ref }}
|
|
||||||
repository: ${{ github.event.pull_request.head.repo.full_name }}
|
|
||||||
fetch-depth: 0
|
|
||||||
|
|
||||||
- name: Add Git safe directory
|
|
||||||
run: |
|
|
||||||
git config --global --add safe.directory /__w/ProxmoxVE/ProxmoxVE
|
|
||||||
|
|
||||||
- name: Set up GH_TOKEN
|
|
||||||
env:
|
|
||||||
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
||||||
run: |
|
|
||||||
echo "GH_TOKEN=${GH_TOKEN}" >> $GITHUB_ENV
|
|
||||||
|
|
||||||
- name: Get Changed Files
|
|
||||||
run: |
|
|
||||||
CHANGED_FILES=$(gh pr diff ${{ github.event.pull_request.number }} --repo ${{ github.repository }} --name-only)
|
|
||||||
CHANGED_FILES=$(echo "$CHANGED_FILES" | tr '\n' ' ')
|
|
||||||
echo "Changed files: $CHANGED_FILES"
|
|
||||||
echo "SCRIPT=$CHANGED_FILES" >> $GITHUB_ENV
|
|
||||||
env:
|
|
||||||
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
||||||
|
|
||||||
|
|
||||||
- name: Get scripts
|
|
||||||
id: check-install-script
|
|
||||||
run: |
|
|
||||||
ALL_FILES=()
|
|
||||||
ADDED_FILES=()
|
|
||||||
for FILE in ${{ env.SCRIPT }}; do
|
|
||||||
if [[ $FILE =~ ^install/.*-install\.sh$ ]] || [[ $FILE =~ ^ct/.*\.sh$ ]]; then
|
|
||||||
STRIPPED_NAME=$(basename "$FILE" | sed 's/-install//' | sed 's/\.sh$//')
|
|
||||||
if [[ ! " ${ADDED_FILES[@]} " =~ " $STRIPPED_NAME " ]]; then
|
|
||||||
ALL_FILES+=("$FILE")
|
|
||||||
ADDED_FILES+=("$STRIPPED_NAME") # Mark this base file as added (without the path)
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
ALL_FILES=$(echo "${ALL_FILES[@]}" | xargs)
|
|
||||||
echo "$ALL_FILES"
|
|
||||||
echo "ALL_FILES=$ALL_FILES" >> $GITHUB_ENV
|
|
||||||
|
|
||||||
- name: Run scripts
|
|
||||||
id: run-install
|
|
||||||
continue-on-error: true
|
|
||||||
run: |
|
|
||||||
set +e
|
|
||||||
#run for each files in /ct
|
|
||||||
for FILE in ${{ env.ALL_FILES }}; do
|
|
||||||
STRIPPED_NAME=$(basename "$FILE" | sed 's/-install//' | sed 's/\.sh$//')
|
|
||||||
echo "Running Test for: $STRIPPED_NAME"
|
|
||||||
if grep -E -q 'read\s+-r\s+-p\s+".*"\s+\w+' "$FILE"; then
|
|
||||||
echo "The script contains an interactive prompt. Skipping execution."
|
|
||||||
continue
|
|
||||||
fi
|
|
||||||
if [[ $FILE =~ ^install/.*-install\.sh$ ]]; then
|
|
||||||
CT_SCRIPT="ct/$STRIPPED_NAME.sh"
|
|
||||||
if [[ ! -f $CT_SCRIPT ]]; then
|
|
||||||
echo "No CT script found for $STRIPPED_NAME"
|
|
||||||
ERROR_MSG="No CT script found for $FILE"
|
|
||||||
echo "$ERROR_MSG" > result_$STRIPPED_NAME.log
|
|
||||||
continue
|
|
||||||
fi
|
|
||||||
if grep -E -q 'read\s+-r\s+-p\s+".*"\s+\w+' "install/$STRIPPED_NAME-install.sh"; then
|
|
||||||
echo "The script contains an interactive prompt. Skipping execution."
|
|
||||||
continue
|
|
||||||
fi
|
|
||||||
echo "Found CT script for $STRIPPED_NAME"
|
|
||||||
chmod +x "$CT_SCRIPT"
|
|
||||||
RUNNING_FILE=$CT_SCRIPT
|
|
||||||
elif [[ $FILE =~ ^ct/.*\.sh$ ]]; then
|
|
||||||
INSTALL_SCRIPT="install/$STRIPPED_NAME-install.sh"
|
|
||||||
if [[ ! -f $INSTALL_SCRIPT ]]; then
|
|
||||||
echo "No install script found for $STRIPPED_NAME"
|
|
||||||
ERROR_MSG="No install script found for $FILE"
|
|
||||||
echo "$ERROR_MSG" > result_$STRIPPED_NAME.log
|
|
||||||
continue
|
|
||||||
fi
|
|
||||||
echo "Found install script for $STRIPPED_NAME"
|
|
||||||
chmod +x "$INSTALL_SCRIPT"
|
|
||||||
RUNNING_FILE=$FILE
|
|
||||||
if grep -E -q 'read\s+-r\s+-p\s+".*"\s+\w+' "ct/$STRIPPED_NAME.sh"; then
|
|
||||||
echo "The script contains an interactive prompt. Skipping execution."
|
|
||||||
continue
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
git remote add community-scripts https://github.com/community-scripts/ProxmoxVE.git
|
|
||||||
git fetch community-scripts
|
|
||||||
rm -f .github/workflows/scripts/app-test/pr-build.func || true
|
|
||||||
rm -f .github/workflows/scripts/app-test/pr-install.func || true
|
|
||||||
rm -f .github/workflows/scripts/app-test/pr-alpine-install.func || true
|
|
||||||
rm -f .github/workflows/scripts/app-test/pr-create-lxc.sh || true
|
|
||||||
git checkout community-scripts/main -- .github/workflows/scripts/app-test/pr-build.func
|
|
||||||
git checkout community-scripts/main -- .github/workflows/scripts/app-test/pr-install.func
|
|
||||||
git checkout community-scripts/main -- .github/workflows/scripts/app-test/pr-alpine-install.func
|
|
||||||
git checkout community-scripts/main -- .github/workflows/scripts/app-test/pr-create-lxc.sh
|
|
||||||
chmod +x $RUNNING_FILE
|
|
||||||
chmod +x .github/workflows/scripts/app-test/pr-create-lxc.sh
|
|
||||||
chmod +x .github/workflows/scripts/app-test/pr-install.func
|
|
||||||
chmod +x .github/workflows/scripts/app-test/pr-alpine-install.func
|
|
||||||
chmod +x .github/workflows/scripts/app-test/pr-build.func
|
|
||||||
sed -i 's|source <(curl -s https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/build.func)|source .github/workflows/scripts/app-test/pr-build.func|g' "$RUNNING_FILE"
|
|
||||||
echo "Executing $RUNNING_FILE"
|
|
||||||
ERROR_MSG=$(./$RUNNING_FILE 2>&1 > /dev/null)
|
|
||||||
echo "Finished running $FILE"
|
|
||||||
if [ -n "$ERROR_MSG" ]; then
|
|
||||||
echo "ERROR in $STRIPPED_NAME: $ERROR_MSG"
|
|
||||||
echo "$ERROR_MSG" > result_$STRIPPED_NAME.log
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
set -e # Restore exit-on-error
|
|
||||||
|
|
||||||
- name: Cleanup PVE Node
|
|
||||||
run: |
|
|
||||||
containers=$(pct list | tail -n +2 | awk '{print $0 " " $4}' | awk '{print $1}')
|
|
||||||
|
|
||||||
for container_id in $containers; do
|
|
||||||
status=$(pct status $container_id | awk '{print $2}')
|
|
||||||
if [[ $status == "running" ]]; then
|
|
||||||
pct stop $container_id
|
|
||||||
pct destroy $container_id
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
|
|
||||||
- name: Post error comments
|
|
||||||
run: |
|
|
||||||
ERROR="false"
|
|
||||||
SEARCH_LINE=".github/workflows/scripts/app-test/pr-build.func: line 255:"
|
|
||||||
|
|
||||||
# Get all existing comments on the PR
|
|
||||||
EXISTING_COMMENTS=$(gh pr view ${{ github.event.pull_request.number }} --repo ${{ github.repository }} --json comments --jq '.comments[].body')
|
|
||||||
|
|
||||||
for FILE in ${{ env.ALL_FILES }}; do
|
|
||||||
STRIPPED_NAME=$(basename "$FILE" | sed 's/-install//' | sed 's/\.sh$//')
|
|
||||||
if [[ ! -f result_$STRIPPED_NAME.log ]]; then
|
|
||||||
continue
|
|
||||||
fi
|
|
||||||
ERROR_MSG=$(cat result_$STRIPPED_NAME.log)
|
|
||||||
|
|
||||||
if [ -n "$ERROR_MSG" ]; then
|
|
||||||
CLEANED_ERROR_MSG=$(echo "$ERROR_MSG" | sed "s|$SEARCH_LINE.*||")
|
|
||||||
COMMENT_BODY=":warning: The script _**$FILE**_ failed with the following message: <br> <div><strong>${CLEANED_ERROR_MSG}</strong></div>"
|
|
||||||
|
|
||||||
# Check if the comment already exists
|
|
||||||
if echo "$EXISTING_COMMENTS" | grep -qF "$COMMENT_BODY"; then
|
|
||||||
echo "Skipping duplicate comment for $FILE"
|
|
||||||
else
|
|
||||||
echo "Posting error message for $FILE"
|
|
||||||
gh pr comment ${{ github.event.pull_request.number }} \
|
|
||||||
--repo ${{ github.repository }} \
|
|
||||||
--body "$COMMENT_BODY"
|
|
||||||
ERROR="true"
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
|
|
||||||
echo "ERROR=$ERROR" >> $GITHUB_ENV
|
|
||||||
|
|
||||||
|
|
||||||
@@ -1,243 +0,0 @@
|
|||||||
name: Script Format Check
|
|
||||||
permissions:
|
|
||||||
pull-requests: write
|
|
||||||
on:
|
|
||||||
pull_request_target:
|
|
||||||
branches:
|
|
||||||
- main
|
|
||||||
paths:
|
|
||||||
- 'install/*.sh'
|
|
||||||
- 'ct/*.sh'
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
run-install-script:
|
|
||||||
runs-on: pvenode
|
|
||||||
steps:
|
|
||||||
- name: Checkout PR branch (supports forks)
|
|
||||||
uses: actions/checkout@v4
|
|
||||||
with:
|
|
||||||
ref: ${{ github.event.pull_request.head.ref }}
|
|
||||||
repository: ${{ github.event.pull_request.head.repo.full_name }}
|
|
||||||
fetch-depth: 0
|
|
||||||
|
|
||||||
- name: Add Git safe directory
|
|
||||||
run: |
|
|
||||||
git config --global --add safe.directory /__w/ProxmoxVE/ProxmoxVE
|
|
||||||
|
|
||||||
- name: Set up GH_TOKEN
|
|
||||||
env:
|
|
||||||
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
||||||
run: |
|
|
||||||
echo "GH_TOKEN=${GH_TOKEN}" >> $GITHUB_ENV
|
|
||||||
|
|
||||||
- name: Get Changed Files
|
|
||||||
run: |
|
|
||||||
CHANGED_FILES=$(gh pr diff ${{ github.event.pull_request.number }} --repo ${{ github.repository }} --name-only)
|
|
||||||
CHANGED_FILES=$(echo "$CHANGED_FILES" | tr '\n' ' ')
|
|
||||||
echo "Changed files: $CHANGED_FILES"
|
|
||||||
echo "SCRIPT=$CHANGED_FILES" >> $GITHUB_ENV
|
|
||||||
env:
|
|
||||||
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
||||||
|
|
||||||
- name: Check scripts
|
|
||||||
id: run-install
|
|
||||||
continue-on-error: true
|
|
||||||
run: |
|
|
||||||
for FILE in ${{ env.SCRIPT }}; do
|
|
||||||
STRIPPED_NAME=$(basename "$FILE" | sed 's/-install//' | sed 's/\.sh$//')
|
|
||||||
echo "Running Test for: $STRIPPED_NAME"
|
|
||||||
FILE_STRIPPED="${FILE##*/}"
|
|
||||||
LOG_FILE="result_$FILE_STRIPPED.log"
|
|
||||||
|
|
||||||
if [[ $FILE =~ ^ct/.*\.sh$ ]]; then
|
|
||||||
|
|
||||||
FIRST_LINE=$(sed -n '1p' "$FILE")
|
|
||||||
[[ "$FIRST_LINE" != "#!/usr/bin/env bash" ]] && echo "Line 1 was $FIRST_LINE | Should be: #!/usr/bin/env bash" >> "$LOG_FILE"
|
|
||||||
SECOND_LINE=$(sed -n '2p' "$FILE")
|
|
||||||
[[ "$SECOND_LINE" != "source <(curl -s https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/build.func)" ]] &&
|
|
||||||
echo "Line 2 was $SECOND_LINE | Should be: source <(curl -s https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/build.func)" >> "$LOG_FILE"
|
|
||||||
THIRD_LINE=$(sed -n '3p' "$FILE")
|
|
||||||
if ! [[ "$THIRD_LINE" =~ ^#\ Copyright\ \(c\)\ [0-9]{4}-[0-9]{4}\ community-scripts\ ORG$ || "$THIRD_LINE" =~ ^Copyright\ \(c\)\ [0-9]{4}-[0-9]{4}\ tteck$ ]]; then
|
|
||||||
echo "Line 3 was $THIRD_LINE | Should be: # Copyright (c) 2021-2025 community-scripts ORG" >> "$LOG_FILE"
|
|
||||||
fi
|
|
||||||
|
|
||||||
EXPECTED_AUTHOR="# Author:"
|
|
||||||
EXPECTED_LICENSE="# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE"
|
|
||||||
EXPECTED_SOURCE="# Source:"
|
|
||||||
EXPECTED_EMPTY=""
|
|
||||||
|
|
||||||
for i in {4..7}; do
|
|
||||||
LINE=$(sed -n "${i}p" "$FILE")
|
|
||||||
|
|
||||||
case $i in
|
|
||||||
4)
|
|
||||||
[[ $LINE == $EXPECTED_AUTHOR* ]] || printf "Line %d was: '%s' | Should start with: '%s'\n" "$i" "$LINE" "$EXPECTED_AUTHOR" >> $LOG_FILE
|
|
||||||
;;
|
|
||||||
5)
|
|
||||||
[[ "$LINE" == "$EXPECTED_LICENSE" ]] || printf "Line %d was: '%s' | Should be: '%s'\n" "$i" "$LINE" "$EXPECTED_LICENSE" >> $LOG_FILE
|
|
||||||
;;
|
|
||||||
6)
|
|
||||||
[[ $LINE == $EXPECTED_SOURCE* ]] || printf "Line %d was: '%s' | Should start with: '%s'\n" "$i" "$LINE" "$EXPECTED_SOURCE" >> $LOG_FILE
|
|
||||||
;;
|
|
||||||
7)
|
|
||||||
[[ -z $LINE ]] || printf "Line %d was: '%s' | Should be empty\n" "$i" "$LINE" >> $LOG_FILE
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
done
|
|
||||||
|
|
||||||
|
|
||||||
EXPECTED_PREFIXES=(
|
|
||||||
"APP="
|
|
||||||
"var_tags="
|
|
||||||
"var_cpu=" # Must be a number
|
|
||||||
"var_ram=" # Must be a number
|
|
||||||
"var_disk=" # Must be a number
|
|
||||||
"var_os=" # Must be debian, alpine, or ubuntu
|
|
||||||
"var_version="
|
|
||||||
"var_unprivileged=" # Must be 0 or 1
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
for i in {8..15}; do
|
|
||||||
LINE=$(sed -n "${i}p" "$FILE")
|
|
||||||
INDEX=$((i - 8))
|
|
||||||
|
|
||||||
case $INDEX in
|
|
||||||
2|3|4) # var_cpu, var_ram, var_disk (must be numbers)
|
|
||||||
if [[ "$LINE" =~ ^${EXPECTED_PREFIXES[$INDEX]}([0-9]+)$ ]]; then
|
|
||||||
continue # Valid
|
|
||||||
else
|
|
||||||
echo "Line $i was '$LINE' | Should be: '${EXPECTED_PREFIXES[$INDEX]}<NUMBER>'" >> "$LOG_FILE"
|
|
||||||
fi
|
|
||||||
;;
|
|
||||||
5) # var_os (must be debian, alpine, or ubuntu)
|
|
||||||
if [[ "$LINE" =~ ^var_os=(debian|alpine|ubuntu)$ ]]; then
|
|
||||||
continue # Valid
|
|
||||||
else
|
|
||||||
echo "Line $i was '$LINE' | Should be: 'var_os=[debian|alpine|ubuntu]'" >> "$LOG_FILE"
|
|
||||||
fi
|
|
||||||
;;
|
|
||||||
7) # var_unprivileged (must be 0 or 1)
|
|
||||||
if [[ "$LINE" =~ ^var_unprivileged=[01]$ ]]; then
|
|
||||||
continue # Valid
|
|
||||||
else
|
|
||||||
echo "Line $i was '$LINE' | Should be: 'var_unprivileged=[0|1]'" >> "$LOG_FILE"
|
|
||||||
fi
|
|
||||||
;;
|
|
||||||
*) # Other lines (must start with expected prefix)
|
|
||||||
if [[ "$LINE" == ${EXPECTED_PREFIXES[$INDEX]}* ]]; then
|
|
||||||
continue # Valid
|
|
||||||
else
|
|
||||||
echo "Line $i was '$LINE' | Should start with '${EXPECTED_PREFIXES[$INDEX]}'" >> "$LOG_FILE"
|
|
||||||
fi
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
done
|
|
||||||
|
|
||||||
for i in {16..20}; do
|
|
||||||
LINE=$(sed -n "${i}p" "$FILE")
|
|
||||||
EXPECTED=(
|
|
||||||
"header_info \"$APP\""
|
|
||||||
"variables"
|
|
||||||
"color"
|
|
||||||
"catch_errors"
|
|
||||||
"function update_script() {"
|
|
||||||
)
|
|
||||||
[[ "$LINE" != "${EXPECTED[$((i-16))]}" ]] && echo "Line $i was $LINE | Should be: ${EXPECTED[$((i-16))]}" >> "$LOG_FILE"
|
|
||||||
done
|
|
||||||
cat "$LOG_FILE"
|
|
||||||
elif [[ $FILE =~ ^install/.*-install\.sh$ ]]; then
|
|
||||||
|
|
||||||
FIRST_LINE=$(sed -n '1p' "$FILE")
|
|
||||||
[[ "$FIRST_LINE" != "#!/usr/bin/env bash" ]] && echo "Line 1 was $FIRST_LINE | Should be: #!/usr/bin/env bash" >> "$LOG_FILE"
|
|
||||||
|
|
||||||
SECOND_LINE=$(sed -n '2p' "$FILE")
|
|
||||||
[[ -n "$SECOND_LINE" ]] && echo "Line 2 should be empty" >> "$LOG_FILE"
|
|
||||||
|
|
||||||
THIRD_LINE=$(sed -n '3p' "$FILE")
|
|
||||||
if ! [[ "$THIRD_LINE" =~ ^#\ Copyright\ \(c\)\ [0-9]{4}-[0-9]{4}\ community-scripts\ ORG$ || "$THIRD_LINE" =~ ^Copyright\ \(c\)\ [0-9]{4}-[0-9]{4}\ tteck$ ]]; then
|
|
||||||
echo "Line 3 was $THIRD_LINE | Should be: # Copyright (c) 2021-2025 community-scripts ORG" >> "$LOG_FILE"
|
|
||||||
fi
|
|
||||||
|
|
||||||
EXPECTED_AUTHOR="# Author:"
|
|
||||||
EXPECTED_LICENSE="# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE"
|
|
||||||
EXPECTED_SOURCE="# Source:"
|
|
||||||
EXPECTED_EMPTY=""
|
|
||||||
|
|
||||||
for i in {4..7}; do
|
|
||||||
LINE=$(sed -n "${i}p" "$FILE")
|
|
||||||
|
|
||||||
case $i in
|
|
||||||
4)
|
|
||||||
[[ $LINE == $EXPECTED_AUTHOR* ]] || printf "Line %d was: '%s' | Should start with: '%s'\n" "$i" "$LINE" "$EXPECTED_AUTHOR" >> $LOG_FILE
|
|
||||||
;;
|
|
||||||
5)
|
|
||||||
[[ "$LINE" == "$EXPECTED_LICENSE" ]] || printf "Line %d was: '%s' | Should be: '%s'\n" "$i" "$LINE" "$EXPECTED_LICENSE" >> $LOG_FILE
|
|
||||||
;;
|
|
||||||
6)
|
|
||||||
[[ $LINE == $EXPECTED_SOURCE* ]] || printf "Line %d was: '%s' | Should start with: '%s'\n" "$i" "$LINE" "$EXPECTED_SOURCE" >> $LOG_FILE
|
|
||||||
;;
|
|
||||||
7)
|
|
||||||
[[ -z $LINE ]] || printf "Line %d was: '%s' | Should be empty\n" "$i" "$LINE" >> $LOG_FILE
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
done
|
|
||||||
|
|
||||||
[[ "$(sed -n '8p' "$FILE")" != 'source /dev/stdin <<< "$FUNCTIONS_FILE_PATH"' ]] && echo 'Line 8 should be: source /dev/stdin <<< "$FUNCTIONS_FILE_PATH"' >> "$LOG_FILE"
|
|
||||||
|
|
||||||
for i in {9..14}; do
|
|
||||||
LINE=$(sed -n "${i}p" "$FILE")
|
|
||||||
EXPECTED=(
|
|
||||||
"color"
|
|
||||||
"verb_ip6"
|
|
||||||
"catch_errors"
|
|
||||||
"setting_up_container"
|
|
||||||
"network_check"
|
|
||||||
"update_os"
|
|
||||||
)
|
|
||||||
[[ "$LINE" != "${EXPECTED[$((i-9))]}" ]] && echo "Line $i was $LINE | Should be: ${EXPECTED[$((i-9))]}" >> "$LOG_FILE"
|
|
||||||
done
|
|
||||||
|
|
||||||
[[ -n "$(sed -n '15p' "$FILE")" ]] && echo "Line 15 should be empty" >> "$LOG_FILE"
|
|
||||||
[[ "$(sed -n '16p' "$FILE")" != 'msg_info "Installing Dependencies"' ]] && echo 'Line 16 should be: msg_info "Installing Dependencies"' >> "$LOG_FILE"
|
|
||||||
|
|
||||||
LAST_3_LINES=$(tail -n 3 "$FILE")
|
|
||||||
[[ "$LAST_3_LINES" != *"$STD apt-get -y autoremove"* ]] && echo 'Third to last line should be: $STD apt-get -y autoremove' >> "$LOG_FILE"
|
|
||||||
[[ "$LAST_3_LINES" != *"$STD apt-get -y autoclean"* ]] && echo 'Second to last line should be: $STD apt-get -y clean' >> "$LOG_FILE"
|
|
||||||
[[ "$LAST_3_LINES" != *'msg_ok "Cleaned"'* ]] && echo 'Last line should be: msg_ok "Cleaned"' >> "$LOG_FILE"
|
|
||||||
cat "$LOG_FILE"
|
|
||||||
fi
|
|
||||||
|
|
||||||
done
|
|
||||||
|
|
||||||
|
|
||||||
- name: Post error comments
|
|
||||||
run: |
|
|
||||||
ERROR="false"
|
|
||||||
for FILE in ${{ env.SCRIPT }}; do
|
|
||||||
FILE_STRIPPED="${FILE##*/}"
|
|
||||||
LOG_FILE="result_$FILE_STRIPPED.log"
|
|
||||||
echo $LOG_FILE
|
|
||||||
if [[ ! -f $LOG_FILE ]]; then
|
|
||||||
continue
|
|
||||||
fi
|
|
||||||
ERROR_MSG=$(cat $LOG_FILE)
|
|
||||||
|
|
||||||
if [ -n "$ERROR_MSG" ]; then
|
|
||||||
echo "Posting error message for $FILE"
|
|
||||||
echo ${ERROR_MSG}
|
|
||||||
gh pr comment ${{ github.event.pull_request.number }} \
|
|
||||||
--repo ${{ github.repository }} \
|
|
||||||
--body ":warning: The script _**$FILE**_ has the following formatting errors: <br> <div><strong>${ERROR_MSG}</strong></div>"
|
|
||||||
|
|
||||||
|
|
||||||
ERROR="true"
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
echo "ERROR=$ERROR" >> $GITHUB_ENV
|
|
||||||
env:
|
|
||||||
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
||||||
|
|
||||||
- name: Fail if error
|
|
||||||
if: ${{ env.ERROR == 'true' }}
|
|
||||||
run: exit 1
|
|
||||||
@@ -1,86 +0,0 @@
|
|||||||
#!/usr/bin/env bash
|
|
||||||
# Copyright (c) 2021-2025 community-scripts ORG
|
|
||||||
# Author: Michel Roegl-Brunner (michelroegl-brunner)
|
|
||||||
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
|
|
||||||
|
|
||||||
color() {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
catch_errors() {
|
|
||||||
set -Eeuo pipefail
|
|
||||||
trap 'error_handler $LINENO "$BASH_COMMAND"' ERR
|
|
||||||
}
|
|
||||||
|
|
||||||
# This function handles errors
|
|
||||||
error_handler() {
|
|
||||||
local line_number="$1"
|
|
||||||
local command="$2"
|
|
||||||
SCRIPT_NAME=$(basename "$0")
|
|
||||||
local error_message="$SCRIPT_NAME: Failure in line $line_number while executing command $command"
|
|
||||||
echo -e "\n$error_message"
|
|
||||||
exit 0
|
|
||||||
}
|
|
||||||
verb_ip6() {
|
|
||||||
STD=""
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
msg_info() {
|
|
||||||
local msg="$1"
|
|
||||||
echo -ne "${msg}\n"
|
|
||||||
}
|
|
||||||
|
|
||||||
msg_ok() {
|
|
||||||
local msg="$1"
|
|
||||||
echo -e "${msg}\n"
|
|
||||||
}
|
|
||||||
|
|
||||||
msg_error() {
|
|
||||||
|
|
||||||
local msg="$1"
|
|
||||||
echo -e "${msg}\n"
|
|
||||||
}
|
|
||||||
|
|
||||||
RETRY_NUM=10
|
|
||||||
RETRY_EVERY=3
|
|
||||||
i=$RETRY_NUM
|
|
||||||
|
|
||||||
setting_up_container() {
|
|
||||||
while [ $i -gt 0 ]; do
|
|
||||||
if [ "$(ip addr show | grep 'inet ' | grep -v '127.0.0.1' | awk '{print $2}' | cut -d'/' -f1)" != "" ]; then
|
|
||||||
break
|
|
||||||
fi
|
|
||||||
echo 1>&2 -en "No Network! "
|
|
||||||
sleep $RETRY_EVERY
|
|
||||||
i=$((i - 1))
|
|
||||||
done
|
|
||||||
|
|
||||||
if [ "$(ip addr show | grep 'inet ' | grep -v '127.0.0.1' | awk '{print $2}' | cut -d'/' -f1)" = "" ]; then
|
|
||||||
echo 1>&2 -e "\n No Network After $RETRY_NUM Tries"
|
|
||||||
echo -e "Check Network Settings"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
msg_ok "Set up Container OS"
|
|
||||||
msg_ok "Network Connected: $(hostname -i)"
|
|
||||||
}
|
|
||||||
|
|
||||||
network_check() {
|
|
||||||
RESOLVEDIP=$(getent hosts github.com | awk '{ print $1 }')
|
|
||||||
if [[ -z "$RESOLVEDIP" ]]; then msg_error "DNS Lookup Failure"; else msg_ok "DNS Resolved github.com to $RESOLVEDIP"; fi
|
|
||||||
set -e
|
|
||||||
}
|
|
||||||
|
|
||||||
update_os() {
|
|
||||||
msg_info "Updating Container OS"
|
|
||||||
apk update
|
|
||||||
apk upgrade
|
|
||||||
msg_ok "Updated Container OS"
|
|
||||||
}
|
|
||||||
|
|
||||||
motd_ssh() {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
customize() {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
@@ -1,260 +0,0 @@
|
|||||||
#!/usr/bin/env bash
|
|
||||||
# Copyright (c) 2021-2025 community-scripts ORG
|
|
||||||
# Author: Michel Roegl-Brunner (michelroegl-brunner)
|
|
||||||
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
|
|
||||||
|
|
||||||
variables() {
|
|
||||||
NSAPP=$(echo ${APP,,} | tr -d ' ') # This function sets the NSAPP variable by converting the value of the APP variable to lowercase and removing any spaces.
|
|
||||||
var_install="${NSAPP}-install" # sets the var_install variable by appending "-install" to the value of NSAPP.
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
NEXTID=$(pvesh get /cluster/nextid)
|
|
||||||
timezone=$(cat /etc/timezone)
|
|
||||||
header_info() {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
base_settings() {
|
|
||||||
# Default Settings
|
|
||||||
CT_TYPE="1"
|
|
||||||
DISK_SIZE="4"
|
|
||||||
CORE_COUNT="1"
|
|
||||||
RAM_SIZE="1024"
|
|
||||||
VERBOSE="no"
|
|
||||||
PW=""
|
|
||||||
CT_ID=$NEXTID
|
|
||||||
HN=$NSAPP
|
|
||||||
BRG="vmbr0"
|
|
||||||
NET="dhcp"
|
|
||||||
GATE=""
|
|
||||||
APT_CACHER=""
|
|
||||||
APT_CACHER_IP=""
|
|
||||||
DISABLEIP6="no"
|
|
||||||
MTU=""
|
|
||||||
SD=""
|
|
||||||
NS=""
|
|
||||||
MAC=""
|
|
||||||
VLAN=""
|
|
||||||
SSH="no"
|
|
||||||
SSH_AUTHORIZED_KEY=""
|
|
||||||
TAGS="community-script;"
|
|
||||||
|
|
||||||
# Override default settings with variables from ct script
|
|
||||||
CT_TYPE=${var_unprivileged:-$CT_TYPE}
|
|
||||||
DISK_SIZE=${var_disk:-$DISK_SIZE}
|
|
||||||
CORE_COUNT=${var_cpu:-$CORE_COUNT}
|
|
||||||
RAM_SIZE=${var_ram:-$RAM_SIZE}
|
|
||||||
VERB=${var_verbose:-$VERBOSE}
|
|
||||||
TAGS="${TAGS}${var_tags:-}"
|
|
||||||
|
|
||||||
# Since these 2 are only defined outside of default_settings function, we add a temporary fallback. TODO: To align everything, we should add these as constant variables (e.g. OSTYPE and OSVERSION), but that would currently require updating the default_settings function for all existing scripts
|
|
||||||
if [ -z "$var_os" ]; then
|
|
||||||
var_os="debian"
|
|
||||||
fi
|
|
||||||
if [ -z "$var_version" ]; then
|
|
||||||
var_version="12"
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
color() {
|
|
||||||
# Colors
|
|
||||||
YW=$(echo "\033[33m")
|
|
||||||
YWB=$(echo "\033[93m")
|
|
||||||
BL=$(echo "\033[36m")
|
|
||||||
RD=$(echo "\033[01;31m")
|
|
||||||
BGN=$(echo "\033[4;92m")
|
|
||||||
GN=$(echo "\033[1;92m")
|
|
||||||
DGN=$(echo "\033[32m")
|
|
||||||
|
|
||||||
# Formatting
|
|
||||||
CL=$(echo "\033[m")
|
|
||||||
UL=$(echo "\033[4m")
|
|
||||||
BOLD=$(echo "\033[1m")
|
|
||||||
BFR="\\r\\033[K"
|
|
||||||
HOLD=" "
|
|
||||||
TAB=" "
|
|
||||||
|
|
||||||
# Icons
|
|
||||||
CM="${TAB}✔️${TAB}${CL}"
|
|
||||||
CROSS="${TAB}✖️${TAB}${CL}"
|
|
||||||
INFO="${TAB}💡${TAB}${CL}"
|
|
||||||
OS="${TAB}🖥️${TAB}${CL}"
|
|
||||||
OSVERSION="${TAB}🌟${TAB}${CL}"
|
|
||||||
CONTAINERTYPE="${TAB}📦${TAB}${CL}"
|
|
||||||
DISKSIZE="${TAB}💾${TAB}${CL}"
|
|
||||||
CPUCORE="${TAB}🧠${TAB}${CL}"
|
|
||||||
RAMSIZE="${TAB}🛠️${TAB}${CL}"
|
|
||||||
SEARCH="${TAB}🔍${TAB}${CL}"
|
|
||||||
VERIFYPW="${TAB}🔐${TAB}${CL}"
|
|
||||||
CONTAINERID="${TAB}🆔${TAB}${CL}"
|
|
||||||
HOSTNAME="${TAB}🏠${TAB}${CL}"
|
|
||||||
BRIDGE="${TAB}🌉${TAB}${CL}"
|
|
||||||
NETWORK="${TAB}📡${TAB}${CL}"
|
|
||||||
GATEWAY="${TAB}🌐${TAB}${CL}"
|
|
||||||
DISABLEIPV6="${TAB}🚫${TAB}${CL}"
|
|
||||||
DEFAULT="${TAB}⚙️${TAB}${CL}"
|
|
||||||
MACADDRESS="${TAB}🔗${TAB}${CL}"
|
|
||||||
VLANTAG="${TAB}🏷️${TAB}${CL}"
|
|
||||||
ROOTSSH="${TAB}🔑${TAB}${CL}"
|
|
||||||
CREATING="${TAB}🚀${TAB}${CL}"
|
|
||||||
ADVANCED="${TAB}🧩${TAB}${CL}"
|
|
||||||
}
|
|
||||||
|
|
||||||
catch_errors() {
|
|
||||||
set -Eeuo pipefail
|
|
||||||
trap 'error_handler $LINENO "$BASH_COMMAND"' ERR
|
|
||||||
}
|
|
||||||
|
|
||||||
# This function handles errors
|
|
||||||
error_handler() {
|
|
||||||
local line_number="$1"
|
|
||||||
local command="$2"
|
|
||||||
SCRIPT_NAME=$(basename "$0")
|
|
||||||
local error_message="$SCRIPT_NAME: Failure in line $line_number while executing command $command"
|
|
||||||
echo -e "\n$error_message"
|
|
||||||
exit 100
|
|
||||||
}
|
|
||||||
|
|
||||||
msg_info() {
|
|
||||||
local msg="$1"
|
|
||||||
echo -ne "${msg}\n"
|
|
||||||
}
|
|
||||||
|
|
||||||
msg_ok() {
|
|
||||||
local msg="$1"
|
|
||||||
echo -e "${msg}\n"
|
|
||||||
}
|
|
||||||
|
|
||||||
msg_error() {
|
|
||||||
|
|
||||||
local msg="$1"
|
|
||||||
echo -e "${msg}\n"
|
|
||||||
}
|
|
||||||
start() {
|
|
||||||
base_settings
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
build_container() {
|
|
||||||
# if [ "$VERB" == "yes" ]; then set -x; fi
|
|
||||||
|
|
||||||
if [ "$CT_TYPE" == "1" ]; then
|
|
||||||
FEATURES="keyctl=1,nesting=1"
|
|
||||||
else
|
|
||||||
FEATURES="nesting=1"
|
|
||||||
fi
|
|
||||||
TEMP_DIR=$(mktemp -d)
|
|
||||||
pushd $TEMP_DIR >/dev/null
|
|
||||||
if [ "$var_os" == "alpine" ]; then
|
|
||||||
export FUNCTIONS_FILE_PATH="$(curl -s https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/.github/workflows/scripts/app-test/pr-alpine-install.func)"
|
|
||||||
else
|
|
||||||
export FUNCTIONS_FILE_PATH="$(curl -s https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/.github/workflows/scripts/app-test/pr-install.func)"
|
|
||||||
fi
|
|
||||||
|
|
||||||
export CACHER="$APT_CACHER"
|
|
||||||
export CACHER_IP="$APT_CACHER_IP"
|
|
||||||
export tz=""
|
|
||||||
export DISABLEIPV6="$DISABLEIP6"
|
|
||||||
export APPLICATION="$APP"
|
|
||||||
export app="$NSAPP"
|
|
||||||
export PASSWORD="$PW"
|
|
||||||
export VERBOSE="$VERB"
|
|
||||||
export SSH_ROOT="${SSH}"
|
|
||||||
export SSH_AUTHORIZED_KEY
|
|
||||||
export CTID="$CT_ID"
|
|
||||||
export CTTYPE="$CT_TYPE"
|
|
||||||
export PCT_OSTYPE="$var_os"
|
|
||||||
export PCT_OSVERSION="$var_version"
|
|
||||||
export PCT_DISK_SIZE="$DISK_SIZE"
|
|
||||||
export tz="$timezone"
|
|
||||||
export PCT_OPTIONS="
|
|
||||||
-features $FEATURES
|
|
||||||
-hostname $HN
|
|
||||||
-tags $TAGS
|
|
||||||
$SD
|
|
||||||
$NS
|
|
||||||
-net0 name=eth0,bridge=$BRG$MAC,ip=$NET$GATE$VLAN$MTU
|
|
||||||
-onboot 1
|
|
||||||
-cores $CORE_COUNT
|
|
||||||
-memory $RAM_SIZE
|
|
||||||
-unprivileged $CT_TYPE
|
|
||||||
$PW
|
|
||||||
"
|
|
||||||
echo "Container ID: $CTID"
|
|
||||||
|
|
||||||
# This executes create_lxc.sh and creates the container and .conf file
|
|
||||||
bash -c "$(wget -qLO - https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/.github/workflows/scripts/app-test/pr-create-lxc.sh)"
|
|
||||||
|
|
||||||
LXC_CONFIG=/etc/pve/lxc/${CTID}.conf
|
|
||||||
if [ "$CT_TYPE" == "0" ]; then
|
|
||||||
cat <<EOF >>$LXC_CONFIG
|
|
||||||
# USB passthrough
|
|
||||||
lxc.cgroup2.devices.allow: a
|
|
||||||
lxc.cap.drop:
|
|
||||||
lxc.cgroup2.devices.allow: c 188:* rwm
|
|
||||||
lxc.cgroup2.devices.allow: c 189:* rwm
|
|
||||||
lxc.mount.entry: /dev/serial/by-id dev/serial/by-id none bind,optional,create=dir
|
|
||||||
lxc.mount.entry: /dev/ttyUSB0 dev/ttyUSB0 none bind,optional,create=file
|
|
||||||
lxc.mount.entry: /dev/ttyUSB1 dev/ttyUSB1 none bind,optional,create=file
|
|
||||||
lxc.mount.entry: /dev/ttyACM0 dev/ttyACM0 none bind,optional,create=file
|
|
||||||
lxc.mount.entry: /dev/ttyACM1 dev/ttyACM1 none bind,optional,create=file
|
|
||||||
EOF
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [ "$CT_TYPE" == "0" ]; then
|
|
||||||
if [[ "$APP" == "Channels" || "$APP" == "Emby" || "$APP" == "ErsatzTV" || "$APP" == "Frigate" || "$APP" == "Jellyfin" || "$APP" == "Plex" || "$APP" == "Scrypted" || "$APP" == "Tdarr" || "$APP" == "Unmanic" || "$APP" == "Ollama" ]]; then
|
|
||||||
cat <<EOF >>$LXC_CONFIG
|
|
||||||
# VAAPI hardware transcoding
|
|
||||||
lxc.cgroup2.devices.allow: c 226:0 rwm
|
|
||||||
lxc.cgroup2.devices.allow: c 226:128 rwm
|
|
||||||
lxc.cgroup2.devices.allow: c 29:0 rwm
|
|
||||||
lxc.mount.entry: /dev/fb0 dev/fb0 none bind,optional,create=file
|
|
||||||
lxc.mount.entry: /dev/dri dev/dri none bind,optional,create=dir
|
|
||||||
lxc.mount.entry: /dev/dri/renderD128 dev/dri/renderD128 none bind,optional,create=file
|
|
||||||
EOF
|
|
||||||
fi
|
|
||||||
else
|
|
||||||
if [[ "$APP" == "Channels" || "$APP" == "Emby" || "$APP" == "ErsatzTV" || "$APP" == "Frigate" || "$APP" == "Jellyfin" || "$APP" == "Plex" || "$APP" == "Scrypted" || "$APP" == "Tdarr" || "$APP" == "Unmanic" || "$APP" == "Ollama" ]]; then
|
|
||||||
if [[ -e "/dev/dri/renderD128" ]]; then
|
|
||||||
if [[ -e "/dev/dri/card0" ]]; then
|
|
||||||
cat <<EOF >>$LXC_CONFIG
|
|
||||||
# VAAPI hardware transcoding
|
|
||||||
dev0: /dev/dri/card0,gid=44
|
|
||||||
dev1: /dev/dri/renderD128,gid=104
|
|
||||||
EOF
|
|
||||||
else
|
|
||||||
cat <<EOF >>$LXC_CONFIG
|
|
||||||
# VAAPI hardware transcoding
|
|
||||||
dev0: /dev/dri/card1,gid=44
|
|
||||||
dev1: /dev/dri/renderD128,gid=104
|
|
||||||
EOF
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
|
|
||||||
# This starts the container and executes <app>-install.sh
|
|
||||||
msg_info "Starting LXC Container"
|
|
||||||
pct start "$CTID"
|
|
||||||
msg_ok "Started LXC Container"
|
|
||||||
|
|
||||||
if [[ ! -f "/root/actions-runner/_work/ProxmoxVE/ProxmoxVE/install/$var_install.sh" ]]; then
|
|
||||||
msg_error "No install script found for $APP"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
if [ "$var_os" == "alpine" ]; then
|
|
||||||
sleep 3
|
|
||||||
pct exec "$CTID" -- /bin/sh -c 'cat <<EOF >/etc/apk/repositories
|
|
||||||
http://dl-cdn.alpinelinux.org/alpine/latest-stable/main
|
|
||||||
http://dl-cdn.alpinelinux.org/alpine/latest-stable/community
|
|
||||||
EOF'
|
|
||||||
pct exec "$CTID" -- ash -c "apk add bash >/dev/null"
|
|
||||||
fi
|
|
||||||
lxc-attach -n "$CTID" -- bash -c "$(cat /root/actions-runner/_work/ProxmoxVE/ProxmoxVE/install/$var_install.sh)"
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
description() {
|
|
||||||
IP=$(pct exec "$CTID" ip a s dev eth0 | awk '/inet / {print $2}' | cut -d/ -f1)
|
|
||||||
}
|
|
||||||
@@ -1,163 +0,0 @@
|
|||||||
#!/usr/bin/env bash
|
|
||||||
# Copyright (c) 2021-2025 community-scripts ORG
|
|
||||||
# Author: Michel Roegl-Brunner (michelroegl-brunner)
|
|
||||||
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
|
|
||||||
|
|
||||||
color() {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
catch_errors() {
|
|
||||||
set -Eeuo pipefail
|
|
||||||
trap 'error_handler $LINENO "$BASH_COMMAND"' ERR
|
|
||||||
}
|
|
||||||
|
|
||||||
# This function handles errors
|
|
||||||
error_handler() {
|
|
||||||
local exit_code="$?"
|
|
||||||
local line_number="$1"
|
|
||||||
local command="$2"
|
|
||||||
local error_message="Failure in line $line_number: exit code $exit_code: while executing command $command"
|
|
||||||
echo -e "\n$error_message"
|
|
||||||
exit 100
|
|
||||||
}
|
|
||||||
verb_ip6() {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
msg_info() {
|
|
||||||
local msg="$1"
|
|
||||||
echo -ne "${msg}\n"
|
|
||||||
}
|
|
||||||
|
|
||||||
msg_ok() {
|
|
||||||
local msg="$1"
|
|
||||||
echo -e "${msg}\n"
|
|
||||||
}
|
|
||||||
|
|
||||||
msg_error() {
|
|
||||||
|
|
||||||
local msg="$1"
|
|
||||||
echo -e "${msg}\n"
|
|
||||||
}
|
|
||||||
|
|
||||||
VALIDCT=$(pvesm status -content rootdir | awk 'NR>1')
|
|
||||||
if [ -z "$VALIDCT" ]; then
|
|
||||||
msg_error "Unable to detect a valid Container Storage location."
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
VALIDTMP=$(pvesm status -content vztmpl | awk 'NR>1')
|
|
||||||
if [ -z "$VALIDTMP" ]; then
|
|
||||||
msg_error "Unable to detect a valid Template Storage location."
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
function select_storage() {
|
|
||||||
local CLASS=$1
|
|
||||||
local CONTENT
|
|
||||||
local CONTENT_LABEL
|
|
||||||
case $CLASS in
|
|
||||||
container)
|
|
||||||
CONTENT='rootdir'
|
|
||||||
CONTENT_LABEL='Container'
|
|
||||||
;;
|
|
||||||
template)
|
|
||||||
CONTENT='vztmpl'
|
|
||||||
CONTENT_LABEL='Container template'
|
|
||||||
;;
|
|
||||||
*) false || {
|
|
||||||
msg_error "Invalid storage class."
|
|
||||||
exit 201
|
|
||||||
} ;;
|
|
||||||
esac
|
|
||||||
|
|
||||||
# This Queries all storage locations
|
|
||||||
local -a MENU
|
|
||||||
while read -r line; do
|
|
||||||
local TAG=$(echo $line | awk '{print $1}')
|
|
||||||
local TYPE=$(echo $line | awk '{printf "%-10s", $2}')
|
|
||||||
local FREE=$(echo $line | numfmt --field 4-6 --from-unit=K --to=iec --format %.2f | awk '{printf( "%9sB", $6)}')
|
|
||||||
local ITEM="Type: $TYPE Free: $FREE "
|
|
||||||
local OFFSET=2
|
|
||||||
if [[ $((${#ITEM} + $OFFSET)) -gt ${MSG_MAX_LENGTH:-} ]]; then
|
|
||||||
local MSG_MAX_LENGTH=$((${#ITEM} + $OFFSET))
|
|
||||||
fi
|
|
||||||
MENU+=("$TAG" "$ITEM" "OFF")
|
|
||||||
done < <(pvesm status -content $CONTENT | awk 'NR>1')
|
|
||||||
|
|
||||||
# Select storage location
|
|
||||||
if [ $((${#MENU[@]} / 3)) -eq 1 ]; then
|
|
||||||
printf ${MENU[0]}
|
|
||||||
else
|
|
||||||
msg_error "STORAGE ISSUES!"
|
|
||||||
exit 202
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
[[ "${CTID:-}" ]] || {
|
|
||||||
msg_error "You need to set 'CTID' variable."
|
|
||||||
exit 203
|
|
||||||
}
|
|
||||||
[[ "${PCT_OSTYPE:-}" ]] || {
|
|
||||||
msg_error "You need to set 'PCT_OSTYPE' variable."
|
|
||||||
exit 204
|
|
||||||
}
|
|
||||||
|
|
||||||
# Test if ID is valid
|
|
||||||
[ "$CTID" -ge "100" ] || {
|
|
||||||
msg_error "ID cannot be less than 100."
|
|
||||||
exit 205
|
|
||||||
}
|
|
||||||
|
|
||||||
# Test if ID is in use
|
|
||||||
if pct status $CTID &>/dev/null; then
|
|
||||||
echo -e "ID '$CTID' is already in use."
|
|
||||||
unset CTID
|
|
||||||
msg_error "Cannot use ID that is already in use."
|
|
||||||
exit 206
|
|
||||||
fi
|
|
||||||
|
|
||||||
TEMPLATE_STORAGE=$(select_storage template) || exit
|
|
||||||
|
|
||||||
CONTAINER_STORAGE=$(select_storage container) || exit
|
|
||||||
|
|
||||||
pveam update >/dev/null
|
|
||||||
|
|
||||||
TEMPLATE_SEARCH=${PCT_OSTYPE}-${PCT_OSVERSION:-}
|
|
||||||
mapfile -t TEMPLATES < <(pveam available -section system | sed -n "s/.*\($TEMPLATE_SEARCH.*\)/\1/p" | sort -t - -k 2 -V)
|
|
||||||
[ ${#TEMPLATES[@]} -gt 0 ] || {
|
|
||||||
msg_error "Unable to find a template when searching for '$TEMPLATE_SEARCH'."
|
|
||||||
exit 207
|
|
||||||
}
|
|
||||||
TEMPLATE="${TEMPLATES[-1]}"
|
|
||||||
|
|
||||||
TEMPLATE_PATH="/var/lib/vz/template/cache/$TEMPLATE"
|
|
||||||
|
|
||||||
if ! pveam list "$TEMPLATE_STORAGE" | grep -q "$TEMPLATE"; then
|
|
||||||
[[ -f "$TEMPLATE_PATH" ]] && rm -f "$TEMPLATE_PATH"
|
|
||||||
pveam download "$TEMPLATE_STORAGE" "$TEMPLATE" >/dev/null ||
|
|
||||||
{
|
|
||||||
msg_error "A problem occurred while downloading the LXC template."
|
|
||||||
exit 208
|
|
||||||
}
|
|
||||||
fi
|
|
||||||
|
|
||||||
grep -q "root:100000:65536" /etc/subuid || echo "root:100000:65536" >>/etc/subuid
|
|
||||||
grep -q "root:100000:65536" /etc/subgid || echo "root:100000:65536" >>/etc/subgid
|
|
||||||
|
|
||||||
PCT_OPTIONS=(${PCT_OPTIONS[@]:-${DEFAULT_PCT_OPTIONS[@]}})
|
|
||||||
[[ " ${PCT_OPTIONS[@]} " =~ " -rootfs " ]] || PCT_OPTIONS+=(-rootfs "$CONTAINER_STORAGE:${PCT_DISK_SIZE:-8}")
|
|
||||||
|
|
||||||
if ! pct create "$CTID" "${TEMPLATE_STORAGE}:vztmpl/${TEMPLATE}" "${PCT_OPTIONS[@]}" &>/dev/null; then
|
|
||||||
[[ -f "$TEMPLATE_PATH" ]] && rm -f "$TEMPLATE_PATH"
|
|
||||||
|
|
||||||
pveam download "$TEMPLATE_STORAGE" "$TEMPLATE" >/dev/null ||
|
|
||||||
{
|
|
||||||
msg_error "A problem occurred while re-downloading the LXC template."
|
|
||||||
exit 208
|
|
||||||
}
|
|
||||||
|
|
||||||
if ! pct create "$CTID" "${TEMPLATE_STORAGE}:vztmpl/${TEMPLATE}" "${PCT_OPTIONS[@]}" &>/dev/null; then
|
|
||||||
msg_error "A problem occurred while trying to create container after re-downloading template."
|
|
||||||
exit 200
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
@@ -1,93 +0,0 @@
|
|||||||
#!/usr/bin/env bash
|
|
||||||
# Copyright (c) 2021-2025 community-scripts ORG
|
|
||||||
# Author: Michel Roegl-Brunner (michelroegl-brunner)
|
|
||||||
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
|
|
||||||
|
|
||||||
color() {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
catch_errors() {
|
|
||||||
set -Euo pipefail
|
|
||||||
trap 'error_handler $LINENO "$BASH_COMMAND"' ERR
|
|
||||||
}
|
|
||||||
|
|
||||||
error_handler() {
|
|
||||||
local line_number="$1"
|
|
||||||
local command="$2"
|
|
||||||
local error_message="Failure in line $line_number while executing command '$command'"
|
|
||||||
echo -e "\n$error_message\n" >&2
|
|
||||||
exit 1
|
|
||||||
}
|
|
||||||
|
|
||||||
verb_ip6() {
|
|
||||||
STD="silent"
|
|
||||||
silent() {
|
|
||||||
"$@" >/dev/null 2>&1 || error_handler "${BASH_LINENO[0]}" "$*"
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
msg_info() {
|
|
||||||
local msg="$1"
|
|
||||||
echo -ne "${msg}\n"
|
|
||||||
}
|
|
||||||
|
|
||||||
msg_ok() {
|
|
||||||
local msg="$1"
|
|
||||||
echo -e "${msg}\n"
|
|
||||||
}
|
|
||||||
|
|
||||||
msg_error() {
|
|
||||||
|
|
||||||
local msg="$1"
|
|
||||||
echo -e "${msg}\n"
|
|
||||||
}
|
|
||||||
|
|
||||||
RETRY_NUM=10
|
|
||||||
RETRY_EVERY=3
|
|
||||||
setting_up_container() {
|
|
||||||
|
|
||||||
sed -i "/$LANG/ s/\(^# \)//" /etc/locale.gen
|
|
||||||
locale_line=$(grep -v '^#' /etc/locale.gen | grep -E '^[a-zA-Z]' | awk '{print $1}' | head -n 1)
|
|
||||||
echo "LANG=${locale_line}" >/etc/default/locale
|
|
||||||
locale-gen >/dev/null
|
|
||||||
export LANG=${locale_line}
|
|
||||||
echo $tz >/etc/timezone
|
|
||||||
ln -sf /usr/share/zoneinfo/$tz /etc/localtime
|
|
||||||
|
|
||||||
for ((i = RETRY_NUM; i > 0; i--)); do
|
|
||||||
if [ "$(hostname -I)" != "" ]; then
|
|
||||||
break
|
|
||||||
fi
|
|
||||||
sleep $RETRY_EVERY
|
|
||||||
done
|
|
||||||
if [ "$(hostname -I)" = "" ]; then
|
|
||||||
echo 1>&2 -e "\nNo Network After $RETRY_NUM Tries"
|
|
||||||
echo -e "Check Network Settings"
|
|
||||||
exit 101
|
|
||||||
fi
|
|
||||||
rm -rf /usr/lib/python3.*/EXTERNALLY-MANAGED
|
|
||||||
systemctl disable -q --now systemd-networkd-wait-online.service
|
|
||||||
}
|
|
||||||
|
|
||||||
network_check() {
|
|
||||||
RESOLVEDIP=$(getent hosts github.com | awk '{ print $1 }')
|
|
||||||
if [[ -z "$RESOLVEDIP" ]]; then msg_error "DNS Lookup Failure"; else msg_ok "DNS Resolved github.com to $RESOLVEDIP"; fi
|
|
||||||
set -e
|
|
||||||
}
|
|
||||||
|
|
||||||
update_os() {
|
|
||||||
export DEBIAN_FRONTEND=noninteractive
|
|
||||||
apt-get update >/dev/null 2>&1
|
|
||||||
apt-get -o Dpkg::Options::="--force-confold" -y dist-upgrade >/dev/null
|
|
||||||
rm -rf /usr/lib/python3.*/EXTERNALLY-MANAGED
|
|
||||||
}
|
|
||||||
|
|
||||||
motd_ssh() {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
customize() {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
@@ -1,20 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
|
|
||||||
FILE=$1
|
|
||||||
TODAY=$(date -u +"%Y-%m-%d")
|
|
||||||
|
|
||||||
if [[ -z "$FILE" ]]; then
|
|
||||||
echo "No file specified. Exiting."
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [[ ! -f "$FILE" ]]; then
|
|
||||||
echo "File $FILE not found. Exiting."
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
DATE_IN_JSON=$(jq -r '.date_created' "$FILE" 2>/dev/null || echo "")
|
|
||||||
|
|
||||||
if [[ "$DATE_IN_JSON" != "$TODAY" ]]; then
|
|
||||||
jq --arg date "$TODAY" '.date_created = $date' "$FILE" > tmp.json && mv tmp.json "$FILE"
|
|
||||||
fi
|
|
||||||
@@ -1,23 +0,0 @@
|
|||||||
#!/usr/bin/env bash
|
|
||||||
|
|
||||||
# Verzeichnis, das die JSON-Dateien enthält
|
|
||||||
json_dir="./json/*.json"
|
|
||||||
|
|
||||||
current_date=$(date +"%Y-%m-%d")
|
|
||||||
|
|
||||||
for json_file in $json_dir; do
|
|
||||||
if [[ -f "$json_file" ]]; then
|
|
||||||
current_json_date=$(jq -r '.date_created' "$json_file")
|
|
||||||
|
|
||||||
if [[ "$current_json_date" != "$current_date" ]]; then
|
|
||||||
echo "Updating $json_file with date $current_date"
|
|
||||||
jq --arg date "$current_date" '.date_created = $date' "$json_file" > temp.json && mv temp.json "$json_file"
|
|
||||||
|
|
||||||
git add "$json_file"
|
|
||||||
git commit -m "Update date_created to $current_date in $json_file"
|
|
||||||
else
|
|
||||||
echo "Date in $json_file is already up to date."
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
git push origin HEAD
|
|
||||||
@@ -1,131 +0,0 @@
|
|||||||
name: Update JSON Date
|
|
||||||
|
|
||||||
on:
|
|
||||||
push:
|
|
||||||
branches:
|
|
||||||
- main
|
|
||||||
paths:
|
|
||||||
- 'json/**.json'
|
|
||||||
workflow_dispatch:
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
update-app-files:
|
|
||||||
runs-on: runner-cluster-htl-set
|
|
||||||
|
|
||||||
permissions:
|
|
||||||
contents: write
|
|
||||||
pull-requests: write
|
|
||||||
|
|
||||||
steps:
|
|
||||||
- name: Generate a token
|
|
||||||
id: generate-token
|
|
||||||
uses: actions/create-github-app-token@v1
|
|
||||||
with:
|
|
||||||
app-id: ${{ vars.APP_ID }}
|
|
||||||
private-key: ${{ secrets.APP_PRIVATE_KEY }}
|
|
||||||
|
|
||||||
- name: Generate dynamic branch name
|
|
||||||
id: timestamp
|
|
||||||
run: echo "BRANCH_NAME=pr-update-json-$(date +'%Y%m%d%H%M%S')" >> $GITHUB_ENV
|
|
||||||
|
|
||||||
- name: Set up GH_TOKEN
|
|
||||||
env:
|
|
||||||
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
||||||
run: |
|
|
||||||
echo "GH_TOKEN=${GH_TOKEN}" >> $GITHUB_ENV
|
|
||||||
|
|
||||||
- name: Checkout Repository
|
|
||||||
uses: actions/checkout@v4
|
|
||||||
with:
|
|
||||||
fetch-depth: 2 # Ensure we have the last two commits
|
|
||||||
|
|
||||||
- name: Get Previous Commit
|
|
||||||
id: prev_commit
|
|
||||||
run: |
|
|
||||||
PREV_COMMIT=$(git rev-parse HEAD^)
|
|
||||||
echo "Previous commit: $PREV_COMMIT"
|
|
||||||
echo "prev_commit=$PREV_COMMIT" >> $GITHUB_ENV
|
|
||||||
|
|
||||||
- name: Get Newly Added JSON Files
|
|
||||||
id: new_json_files
|
|
||||||
run: |
|
|
||||||
git diff --name-only --diff-filter=A ${{ env.prev_commit }} HEAD | grep '^json/.*\.json$' > new_files.txt || true
|
|
||||||
echo "New files detected:"
|
|
||||||
cat new_files.txt || echo "No new files."
|
|
||||||
|
|
||||||
- name: Disable file mode changes
|
|
||||||
run: git config core.fileMode false
|
|
||||||
|
|
||||||
- name: Set up Git
|
|
||||||
run: |
|
|
||||||
git config --global user.name "GitHub Actions"
|
|
||||||
git config --global user.email "github-actions[bot]@users.noreply.github.com"
|
|
||||||
|
|
||||||
- name: Change JSON Date
|
|
||||||
id: change-json-date
|
|
||||||
run: |
|
|
||||||
current_date=$(date +"%Y-%m-%d")
|
|
||||||
while IFS= read -r file; do
|
|
||||||
# Skip empty lines
|
|
||||||
[[ -z "$file" ]] && continue
|
|
||||||
|
|
||||||
if [[ -f "$file" ]]; then
|
|
||||||
echo "Processing $file..."
|
|
||||||
current_json_date=$(jq -r '.date_created // empty' "$file")
|
|
||||||
if [[ -z "$current_json_date" || "$current_json_date" != "$current_date" ]]; then
|
|
||||||
echo "Updating $file with date $current_date"
|
|
||||||
jq --arg date "$current_date" '.date_created = $date' "$file" > temp.json && mv temp.json "$file"
|
|
||||||
else
|
|
||||||
echo "Date in $file is already up to date."
|
|
||||||
fi
|
|
||||||
else
|
|
||||||
echo "Warning: File $file not found!"
|
|
||||||
fi
|
|
||||||
done < new_files.txt
|
|
||||||
rm new_files.txt
|
|
||||||
|
|
||||||
- name: Check if there are any changes
|
|
||||||
run: |
|
|
||||||
echo "Checking for changes..."
|
|
||||||
git add -A # Untracked Dateien aufnehmen
|
|
||||||
git status
|
|
||||||
if git diff --cached --quiet; then
|
|
||||||
echo "No changes detected."
|
|
||||||
echo "changed=false" >> "$GITHUB_ENV"
|
|
||||||
else
|
|
||||||
echo "Changes detected:"
|
|
||||||
git diff --stat --cached
|
|
||||||
echo "changed=true" >> "$GITHUB_ENV"
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Step 7: Commit and create PR if changes exist
|
|
||||||
- name: Commit and create PR if changes exist
|
|
||||||
if: env.changed == 'true'
|
|
||||||
run: |
|
|
||||||
|
|
||||||
|
|
||||||
git commit -m "Update date in json"
|
|
||||||
git checkout -b ${{ env.BRANCH_NAME }}
|
|
||||||
git push origin ${{ env.BRANCH_NAME }}
|
|
||||||
|
|
||||||
gh pr create --title "[core] update date in json" \
|
|
||||||
--body "This PR is auto-generated by a GitHub Action to update the date in json." \
|
|
||||||
--head ${{ env.BRANCH_NAME }} \
|
|
||||||
--base main \
|
|
||||||
--label "automated pr"
|
|
||||||
env:
|
|
||||||
GH_TOKEN: ${{ steps.generate-token.outputs.token }}
|
|
||||||
|
|
||||||
- name: Approve pull request
|
|
||||||
if: env.changed == 'true'
|
|
||||||
env:
|
|
||||||
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
||||||
run: |
|
|
||||||
PR_NUMBER=$(gh pr list --head "${{ env.BRANCH_NAME }}" --json number --jq '.[].number')
|
|
||||||
if [ -n "$PR_NUMBER" ]; then
|
|
||||||
gh pr review $PR_NUMBER --approve
|
|
||||||
fi
|
|
||||||
|
|
||||||
- name: No changes detected
|
|
||||||
if: env.changed == 'false'
|
|
||||||
run: echo "No changes to commit. Workflow completed successfully."
|
|
||||||
Reference in New Issue
Block a user