This commit is contained in:
Michel Roegl-Brunner 2025-03-24 12:47:48 +01:00
parent 3c29fa4201
commit 67d032e898
3 changed files with 394 additions and 0 deletions

263
.github/workflows/changelog-pr.yaml vendored Normal file
View File

@ -0,0 +1,263 @@
name: Create Changelog Pull Request
on:
push:
branches: ["main"]
workflow_dispatch:
jobs:
update-changelog-pull-request:
runs-on: runner-cluster-htl-set
env:
CONFIG_PATH: .github/changelog-pr-config.json
BRANCH_NAME: github-action-update-changelog
AUTOMATED_PR_LABEL: "automated pr"
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 code
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Get latest dates in changelog
run: |
DATES=$(grep -E '^## [0-9]{4}-[0-9]{2}-[0-9]{2}' CHANGELOG.md | head -n 2 | awk '{print $2}')
LATEST_DATE=$(echo "$DATES" | sed -n '1p')
SECOND_LATEST_DATE=$(echo "$DATES" | sed -n '2p')
TODAY=$(date -u +%Y-%m-%d)
echo "TODAY=$TODAY" >> $GITHUB_ENV
if [[ "$LATEST_DATE" == "$TODAY" ]]; then
echo "LATEST_DATE=$SECOND_LATEST_DATE" >> $GITHUB_ENV
else
echo "LATEST_DATE=$LATEST_DATE" >> $GITHUB_ENV
fi
- name: Get categorized pull requests
id: get-categorized-prs
uses: actions/github-script@v7
with:
script: |
async function main() {
const fs = require('fs').promises;
const path = require('path');
const configPath = path.resolve(process.env.CONFIG_PATH);
const fileContent = await fs.readFile(configPath, 'utf-8');
const changelogConfig = JSON.parse(fileContent);
const categorizedPRs = changelogConfig.map(obj => ({
...obj,
notes: [],
subCategories: obj.subCategories ?? (
obj.labels.includes("update script") ? [
{ title: "🐞 Bug Fixes", labels: ["bugfix"], notes: [] },
{ title: "✨ New Features", labels: ["feature"], notes: [] },
{ title: "💥 Breaking Changes", labels: ["breaking change"], notes: [] },
{ title: "🔧 Refactor", labels: ["refactor"], notes: [] },
] :
obj.labels.includes("maintenance") ? [
{ title: "🐞 Bug Fixes", labels: ["bugfix"], notes: [] },
{ title: "✨ New Features", labels: ["feature"], notes: [] },
{ title: "💥 Breaking Changes", labels: ["breaking change"], notes: [] },
{ title: "📡 API", labels: ["api"], notes: [] },
{ title: "Github", labels: ["github"], notes: [] },
{ title: "📝 Documentation", labels: ["documentation"], notes: [] },
{ title: "🔧 Refactor", labels: ["refactor"], notes: [] }
] :
obj.labels.includes("website") ? [
{ title: "🐞 Bug Fixes", labels: ["bugfix"], notes: [] },
{ title: "✨ New Features", labels: ["feature"], notes: [] },
{ title: "💥 Breaking Changes", labels: ["breaking change"], notes: [] },
{ title: "Script Information", labels: ["json"], notes: [] }
] : []
)
}));
const latestDateInChangelog = new Date(process.env.LATEST_DATE);
latestDateInChangelog.setUTCHours(23, 59, 59, 999);
const { data: pulls } = await github.rest.pulls.list({
owner: context.repo.owner,
repo: context.repo.repo,
base: "main",
state: "closed",
sort: "updated",
direction: "desc",
per_page: 100,
});
pulls.filter(pr =>
pr.merged_at &&
new Date(pr.merged_at) > latestDateInChangelog &&
!pr.labels.some(label =>
["invalid", "wontdo", process.env.AUTOMATED_PR_LABEL].includes(label.name.toLowerCase())
)
).forEach(pr => {
const prLabels = pr.labels.map(label => label.name.toLowerCase());
if (pr.user.login === "push-app-to-main") {
const scriptName = pr.title;
if (scriptName) {
try {
const { data: relatedIssues } = await github.rest.issues.listForRepo({
owner: context.repo.owner,
repo: "ProxmoxVED",
state: "all",
label: "Started Migration To ProxmoxVE",
per_page: 5
});
const matchingIssue = relatedIssues.find(issue =>
issue.title.toLowerCase().includes(scriptName.toLowerCase())
);
if (matchingIssue) {
const issueAuthor = matchingIssue.user.login;
const issueAuthorUrl = `https://github.com/${issueAuthor}`;
const prNote = `- ${pr.title} [@${issueAuthor}](${issueAuthorUrl}) ([#${pr.number}](${pr.html_url}))`;
} else {
const prNote = `- ${pr.title} ([#${pr.number}](${pr.html_url}))`;
}
} catch (error) {
console.error(`Error fetching related issues: ${error}`);
const prNote = `- ${pr.title} ([#${pr.number}](${pr.html_url}))`;
}
} else {
const prNote = `- ${pr.title} ([#${pr.number}](${pr.html_url}))`;
}else{
const prNote = `- ${pr.title} [@${pr.user.login}](https://github.com/${pr.user.login}) ([#${pr.number}](${pr.html_url}))`;
}
const updateScriptsCategory = categorizedPRs.find(category =>
category.labels.some(label => prLabels.includes(label))
);
if (updateScriptsCategory) {
const subCategory = updateScriptsCategory.subCategories.find(sub =>
sub.labels.some(label => prLabels.includes(label))
);
if (subCategory) {
subCategory.notes.push(prNote);
} else {
updateScriptsCategory.notes.push(prNote);
}
}
});
console.log(JSON.stringify(categorizedPRs, null, 2));
return categorizedPRs;
}
main().catch(error => {
console.error("Error in script:", error);
});
- name: Update CHANGELOG.md
uses: actions/github-script@v7
with:
script: |
const fs = require('fs').promises;
const path = require('path');
const today = process.env.TODAY;
const latestDateInChangelog = process.env.LATEST_DATE;
const changelogPath = path.resolve('CHANGELOG.md');
const categorizedPRs = ${{ steps.get-categorized-prs.outputs.result }};
console.log(JSON.stringify(categorizedPRs, null, 2));
let newReleaseNotes = `## ${today}\n\n`;
for (const { title, notes, subCategories } of categorizedPRs) {
const hasSubcategories = subCategories && subCategories.length > 0;
const hasMainNotes = notes.length > 0;
const hasSubNotes = hasSubcategories && subCategories.some(sub => sub.notes && sub.notes.length > 0);
if (hasMainNotes || hasSubNotes) {
newReleaseNotes += `### ${title}\n\n`;
}
if (hasMainNotes) {
newReleaseNotes += ` ${notes.join("\n")}\n\n`;
}
if (hasSubcategories) {
for (const { title: subTitle, notes: subNotes } of subCategories) {
if (subNotes && subNotes.length > 0) {
newReleaseNotes += ` - #### ${subTitle}\n\n`;
newReleaseNotes += ` ${subNotes.join("\n ")}\n\n`;
}
}
}
}
const changelogContent = await fs.readFile(changelogPath, 'utf-8');
const changelogIncludesTodaysReleaseNotes = changelogContent.includes(`\n## ${today}`);
const regex = changelogIncludesTodaysReleaseNotes
? new RegExp(`## ${today}.*(?=## ${latestDateInChangelog})`, "gs")
: new RegExp(`(?=## ${latestDateInChangelog})`, "gs");
const newChangelogContent = changelogContent.replace(regex, newReleaseNotes);
await fs.writeFile(changelogPath, newChangelogContent);
- name: Check for changes
id: verify-diff
run: |
git diff --quiet . || echo "changed=true" >> $GITHUB_ENV
- name: Commit and push changes
if: env.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 CHANGELOG.md
git commit -m "Update CHANGELOG.md"
git checkout -b $BRANCH_NAME || git checkout $BRANCH_NAME
git push origin $BRANCH_NAME --force
- name: Create pull request if not exists
if: env.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 CHANGELOG.md" \
--body "This PR is auto-generated by a Github Action to update the CHANGELOG.md file." \
--head $BRANCH_NAME \
--base main \
--label "$AUTOMATED_PR_LABEL"
fi
- name: Approve pull request
if: env.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: Re-approve pull request after update
if: env.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

42
ct/librenms.sh Normal file
View File

@ -0,0 +1,42 @@
#!/usr/bin/env bash
source <(curl -s https://raw.githubusercontent.com/community-scripts/ProxmoxVED/main/misc/build.func)
# Copyright (c) 2021-2025 community-scripts ORG
# Author: michelroegl-brunner
# License: MIT | https://github.com/community-scripts/ProxmoxVED/raw/main/LICENSE
# Source: https://librenms.org
APP="Librenms"
var_tags="monitoring"
var_cpu="2"
var_ram="2048"
var_disk="4"
var_os="debian"
var_version="12"
var_unprivileged="1"
header_info "$APP"
variables
color
catch_errors
function update_script() {
header_info
check_container_storage
check_container_resources
if [ ! -d /opt/librenms ]; then
msg_error "No ${APP} Installation Found!"
exit
fi
msg_error "Update not supported!"
exit
}
start
build_container
description
msg_ok "Completed Successfully!\n"
echo -e "${CREATING}${GN}${APP} setup has been successfully initialized!${CL}"
echo -e "${INFO}${YW} Access it using the following URL:${CL}"
echo -e "${TAB}${GATEWAY}${BGN}http://${IP}/openproject${CL}"

View File

@ -0,0 +1,89 @@
#!/usr/bin/env bash
# Copyright (c) 2021-2025 community-scripts ORG
# Author: michelroegl-brunner
# License: MIT | https://github.com/community-scripts/ProxmoxVED/raw/main/LICENSE
# Source: https://github.com/opf/openproject
source /dev/stdin <<<"$FUNCTIONS_FILE_PATH"
color
verb_ip6
catch_errors
setting_up_container
network_check
update_os
msg_info "Installing Dependencies"
$STD apt-get install -y \
sudo \
curl \
mc \
lsb-release \
ca-certificates \
wget \
acl \
fping \
graphviz \
imagemagick \
mariadb-client \
mariadb-server \
mtr-tiny \
nginx-full \
nmap \
php8.2-{cli,fpm,gd,gmp,mbstring,mysql,snmp,xml,zip} \
python3-{dotenv,pymysql,redis,setuptools,systemd,pip} \
rrdtool \
snmp \
snmpd \
unzip \
whois
msg_ok "Installed Dependencies"
msg_info "Add User"
$STD useradd librenms -d /opt/librenms -M -r -s "$(which bash)"
msg_ok "Add User"
msg_info "Setup Librenms"
tmp_file=$(mktemp)
RELEASE=$(curl -s https://api.github.com/repos/librenms/librenms/releases/latest | grep "tag_name" | awk '{print substr($2, 2, length($2)-3) }')
wget -q https://github.com/librenms/librenms/archive/refs/tags/${RELEASE}.tar.gz -O $tmp_file
tar -xzf $tmp_file -C /opt
chown -R librenms:librenms /opt/librenms
chmod 771 /opt/librenms
setfacl -d -m g::rwx /opt/librenms/rrd /opt/librenms/logs /opt/librenms/bootstrap/cache/ /opt/librenms/storage/
setfacl -R -m g::rwx /opt/librenms/rrd /opt/librenms/logs /opt/librenms/bootstrap/cache/ /opt/librenms/storage/
msg_ok "Setup Librenms"
msg_info "Setup Composer"
cd /opt
wget -q https://getcomposer.org/composer-stable.phar
mv composer-stable.phar /usr/bin/composer
chmod +x /usr/bin/composer
msg_ok "Setup Composer"
msg_info "Setup PHP"
sed -i 's/;date.timezone =/date.timezone = UTC/' /etc/php/8.2/cli/php.ini
sed -i 's/;date.timezone =/date.timezone = UTC/' /etc/php/8.2/fpm/php.ini
msg_ok "Setup PHP"
msg_info "Setup MariaDB"
cat > /etc/mysql/mariadb.conf.d/50-server.cnf << 'EOF'
[mysqld]
innodb_file_per_table=1
lower_case_table_names=0
EOF
systemctl enable -q --now mariadb
msg_ok "Setup MariaDB"
motd_ssh
customize
msg_info "Cleaning up"
$STD apt-get -y autoremove
$STD apt-get -y autoclean
msg_ok "Cleaned"