mirror of
https://github.com/community-scripts/ProxmoxVE.git
synced 2026-03-15 14:33:01 +01:00
Compare commits
2 Commits
fix/patchm
...
cleanup_wo
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
febce9c0b0 | ||
|
|
4f93b1f287 |
68
.github/runner/docker/gh-runner-self.dockerfile
generated
vendored
68
.github/runner/docker/gh-runner-self.dockerfile
generated
vendored
@@ -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
|
|
||||||
55
.github/workflows/bak/close_template_issue.yml
generated
vendored
55
.github/workflows/bak/close_template_issue.yml
generated
vendored
@@ -1,55 +0,0 @@
|
|||||||
name: Auto-Close Wrong Template Issues
|
|
||||||
on:
|
|
||||||
issues:
|
|
||||||
types: [opened]
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
close_tteck_issues:
|
|
||||||
if: github.repository == 'community-scripts/ProxmoxVE'
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- name: Auto-close if wrong Template issue detected
|
|
||||||
uses: actions/github-script@v7
|
|
||||||
with:
|
|
||||||
script: |
|
|
||||||
const issue = context.payload.issue;
|
|
||||||
const content = `${issue.title}\n${issue.body}`;
|
|
||||||
const issueNumber = issue.number;
|
|
||||||
|
|
||||||
// Regex patterns (case-insensitive, flexible versioning)
|
|
||||||
const patterns = [
|
|
||||||
/Template\s+debian-13-standard_[\d.]+-[\d]+_amd64\.tar\.zst\s*\[(online|local)\]/i,
|
|
||||||
/Template\s+debian-13-standard_[\d.]+-[\d]+_amd64\.tar\.zst\s+is\s+missing\s+or\s+corrupted/i,
|
|
||||||
/Container\s+creation\s+failed\.?\s+Checking\s+if\s+template\s+is\s+corrupted\s+or\s+incomplete/i,
|
|
||||||
/Template\s+is\s+valid,\s+but\s+container\s+creation\s+still\s+failed/i,
|
|
||||||
/exit\s+code\s+0:\s+while\s+executing\s+command\s+bash\s+-c\s+"\$?\(curl\s+-fsSL\s+https:\/\/raw\.githubusercontent\.com\/[\w/-]+\/create_lxc\.sh\)"/i
|
|
||||||
];
|
|
||||||
|
|
||||||
const matched = patterns.some((regex) => regex.test(content));
|
|
||||||
|
|
||||||
if (matched) {
|
|
||||||
const message = "👋 Hello!\n\n" +
|
|
||||||
"It looks like you are referencing a **container creation issue with a Debian 13 template** (e.g. `debian-13-standard_13.x-x_amd64.tar.zst`).\n\n" +
|
|
||||||
"We receive many similar reports about this, and it's not related to the scripts themselves but to **a Proxmox base template bug**.\n\n" +
|
|
||||||
"Please refer to [discussion #8126](https://github.com/community-scripts/ProxmoxVE/discussions/8126) for details.\n" +
|
|
||||||
"If your issue persists after following the guidance there, feel free to reopen this issue.\n\n" +
|
|
||||||
"_This issue was automatically closed by a bot._";
|
|
||||||
|
|
||||||
await github.rest.issues.createComment({
|
|
||||||
...context.repo,
|
|
||||||
issue_number: issueNumber,
|
|
||||||
body: message
|
|
||||||
});
|
|
||||||
|
|
||||||
await github.rest.issues.addLabels({
|
|
||||||
...context.repo,
|
|
||||||
issue_number: issueNumber,
|
|
||||||
labels: ["not planned"]
|
|
||||||
});
|
|
||||||
|
|
||||||
await github.rest.issues.update({
|
|
||||||
...context.repo,
|
|
||||||
issue_number: issueNumber,
|
|
||||||
state: "closed"
|
|
||||||
});
|
|
||||||
}
|
|
||||||
126
.github/workflows/bak/crawl-versions.yaml
generated
vendored
126
.github/workflows/bak/crawl-versions.yaml
generated
vendored
@@ -1,126 +0,0 @@
|
|||||||
name: Crawl Versions from newreleases.io
|
|
||||||
|
|
||||||
on:
|
|
||||||
workflow_dispatch:
|
|
||||||
schedule:
|
|
||||||
# Runs at 12:00 AM and 12:00 PM UTC
|
|
||||||
- cron: "0 0,12 * * *"
|
|
||||||
|
|
||||||
permissions:
|
|
||||||
contents: write
|
|
||||||
pull-requests: write
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
crawl-versions:
|
|
||||||
if: github.repository == 'community-scripts/ProxmoxVE'
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
|
|
||||||
steps:
|
|
||||||
- name: Checkout Repository
|
|
||||||
uses: actions/checkout@v2
|
|
||||||
with:
|
|
||||||
repository: community-scripts/ProxmoxVE
|
|
||||||
ref: main
|
|
||||||
|
|
||||||
- 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: Crawl from newreleases.io
|
|
||||||
env:
|
|
||||||
token: ${{ secrets.NEWRELEASES_TOKEN }}
|
|
||||||
run: |
|
|
||||||
page=1
|
|
||||||
projects_file="project_json"
|
|
||||||
output_file="frontend/public/json/versions.json"
|
|
||||||
|
|
||||||
echo "[]" > $output_file
|
|
||||||
|
|
||||||
while true; do
|
|
||||||
|
|
||||||
echo "Start loop on page: $page"
|
|
||||||
|
|
||||||
projects=$(curl -s -H "X-Key: $token" "https://api.newreleases.io/v1/projects?page=$page")
|
|
||||||
total_pages=$(echo "$projects" | jq -r '.total_pages')
|
|
||||||
|
|
||||||
if [ -z "$total_pages" ] || [ "$total_pages" -eq 0 ]; then
|
|
||||||
echo "No pages available. Exiting."
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
if [ $page == $total_pages ]; then
|
|
||||||
break
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [ -z "$projects" ] || ! echo "$projects" | jq -e '.projects' > /dev/null; then
|
|
||||||
echo "No more projects or invalid response. Exiting."
|
|
||||||
break
|
|
||||||
fi
|
|
||||||
|
|
||||||
echo "$projects" > "$projects_file"
|
|
||||||
|
|
||||||
jq -r '.projects[] | "\(.id) \(.name)"' "$projects_file" | while read -r id name; do
|
|
||||||
version=$(curl -s -H "X-Key: $token" "https://api.newreleases.io/v1/projects/$id/latest-release")
|
|
||||||
version_data=$(echo "$version" | jq -r '.version // empty')
|
|
||||||
date=$(echo "$version" | jq -r '.date // empty')
|
|
||||||
if [ -n "$version_data" ]; then
|
|
||||||
jq --arg name "$name" --arg version "$version_data" --arg date "$date" \
|
|
||||||
'. += [{"name": $name, "version": $version, "date": $date}]' "$output_file" > "$output_file.tmp" && mv "$output_file.tmp" "$output_file"
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
((page++))
|
|
||||||
done
|
|
||||||
|
|
||||||
- name: Commit JSON
|
|
||||||
env:
|
|
||||||
GH_TOKEN: ${{ steps.generate-token.outputs.token }}
|
|
||||||
run: |
|
|
||||||
git config --global user.email "github-actions[bot]@users.noreply.github.com"
|
|
||||||
git config --global user.name "GitHub Actions[bot]"
|
|
||||||
git checkout -b update_versions || git checkout update_versions
|
|
||||||
git add frontend/public/json/versions.json
|
|
||||||
if git diff --cached --quiet; then
|
|
||||||
echo "No changes detected."
|
|
||||||
echo "changed=false" >> "$GITHUB_ENV"
|
|
||||||
exit 0
|
|
||||||
else
|
|
||||||
echo "Changes detected:"
|
|
||||||
git diff --stat --cached
|
|
||||||
echo "changed=true" >> "$GITHUB_ENV"
|
|
||||||
fi
|
|
||||||
git commit -m "Update versions.json"
|
|
||||||
git push origin update_versions --force
|
|
||||||
gh pr create --title "[Github Action] Update versions.json" --body "Update versions.json, crawled from newreleases.io" --base main --head update_versions --label "automated pr"
|
|
||||||
|
|
||||||
- name: Approve pull request
|
|
||||||
if: env.changed == 'true'
|
|
||||||
env:
|
|
||||||
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
||||||
run: |
|
|
||||||
PR_NUMBER=$(gh pr list --head "update_versions" --json number --jq '.[].number')
|
|
||||||
if [ -n "$PR_NUMBER" ]; then
|
|
||||||
gh pr review $PR_NUMBER --approve
|
|
||||||
fi
|
|
||||||
|
|
||||||
- name: Approve pull request and merge
|
|
||||||
if: env.changed == 'true'
|
|
||||||
env:
|
|
||||||
GH_TOKEN: ${{ secrets.PAT_AUTOMERGE }}
|
|
||||||
run: |
|
|
||||||
PR_NUMBER=$(gh pr list --head "update_versions" --json number --jq '.[].number')
|
|
||||||
if [ -n "$PR_NUMBER" ]; then
|
|
||||||
gh pr review $PR_NUMBER --approve
|
|
||||||
gh pr merge $PR_NUMBER --squash --admin
|
|
||||||
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 "update_versions" --json number --jq '.[].number')
|
|
||||||
if [ -n "$PR_NUMBER" ]; then
|
|
||||||
gh pr review $PR_NUMBER --approve
|
|
||||||
fi
|
|
||||||
175
.github/workflows/bak/script-test.yml
generated
vendored
175
.github/workflows/bak/script-test.yml
generated
vendored
@@ -1,175 +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:
|
|
||||||
if: github.repository == 'community-scripts/ProxmoxVE'
|
|
||||||
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 -fsSL 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
|
|
||||||
243
.github/workflows/bak/script_format.yml
generated
vendored
243
.github/workflows/bak/script_format.yml
generated
vendored
@@ -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:
|
|
||||||
if: github.repository == 'community-scripts/ProxmoxVE'
|
|
||||||
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 -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/build.func)" ]] &&
|
|
||||||
echo "Line 2 was $SECOND_LINE | Should be: source <(curl -fsSL 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-2026 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-2026 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
|
|
||||||
158
.github/workflows/bak/validate-filenames.yml
generated
vendored
158
.github/workflows/bak/validate-filenames.yml
generated
vendored
@@ -1,158 +0,0 @@
|
|||||||
name: Validate filenames
|
|
||||||
|
|
||||||
on:
|
|
||||||
pull_request_target:
|
|
||||||
paths:
|
|
||||||
- "ct/*.sh"
|
|
||||||
- "install/*.sh"
|
|
||||||
- "frontend/public/json/*.json"
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
check-files:
|
|
||||||
if: github.repository == 'community-scripts/ProxmoxVE'
|
|
||||||
name: Check changed files
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
permissions:
|
|
||||||
pull-requests: write
|
|
||||||
|
|
||||||
steps:
|
|
||||||
- name: Get pull request information
|
|
||||||
if: github.event_name == 'pull_request_target'
|
|
||||||
uses: actions/github-script@v7
|
|
||||||
id: pr
|
|
||||||
with:
|
|
||||||
script: |
|
|
||||||
const { data: pullRequest } = await github.rest.pulls.get({
|
|
||||||
...context.repo,
|
|
||||||
pull_number: context.payload.pull_request.number,
|
|
||||||
});
|
|
||||||
return pullRequest;
|
|
||||||
|
|
||||||
- name: Checkout code
|
|
||||||
uses: actions/checkout@v4
|
|
||||||
with:
|
|
||||||
fetch-depth: 0 # Ensure the full history is fetched for accurate diffing
|
|
||||||
ref: ${{ github.event_name == 'pull_request_target' && fromJSON(steps.pr.outputs.result).merge_commit_sha || '' }}
|
|
||||||
|
|
||||||
- name: Get changed files
|
|
||||||
id: changed-files
|
|
||||||
run: |
|
|
||||||
if ${{ github.event_name == 'pull_request_target' }}; then
|
|
||||||
echo "files=$(git diff --name-only ${{ github.event.pull_request.base.sha }} ${{ steps.pr.outputs.result && fromJSON(steps.pr.outputs.result).merge_commit_sha }} | xargs)" >> $GITHUB_OUTPUT
|
|
||||||
else
|
|
||||||
echo "files=$(git diff --name-only ${{ github.event.before }} ${{ github.event.after }} | xargs)" >> $GITHUB_OUTPUT
|
|
||||||
fi
|
|
||||||
|
|
||||||
- name: "Validate filenames in ct and install directory"
|
|
||||||
if: always() && steps.changed-files.outputs.files != ''
|
|
||||||
id: check-scripts
|
|
||||||
run: |
|
|
||||||
CHANGED_FILES=$(printf "%s\n" ${{ steps.changed-files.outputs.files }} | { grep -E '^(ct|install)/.*\.sh$' || true; })
|
|
||||||
|
|
||||||
NON_COMPLIANT_FILES=""
|
|
||||||
for FILE in $CHANGED_FILES; do
|
|
||||||
BASENAME=$(echo "$(basename "${FILE%.*}")")
|
|
||||||
if [[ ! "$BASENAME" =~ ^[a-z0-9-]+$ ]]; then
|
|
||||||
NON_COMPLIANT_FILES="$NON_COMPLIANT_FILES $FILE"
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
|
|
||||||
if [ -n "$NON_COMPLIANT_FILES" ]; then
|
|
||||||
echo "files=$NON_COMPLIANT_FILES" >> $GITHUB_OUTPUT
|
|
||||||
echo "Non-compliant filenames found, change to lowercase:"
|
|
||||||
for FILE in $NON_COMPLIANT_FILES; do
|
|
||||||
echo "$FILE"
|
|
||||||
done
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
- name: "Validate filenames in json directory."
|
|
||||||
if: always() && steps.changed-files.outputs.files != ''
|
|
||||||
id: check-json
|
|
||||||
run: |
|
|
||||||
CHANGED_FILES=$(printf "%s\n" ${{ steps.changed-files.outputs.files }} | { grep -E '^json/.*\.json$' || true; })
|
|
||||||
|
|
||||||
NON_COMPLIANT_FILES=""
|
|
||||||
for FILE in $CHANGED_FILES; do
|
|
||||||
BASENAME=$(echo "$(basename "${FILE%.*}")")
|
|
||||||
if [[ ! "$BASENAME" =~ ^[a-z0-9-]+$ ]]; then
|
|
||||||
NON_COMPLIANT_FILES="$NON_COMPLIANT_FILES $FILE"
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
|
|
||||||
if [ -n "$NON_COMPLIANT_FILES" ]; then
|
|
||||||
echo "files=$NON_COMPLIANT_FILES" >> $GITHUB_OUTPUT
|
|
||||||
echo "Non-compliant filenames found, change to lowercase:"
|
|
||||||
for FILE in $NON_COMPLIANT_FILES; do
|
|
||||||
echo "$FILE"
|
|
||||||
done
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
- name: Post results and comment
|
|
||||||
if: always() && steps.check-scripts.outputs.files != '' && steps.check-json.outputs.files != '' && github.event_name == 'pull_request_target'
|
|
||||||
uses: actions/github-script@v7
|
|
||||||
with:
|
|
||||||
script: |
|
|
||||||
const result = "${{ job.status }}" === "success" ? "success" : "failure";
|
|
||||||
const nonCompliantFiles = {
|
|
||||||
script: "${{ steps.check-scripts.outputs.files }}",
|
|
||||||
JSON: "${{ steps.check-json.outputs.files }}",
|
|
||||||
};
|
|
||||||
|
|
||||||
const issueNumber = context.payload.pull_request
|
|
||||||
? context.payload.pull_request.number
|
|
||||||
: null;
|
|
||||||
const commentIdentifier = "validate-filenames";
|
|
||||||
let newCommentBody = `<!-- ${commentIdentifier}-start -->\n### Filename validation\n\n`;
|
|
||||||
|
|
||||||
if (result === "failure") {
|
|
||||||
newCommentBody += ":x: We found issues in the following changed files:\n\n";
|
|
||||||
for (const [check, files] of Object.entries(nonCompliantFiles)) {
|
|
||||||
if (files) {
|
|
||||||
newCommentBody += `**${check.charAt(0).toUpperCase() + check.slice(1)} filename invalid:**\n${files
|
|
||||||
.trim()
|
|
||||||
.split(" ")
|
|
||||||
.map((file) => `- ${file}`)
|
|
||||||
.join("\n")}\n\n`;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
newCommentBody +=
|
|
||||||
"Please change the filenames to lowercase and use only alphanumeric characters and dashes.\n";
|
|
||||||
} else {
|
|
||||||
newCommentBody += `:rocket: All files passed filename validation!\n`;
|
|
||||||
}
|
|
||||||
|
|
||||||
newCommentBody += `\n\n<!-- ${commentIdentifier}-end -->`;
|
|
||||||
|
|
||||||
if (issueNumber) {
|
|
||||||
const { data: comments } = await github.rest.issues.listComments({
|
|
||||||
...context.repo,
|
|
||||||
issue_number: issueNumber,
|
|
||||||
});
|
|
||||||
|
|
||||||
const existingComment = comments.find(
|
|
||||||
(comment) => comment.user.login === "github-actions[bot]",
|
|
||||||
);
|
|
||||||
|
|
||||||
if (existingComment) {
|
|
||||||
if (existingComment.body.includes(commentIdentifier)) {
|
|
||||||
const re = new RegExp(String.raw`<!-- ${commentIdentifier}-start -->[\s\S]*?<!-- ${commentIdentifier}-end -->`, "");
|
|
||||||
newCommentBody = existingComment.body.replace(re, newCommentBody);
|
|
||||||
} else {
|
|
||||||
newCommentBody = existingComment.body + '\n\n---\n\n' + newCommentBody;
|
|
||||||
}
|
|
||||||
|
|
||||||
await github.rest.issues.updateComment({
|
|
||||||
...context.repo,
|
|
||||||
comment_id: existingComment.id,
|
|
||||||
body: newCommentBody,
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
await github.rest.issues.createComment({
|
|
||||||
...context.repo,
|
|
||||||
issue_number: issueNumber,
|
|
||||||
body: newCommentBody,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
164
.github/workflows/close-discussion.yml
generated
vendored
164
.github/workflows/close-discussion.yml
generated
vendored
@@ -1,164 +0,0 @@
|
|||||||
name: Close Discussion on PR Merge
|
|
||||||
|
|
||||||
on:
|
|
||||||
push:
|
|
||||||
branches:
|
|
||||||
- main
|
|
||||||
|
|
||||||
permissions:
|
|
||||||
contents: read
|
|
||||||
discussions: write
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
close-discussion:
|
|
||||||
if: github.repository == 'community-scripts/ProxmoxVE'
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
|
|
||||||
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 }}
|
|
||||||
GITHUB_SHA: ${{ github.sha }}
|
|
||||||
GITHUB_REPOSITORY: ${{ github.repository }}
|
|
||||||
run: |
|
|
||||||
npx zx << 'EOF'
|
|
||||||
import { graphql } from "@octokit/graphql";
|
|
||||||
|
|
||||||
(async function () {
|
|
||||||
try {
|
|
||||||
const token = process.env.GITHUB_TOKEN;
|
|
||||||
const commitSha = process.env.GITHUB_SHA;
|
|
||||||
const [owner, repo] = process.env.GITHUB_REPOSITORY.split("/");
|
|
||||||
|
|
||||||
if (!token || !commitSha || !owner || !repo) {
|
|
||||||
console.log("Missing required environment variables.");
|
|
||||||
process.exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
const graphqlWithAuth = graphql.defaults({
|
|
||||||
headers: { authorization: `Bearer ${token}` },
|
|
||||||
});
|
|
||||||
|
|
||||||
// Find PR from commit SHA
|
|
||||||
const searchQuery = `
|
|
||||||
query($owner: String!, $repo: String!, $sha: GitObjectID!) {
|
|
||||||
repository(owner: $owner, name: $repo) {
|
|
||||||
object(oid: $sha) {
|
|
||||||
... on Commit {
|
|
||||||
associatedPullRequests(first: 1) {
|
|
||||||
nodes {
|
|
||||||
number
|
|
||||||
body
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
`;
|
|
||||||
|
|
||||||
const prResult = await graphqlWithAuth(searchQuery, {
|
|
||||||
owner,
|
|
||||||
repo,
|
|
||||||
sha: commitSha,
|
|
||||||
});
|
|
||||||
|
|
||||||
const pr = prResult.repository.object.associatedPullRequests.nodes[0];
|
|
||||||
if (!pr) {
|
|
||||||
console.log("No PR found for this commit.");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const prNumber = pr.number;
|
|
||||||
const prBody = pr.body;
|
|
||||||
|
|
||||||
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}`);
|
|
||||||
|
|
||||||
// Fetch GraphQL discussion ID
|
|
||||||
const discussionQuery = `
|
|
||||||
query($owner: String!, $repo: String!, $number: Int!) {
|
|
||||||
repository(owner: $owner, name: $repo) {
|
|
||||||
discussion(number: $number) {
|
|
||||||
id
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
`;
|
|
||||||
|
|
||||||
let discussionQLId;
|
|
||||||
try {
|
|
||||||
const discussionResponse = await graphqlWithAuth(discussionQuery, {
|
|
||||||
owner,
|
|
||||||
repo,
|
|
||||||
number: parseInt(discussionNumber, 10),
|
|
||||||
});
|
|
||||||
|
|
||||||
discussionQLId = discussionResponse.repository.discussion.id;
|
|
||||||
if (!discussionQLId) {
|
|
||||||
console.log("Failed to fetch discussion GraphQL ID.");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
} catch (error) {
|
|
||||||
console.error("Discussion not found or error occurred while fetching discussion:", error);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Post comment
|
|
||||||
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}`);
|
|
||||||
|
|
||||||
// Mark comment as answer
|
|
||||||
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);
|
|
||||||
process.exit(1);
|
|
||||||
}
|
|
||||||
})();
|
|
||||||
EOF
|
|
||||||
38
.github/workflows/create-docker-for-runner.yml
generated
vendored
38
.github/workflows/create-docker-for-runner.yml
generated
vendored
@@ -1,38 +0,0 @@
|
|||||||
name: Build and Publish Docker Image
|
|
||||||
|
|
||||||
on:
|
|
||||||
push:
|
|
||||||
branches:
|
|
||||||
- main
|
|
||||||
paths:
|
|
||||||
- '.github/runner/docker/**'
|
|
||||||
schedule:
|
|
||||||
- cron: '0 0 * * *'
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
build:
|
|
||||||
if: github.repository == 'community-scripts/ProxmoxVE'
|
|
||||||
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
|
|
||||||
29
.github/workflows/delete-json-branch.yml
generated
vendored
29
.github/workflows/delete-json-branch.yml
generated
vendored
@@ -1,29 +0,0 @@
|
|||||||
|
|
||||||
name: Delete JSON date PR Branch
|
|
||||||
|
|
||||||
on:
|
|
||||||
pull_request:
|
|
||||||
types: [closed]
|
|
||||||
branches:
|
|
||||||
- main
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
delete_branch:
|
|
||||||
if: github.repository == 'community-scripts/ProxmoxVE'
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
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
|
|
||||||
48
.github/workflows/push-to-gitea.yaml
generated
vendored
48
.github/workflows/push-to-gitea.yaml
generated
vendored
@@ -1,48 +0,0 @@
|
|||||||
name: Sync to Gitea
|
|
||||||
|
|
||||||
on:
|
|
||||||
push:
|
|
||||||
branches:
|
|
||||||
- main
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
sync:
|
|
||||||
if: github.repository == 'community-scripts/ProxmoxVE'
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
|
|
||||||
steps:
|
|
||||||
- name: Checkout source repo
|
|
||||||
uses: actions/checkout@v4
|
|
||||||
with:
|
|
||||||
fetch-depth: 0
|
|
||||||
|
|
||||||
- name: Change all links to git.community-scripts.org
|
|
||||||
run: |
|
|
||||||
echo "Searching for files containing raw.githubusercontent.com URLs..."
|
|
||||||
|
|
||||||
# Find all files containing GitHub raw URLs, excluding certain directories
|
|
||||||
files_with_github_urls=$(grep -r "https://raw.githubusercontent.com/community-scripts/ProxmoxVE" . --exclude-dir=.git --exclude-dir=node_modules --exclude-dir=.github/workflows --files-with-matches || true)
|
|
||||||
|
|
||||||
if [ -n "$files_with_github_urls" ]; then
|
|
||||||
echo "$files_with_github_urls" | while read file; do
|
|
||||||
if [ -f "$file" ]; then
|
|
||||||
sed -i 's|https://raw\.githubusercontent\.com/community-scripts/ProxmoxVE/|https://git.community-scripts.org/community-scripts/ProxmoxVE/raw/branch/|g' "$file"
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
else
|
|
||||||
echo "No files found containing GitHub raw URLs"
|
|
||||||
fi
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
- name: Push to Gitea
|
|
||||||
run: |
|
|
||||||
git config --global user.name "Push From Github"
|
|
||||||
git config --global user.email "actions@github.com"
|
|
||||||
git remote add gitea https://$GITEA_USER:$GITEA_TOKEN@git.community-scripts.org/community-scripts/ProxmoxVE.git
|
|
||||||
git add .
|
|
||||||
git commit -m "Sync to Gitea"
|
|
||||||
git push gitea --all --force
|
|
||||||
env:
|
|
||||||
GITEA_USER: ${{ secrets.GITEA_USERNAME }}
|
|
||||||
GITEA_TOKEN: ${{ secrets.GITEA_TOKEN }}
|
|
||||||
85
.github/workflows/scripts/app-test/pr-alpine-install.func
generated
vendored
85
.github/workflows/scripts/app-test/pr-alpine-install.func
generated
vendored
@@ -1,85 +0,0 @@
|
|||||||
#!/usr/bin/env bash
|
|
||||||
# Copyright (c) 2021-2026 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"
|
|
||||||
$STD apk -U upgrade
|
|
||||||
msg_ok "Updated Container OS"
|
|
||||||
}
|
|
||||||
|
|
||||||
motd_ssh() {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
customize() {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
260
.github/workflows/scripts/app-test/pr-build.func
generated
vendored
260
.github/workflows/scripts/app-test/pr-build.func
generated
vendored
@@ -1,260 +0,0 @@
|
|||||||
#!/usr/bin/env bash
|
|
||||||
# Copyright (c) 2021-2026 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 "$(curl -fsSL 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)
|
|
||||||
}
|
|
||||||
163
.github/workflows/scripts/app-test/pr-create-lxc.sh
generated
vendored
163
.github/workflows/scripts/app-test/pr-create-lxc.sh
generated
vendored
@@ -1,163 +0,0 @@
|
|||||||
#!/usr/bin/env bash
|
|
||||||
# Copyright (c) 2021-2026 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
|
|
||||||
93
.github/workflows/scripts/app-test/pr-install.func
generated
vendored
93
.github/workflows/scripts/app-test/pr-install.func
generated
vendored
@@ -1,93 +0,0 @@
|
|||||||
#!/usr/bin/env bash
|
|
||||||
# Copyright (c) 2021-2026 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
|
|
||||||
}
|
|
||||||
20
.github/workflows/scripts/update-json.sh
generated
vendored
20
.github/workflows/scripts/update-json.sh
generated
vendored
@@ -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
|
|
||||||
23
.github/workflows/scripts/update_json_date.sh
generated
vendored
23
.github/workflows/scripts/update_json_date.sh
generated
vendored
@@ -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
|
|
||||||
152
.github/workflows/update-json-date.yml
generated
vendored
152
.github/workflows/update-json-date.yml
generated
vendored
@@ -1,152 +0,0 @@
|
|||||||
name: Update JSON Date
|
|
||||||
|
|
||||||
on:
|
|
||||||
push:
|
|
||||||
branches:
|
|
||||||
- main
|
|
||||||
paths:
|
|
||||||
- "json/**.json"
|
|
||||||
workflow_dispatch:
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
update-app-files:
|
|
||||||
if: github.repository == 'community-scripts/ProxmoxVE'
|
|
||||||
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: Generate a token for PR approval and merge
|
|
||||||
id: generate-token-merge
|
|
||||||
uses: actions/create-github-app-token@v1
|
|
||||||
with:
|
|
||||||
app-id: ${{ secrets.APP_ID_APPROVE_AND_MERGE }}
|
|
||||||
private-key: ${{ secrets.APP_KEY_APPROVE_AND_MERGE }}
|
|
||||||
|
|
||||||
- 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
|
|
||||||
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: Approve pull request and merge
|
|
||||||
if: env.changed == 'true'
|
|
||||||
env:
|
|
||||||
GH_TOKEN: ${{ steps.generate-token-merge.outputs.token }}
|
|
||||||
run: |
|
|
||||||
git config --global user.name "github-actions-automege[bot]"
|
|
||||||
git config --global user.email "github-actions-automege[bot]@users.noreply.github.com"
|
|
||||||
PR_NUMBER=$(gh pr list --head "${BRANCH_NAME}" --json number --jq '.[].number')
|
|
||||||
if [ -n "$PR_NUMBER" ]; then
|
|
||||||
gh pr review $PR_NUMBER --approve
|
|
||||||
gh pr merge $PR_NUMBER --squash --admin
|
|
||||||
fi
|
|
||||||
|
|
||||||
- name: No changes detected
|
|
||||||
if: env.changed == 'false'
|
|
||||||
run: echo "No changes to commit. Workflow completed successfully."
|
|
||||||
236
.github/workflows/update-versions-github.yml
generated
vendored
236
.github/workflows/update-versions-github.yml
generated
vendored
@@ -1,236 +0,0 @@
|
|||||||
name: Update GitHub Versions (New)
|
|
||||||
|
|
||||||
on:
|
|
||||||
workflow_dispatch:
|
|
||||||
schedule:
|
|
||||||
# Runs 4x daily: 00:00, 06:00, 12:00, 18:00 UTC
|
|
||||||
- cron: "0 0,6,12,18 * * *"
|
|
||||||
|
|
||||||
permissions:
|
|
||||||
contents: write
|
|
||||||
pull-requests: write
|
|
||||||
|
|
||||||
env:
|
|
||||||
VERSIONS_FILE: json/github-versions.json
|
|
||||||
BRANCH_NAME: automated/update-github-versions
|
|
||||||
AUTOMATED_PR_LABEL: "automated pr"
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
update-github-versions:
|
|
||||||
if: github.repository == 'community-scripts/ProxmoxVE'
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
|
|
||||||
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 a token for PR approval and merge
|
|
||||||
id: generate-token-merge
|
|
||||||
uses: actions/create-github-app-token@v1
|
|
||||||
with:
|
|
||||||
app-id: ${{ secrets.APP_ID_APPROVE_AND_MERGE }}
|
|
||||||
private-key: ${{ secrets.APP_KEY_APPROVE_AND_MERGE }}
|
|
||||||
|
|
||||||
- name: Checkout Repository
|
|
||||||
uses: actions/checkout@v4
|
|
||||||
with:
|
|
||||||
ref: main
|
|
||||||
|
|
||||||
- name: Extract GitHub versions from install scripts
|
|
||||||
env:
|
|
||||||
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
||||||
run: |
|
|
||||||
set -euo pipefail
|
|
||||||
|
|
||||||
echo "========================================="
|
|
||||||
echo " Extracting GitHub versions from scripts"
|
|
||||||
echo "========================================="
|
|
||||||
|
|
||||||
# Initialize versions array
|
|
||||||
versions_json="[]"
|
|
||||||
|
|
||||||
# Function to add a version entry
|
|
||||||
add_version() {
|
|
||||||
local slug="$1"
|
|
||||||
local repo="$2"
|
|
||||||
local version="$3"
|
|
||||||
local pinned="$4"
|
|
||||||
local date="$5"
|
|
||||||
|
|
||||||
versions_json=$(echo "$versions_json" | jq \
|
|
||||||
--arg slug "$slug" \
|
|
||||||
--arg repo "$repo" \
|
|
||||||
--arg version "$version" \
|
|
||||||
--argjson pinned "$pinned" \
|
|
||||||
--arg date "$date" \
|
|
||||||
'. += [{"slug": $slug, "repo": $repo, "version": $version, "pinned": $pinned, "date": $date}]')
|
|
||||||
}
|
|
||||||
|
|
||||||
# Get list of slugs from JSON files
|
|
||||||
echo ""
|
|
||||||
echo "=== Scanning JSON files for slugs ==="
|
|
||||||
|
|
||||||
for json_file in json/*.json; do
|
|
||||||
[[ ! -f "$json_file" ]] && continue
|
|
||||||
|
|
||||||
# Skip non-app JSON files
|
|
||||||
basename_file=$(basename "$json_file")
|
|
||||||
case "$basename_file" in
|
|
||||||
metadata.json|versions.json|github-versions.json|dependency-check.json|update-apps.json)
|
|
||||||
continue
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
|
|
||||||
# Extract slug from JSON
|
|
||||||
slug=$(jq -r '.slug // empty' "$json_file" 2>/dev/null)
|
|
||||||
[[ -z "$slug" ]] && continue
|
|
||||||
|
|
||||||
# Find corresponding script (install script or addon script)
|
|
||||||
install_script=""
|
|
||||||
if [[ -f "install/${slug}-install.sh" ]]; then
|
|
||||||
install_script="install/${slug}-install.sh"
|
|
||||||
elif [[ -f "tools/addon/${slug}.sh" ]]; then
|
|
||||||
install_script="tools/addon/${slug}.sh"
|
|
||||||
else
|
|
||||||
continue
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Look for fetch_and_deploy_gh_release calls
|
|
||||||
# Pattern: fetch_and_deploy_gh_release "app" "owner/repo" ["mode"] ["version"]
|
|
||||||
while IFS= read -r line; do
|
|
||||||
# Skip commented lines
|
|
||||||
[[ "$line" =~ ^[[:space:]]*# ]] && continue
|
|
||||||
|
|
||||||
# Extract repo and version from fetch_and_deploy_gh_release
|
|
||||||
if [[ "$line" =~ fetch_and_deploy_gh_release[[:space:]]+\"[^\"]*\"[[:space:]]+\"([^\"]+)\"([[:space:]]+\"([^\"]+)\")?([[:space:]]+\"([^\"]+)\")? ]]; then
|
|
||||||
repo="${BASH_REMATCH[1]}"
|
|
||||||
mode="${BASH_REMATCH[3]:-tarball}"
|
|
||||||
pinned_version="${BASH_REMATCH[5]:-latest}"
|
|
||||||
|
|
||||||
# Check if version is pinned (not "latest" and not empty)
|
|
||||||
is_pinned=false
|
|
||||||
target_version=""
|
|
||||||
|
|
||||||
if [[ -n "$pinned_version" && "$pinned_version" != "latest" ]]; then
|
|
||||||
is_pinned=true
|
|
||||||
target_version="$pinned_version"
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Fetch version from GitHub
|
|
||||||
if [[ "$is_pinned" == "true" ]]; then
|
|
||||||
# For pinned versions, verify it exists and get date
|
|
||||||
response=$(gh api "repos/${repo}/releases/tags/${target_version}" 2>/dev/null || echo '{}')
|
|
||||||
if echo "$response" | jq -e '.tag_name' > /dev/null 2>&1; then
|
|
||||||
version=$(echo "$response" | jq -r '.tag_name')
|
|
||||||
date=$(echo "$response" | jq -r '.published_at // empty')
|
|
||||||
add_version "$slug" "$repo" "$version" "true" "$date"
|
|
||||||
echo "[$slug] ✓ $version (pinned)"
|
|
||||||
else
|
|
||||||
echo "[$slug] ⚠ pinned version $target_version not found"
|
|
||||||
fi
|
|
||||||
else
|
|
||||||
# Fetch latest release
|
|
||||||
response=$(gh api "repos/${repo}/releases/latest" 2>/dev/null || echo '{}')
|
|
||||||
if echo "$response" | jq -e '.tag_name' > /dev/null 2>&1; then
|
|
||||||
version=$(echo "$response" | jq -r '.tag_name')
|
|
||||||
date=$(echo "$response" | jq -r '.published_at // empty')
|
|
||||||
add_version "$slug" "$repo" "$version" "false" "$date"
|
|
||||||
echo "[$slug] ✓ $version"
|
|
||||||
else
|
|
||||||
# Try tags as fallback
|
|
||||||
version=$(gh api "repos/${repo}/tags" --jq '.[0].name // empty' 2>/dev/null || echo "")
|
|
||||||
if [[ -n "$version" ]]; then
|
|
||||||
add_version "$slug" "$repo" "$version" "false" ""
|
|
||||||
echo "[$slug] ✓ $version (from tags)"
|
|
||||||
else
|
|
||||||
echo "[$slug] ⚠ no version found"
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
|
|
||||||
break # Only first match per script
|
|
||||||
fi
|
|
||||||
done < <(grep 'fetch_and_deploy_gh_release' "$install_script" 2>/dev/null || true)
|
|
||||||
|
|
||||||
done
|
|
||||||
|
|
||||||
# Save versions file
|
|
||||||
echo "$versions_json" | jq --arg date "$(date -u +%Y-%m-%dT%H:%M:%SZ)" \
|
|
||||||
'{generated: $date, versions: (. | sort_by(.slug))}' > "$VERSIONS_FILE"
|
|
||||||
|
|
||||||
total=$(echo "$versions_json" | jq 'length')
|
|
||||||
echo ""
|
|
||||||
echo "========================================="
|
|
||||||
echo " Total versions extracted: $total"
|
|
||||||
echo "========================================="
|
|
||||||
|
|
||||||
- name: Check for changes
|
|
||||||
id: check-changes
|
|
||||||
run: |
|
|
||||||
# Check if file is new (untracked) or has changes
|
|
||||||
if [[ ! -f "$VERSIONS_FILE" ]]; then
|
|
||||||
echo "changed=false" >> "$GITHUB_OUTPUT"
|
|
||||||
echo "Versions file was not created"
|
|
||||||
elif ! git ls-files --error-unmatch "$VERSIONS_FILE" &>/dev/null; then
|
|
||||||
# File exists but is not tracked - it's new
|
|
||||||
echo "changed=true" >> "$GITHUB_OUTPUT"
|
|
||||||
echo "New file created: $VERSIONS_FILE"
|
|
||||||
elif git diff --quiet "$VERSIONS_FILE" 2>/dev/null; then
|
|
||||||
echo "changed=false" >> "$GITHUB_OUTPUT"
|
|
||||||
echo "No changes detected"
|
|
||||||
else
|
|
||||||
echo "changed=true" >> "$GITHUB_OUTPUT"
|
|
||||||
echo "Changes detected:"
|
|
||||||
git diff --stat "$VERSIONS_FILE" 2>/dev/null || true
|
|
||||||
fi
|
|
||||||
|
|
||||||
- name: Commit and push changes
|
|
||||||
if: steps.check-changes.outputs.changed == 'true'
|
|
||||||
run: |
|
|
||||||
git config --global user.name "github-actions[bot]"
|
|
||||||
git config --global user.email "github-actions[bot]@users.noreply.github.com"
|
|
||||||
git add "$VERSIONS_FILE"
|
|
||||||
git commit -m "chore: update github-versions.json"
|
|
||||||
git checkout -b $BRANCH_NAME || git checkout $BRANCH_NAME
|
|
||||||
git push origin $BRANCH_NAME --force
|
|
||||||
|
|
||||||
- name: Create pull request if not exists
|
|
||||||
if: steps.check-changes.outputs.changed == 'true'
|
|
||||||
env:
|
|
||||||
GH_TOKEN: ${{ steps.generate-token.outputs.token }}
|
|
||||||
run: |
|
|
||||||
PR_EXISTS=$(gh pr list --head "${BRANCH_NAME}" --json number --jq '.[].number')
|
|
||||||
if [ -z "$PR_EXISTS" ]; then
|
|
||||||
gh pr create --title "[Github Action] Update github-versions.json" \
|
|
||||||
--body "This PR is auto-generated by a Github Action to update the github-versions.json file." \
|
|
||||||
--head $BRANCH_NAME \
|
|
||||||
--base main \
|
|
||||||
--label "$AUTOMATED_PR_LABEL"
|
|
||||||
fi
|
|
||||||
|
|
||||||
- name: Approve pull request
|
|
||||||
if: steps.check-changes.outputs.changed == 'true'
|
|
||||||
env:
|
|
||||||
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
||||||
run: |
|
|
||||||
PR_NUMBER=$(gh pr list --head "${BRANCH_NAME}" --json number --jq '.[].number')
|
|
||||||
if [ -n "$PR_NUMBER" ]; then
|
|
||||||
gh pr review $PR_NUMBER --approve
|
|
||||||
fi
|
|
||||||
|
|
||||||
- name: Approve pull request and merge
|
|
||||||
if: steps.check-changes.outputs.changed == 'true'
|
|
||||||
env:
|
|
||||||
GH_TOKEN: ${{ steps.generate-token-merge.outputs.token }}
|
|
||||||
run: |
|
|
||||||
git config --global user.name "github-actions-automege[bot]"
|
|
||||||
git config --global user.email "github-actions-automege[bot]@users.noreply.github.com"
|
|
||||||
PR_NUMBER=$(gh pr list --head "${BRANCH_NAME}" --json number --jq '.[].number')
|
|
||||||
if [ -n "$PR_NUMBER" ]; then
|
|
||||||
gh pr review $PR_NUMBER --approve
|
|
||||||
gh pr merge $PR_NUMBER --squash --admin
|
|
||||||
fi
|
|
||||||
Reference in New Issue
Block a user