diff --git a/.github/CODE_OF_CONDUCT.md b/.gitea/CODE_OF_CONDUCT.md similarity index 100% rename from .github/CODE_OF_CONDUCT.md rename to .gitea/CODE_OF_CONDUCT.md diff --git a/.github/ISSUE_TEMPLATE/1-bug_report.yml b/.gitea/ISSUE_TEMPLATE/1-bug_report.yml similarity index 100% rename from .github/ISSUE_TEMPLATE/1-bug_report.yml rename to .gitea/ISSUE_TEMPLATE/1-bug_report.yml diff --git a/.github/ISSUE_TEMPLATE/2-feature_request.yml b/.gitea/ISSUE_TEMPLATE/2-feature_request.yml similarity index 100% rename from .github/ISSUE_TEMPLATE/2-feature_request.yml rename to .gitea/ISSUE_TEMPLATE/2-feature_request.yml diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.gitea/ISSUE_TEMPLATE/config.yml similarity index 100% rename from .github/ISSUE_TEMPLATE/config.yml rename to .gitea/ISSUE_TEMPLATE/config.yml diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.gitea/PULL_REQUEST_TEMPLATE.md similarity index 100% rename from .github/PULL_REQUEST_TEMPLATE.md rename to .gitea/PULL_REQUEST_TEMPLATE.md diff --git a/.gitea/workflows/pages.yml b/.gitea/workflows/pages.yml new file mode 100644 index 0000000..98a63b5 --- /dev/null +++ b/.gitea/workflows/pages.yml @@ -0,0 +1,40 @@ +name: Build Docs + +on: + workflow_dispatch: + +jobs: + build: + runs-on: ubuntu-latest + container: + image: artixlinux/artixlinux:base + options: --privileged + + steps: + - uses: actions/checkout@v4 + + - name: Install docs dependencies + run: | + pacman -Syu --noconfirm --needed --overwrite='*' \ + ruby \ + ruby-bundler \ + nodejs \ + npm \ + git \ + docker + + - name: Build Jekyll docs + run: | + cd docs + bundle config set --local path vendor/bundle + bundle install + bundle exec jekyll build + ls -la _site/ + + - name: Deploy to gitea-docs volume + run: | + docker run --rm \ + -v "$(pwd)/docs/_site":/source:ro \ + -v gitea-docs:/target \ + alpine:latest \ + sh -c "rm -rf /target/* && cp -a /source/. /target/ && ls -la /target/" diff --git a/.github/workflows/ai-moderator.yml b/.github/workflows/ai-moderator.yml deleted file mode 100644 index e24d330..0000000 --- a/.github/workflows/ai-moderator.yml +++ /dev/null @@ -1,202 +0,0 @@ -name: AI Moderator - -on: - issues: - types: [opened] - pull_request: - types: [opened] - discussion: - types: [created] - -permissions: - issues: write - pull-requests: write - discussions: write - contents: read - -jobs: - moderate: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v4 - - uses: actions/github-script@v9 - env: - GROQ_API_KEY: ${{ secrets.GROQ_API_KEY }} - with: - script: | - const fs = require('fs'); - - const coc = (() => { try { return fs.readFileSync('.github/CODE_OF_CONDUCT.md', 'utf8'); } catch (e) { return ''; } })(); - const contributing = (() => { try { return fs.readFileSync('CONTRIBUTING.md', 'utf8'); } catch (e) { return ''; } })(); - - const content = context.payload.issue?.body - || context.payload.pull_request?.body - || context.payload.discussion?.body - || ''; - if (!content.trim()) { - console.log('No content to analyze'); - return; - } - - const actor = context.payload.sender?.login; - if (actor === 'c-ludenberg') { - console.log('Repo owner, skipping moderation'); - return; - } - - const isDiscussion = context.payload.discussion !== undefined; - - const prompt = [ - 'You are an AI moderator for the Antergos NeXT project, an Artix-based', - 'Linux distribution (dinit init, KDE Plasma).', - 'Speak in first person. Be direct, confident, and have some snark.', - 'The project has a playful but no-nonsense tone - match it.', - '', - 'Your job is NOT to police opinions, bug reports, feature requests,', - 'pull requests, technical questions, or constructive criticism.', - 'Those are all normal and welcome. A normal PR description or issue', - 'is NEVER a violation, no matter how long, detailed, or assertive it is.', - '', - 'ONLY flag content that genuinely violates the Code of Conduct:', - 'harassment, personal attacks, hate speech, slurs, spam, scams,', - 'doxxing, malicious links, or threats.', - '', - 'When in doubt, or if the content is merely technical, opinionated,', - 'or critical of the project - violation is FALSE.', - '', - 'If the content says it is a test or contains phrases like moderator', - 'or test or reply here, play along with the joke but still enforce the rules.', - '', - 'Code of Conduct:', - coc, - '', - 'Contributing Guidelines:', - contributing, - '', - 'Analyze the content below for violations.', - 'Respond with ONLY valid JSON - no markdown, no backticks.', - '', - '{', - ' "violation": true/false,', - ' "message": "your direct first-person response",', - ' "action": "warn",', - ' "severity": 1-10', - '}', - '', - '"action" options: "warn" (post warning), "hide" (minimize comment), "lock" (lock issue/discussion)', - 'For issues use "warn" or "lock". For comments you may use "hide".', - 'Only use "lock" or "hide" for severe violations.', - '', - 'Content:', - content - ].join('\n'); - - const model = 'llama-3.1-8b-instant'; - - let decision; - try { - const response = await fetch('https://api.groq.com/openai/v1/chat/completions', { - method: 'POST', - headers: { - 'Content-Type': 'application/json', - 'Authorization': `Bearer ${process.env.GROQ_API_KEY}` - }, - body: JSON.stringify({ - model, - messages: [ - { role: 'system', content: 'You are a helpful community moderator. Respond only with valid JSON as instructed.' }, - { role: 'user', content: prompt } - ], - temperature: 0.1, - max_tokens: 250 - }) - }); - - const data = await response.json(); - const raw = data.choices?.[0]?.message?.content || '{}'; - decision = JSON.parse(raw.replace(/```json|```/g, '').trim()); - console.log(`Decision: ${JSON.stringify(decision)}`); - } catch (err) { - console.log(`API error: ${err}`); - return; - } - - if (!decision.violation) { - console.log('Content deemed acceptable'); - return; - } - - if (typeof decision.severity === 'number' && decision.severity < 4) { - console.log(`Low severity (${decision.severity}), no action taken`); - return; - } - - const number = context.payload.issue?.number - || context.payload.pull_request?.number - || context.payload.discussion?.number; - if (!number) { - console.log('No issue/PR/discussion number found'); - return; - } - - const owner = context.repo.owner; - const repo = context.repo.repo; - - try { - if (isDiscussion) { - const discId = context.payload.discussion.node_id; - if (discId) { - const msg = decision.message.replace(/"/g, '\\"'); - await github.graphql(` - mutation { - addDiscussionComment(input: {discussionId: "${discId}", body: "${msg}"}) { - comment { id } - } - } - `); - } - } else { - await github.rest.issues.addLabels({ - owner, repo, issue_number: number, labels: ['ai-moderated'] - }); - await github.rest.issues.createComment({ - owner, repo, issue_number: number, body: decision.message - }); - } - - if (decision.action === 'hide') { - const commentId = context.payload.comment?.node_id; - if (commentId) { - await github.graphql(` - mutation { - minimizeComment(input: {subjectId: "${commentId}", classifier: OFF_TOPIC}) { - minimizedComment { isMinimized } - } - } - `); - console.log('Comment minimized'); - } - } - - if (decision.action === 'lock') { - if (isDiscussion) { - const discId = context.payload.discussion.node_id; - if (discId) { - await github.graphql(` - mutation { - lockLockable(input: {lockableId: "${discId}"}) { - lockedRecord { activeLockReason } - } - } - `); - } - } else { - await github.rest.issues.lock({ owner, repo, issue_number: number, lock_reason: 'too_heated' }); - } - console.log('Locked'); - } - - console.log('Action completed: ' + decision.action); - } catch (err) { - console.log(`GitHub API error: ${err}`); - } diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml deleted file mode 100644 index 28487ac..0000000 --- a/.github/workflows/build.yml +++ /dev/null @@ -1,124 +0,0 @@ -name: Build ISO - -on: - workflow_dispatch: - -jobs: - build: - runs-on: ubuntu-latest - container: - image: artixlinux/artixlinux:base - options: --privileged - - steps: - - uses: actions/checkout@v4 - - - - name: Install dependencies - run: | - pacman -Syu --noconfirm --needed --overwrite='*' \ - artools \ - git \ - squashfs-tools \ - sudo \ - python \ - python-pip - - - name: Bootstrap Antergos package signing key - run: | - KEY_FINGERPRINT=AA644A095D2AF5F950FADB57C51BFE8D3A985236 - curl -fsSL -o /tmp/antergos-next.gpg https://raw.githubusercontent.com/Antergos-NeXT/antergos-packages/master/packages/antergos-next-keyring/antergos-next.gpg - pacman-key --init - pacman-key --add /tmp/antergos-next.gpg - gpg --homedir /etc/pacman.d/gnupg --batch --with-colons --fingerprint "$KEY_FINGERPRINT" | grep -q "fpr:::::::::$KEY_FINGERPRINT:" - pacman-key --lsign-key "$KEY_FINGERPRINT" - rm -f /tmp/antergos-next.gpg - - - - name: Set up WORKSPACE_DIR - run: | - echo "WORKSPACE_DIR=${{ github.workspace }}" >> $GITHUB_ENV - - - name: Debug workspace - run: | - echo "GITHUB_WORKSPACE=$GITHUB_WORKSPACE" - echo "github.workspace=${{ github.workspace }}" - pwd - ls -la - - - name: Override pacman.conf with antergos-pkgs repo - run: | - mkdir -p /root/.config/artools/pacman.conf.d - cp "pacman.conf.d/iso-x86_64.conf" \ - /root/.config/artools/pacman.conf.d/iso-x86_64.conf - # Also override the default in case USER_CONF_DIR differs - cp "pacman.conf.d/iso-x86_64.conf" \ - /usr/share/artools/pacman.conf.d/iso-x86_64.conf - - - name: Check available swap and block devices - run: | - swapon --show || echo "No swap" - lsblk - free -h - - - name: Setup tmpfs for build directory - run: | - mkdir -p /var/lib/artools/buildiso - mount -t tmpfs -o size=12G,exec,suid,dev tmpfs /var/lib/artools/buildiso - mount | grep buildiso - - - name: Build ISO - run: | - sudo -E ./buildiso -p antergos - - - name: Generate checksums - run: | - cd "${WORKSPACE_DIR}/iso/antergos" - ISO=$(ls antergos-*.iso | head -1) - [[ -z "$ISO" || ! -f "$ISO" ]] && { echo "No ISO found"; exit 1; } - sha256sum "$ISO" > "$ISO.sha256" - cat "$ISO.sha256" - - - name: Upload ISO artifact - uses: actions/upload-artifact@v4 - with: - name: Antergos-NeXT-ISO - path: ${{ github.workspace }}/iso/ - - - name: Upload to Internet Archive - if: false # My NVMe tried to unalive itself, 1536 unsafe shutdowns, ext4 cooked medium-rare, so I'm raw-dogging my own distro now. Set to true when I stop being my own QA team. - env: - IA_ACCESS_KEY: ${{ secrets.IA_ACCESS_KEY }} - IA_SECRET_KEY: ${{ secrets.IA_SECRET_KEY }} - run: | - pip install --break-system-packages internetarchive - - mkdir -p "$HOME/.config/internetarchive" - cat > "$HOME/.config/internetarchive/ia.ini" </dev/null | head -1) - [[ -z "$ISO" || ! -f "$ISO" ]] && { echo "No ISO found"; exit 1; } - - DATE=$(date +%Y.%m.%d) - IDENTIFIER="antergos-next-$(date +%Y%m%d)-${{ github.run_number }}" - - SIZE=$(stat -c%s "$ISO") - if [[ $SIZE -lt 524288000 ]]; then - echo "WARNING: ISO smaller than expected (${SIZE} bytes)" - file "$ISO" | grep -q "ISO 9660\|UDF" || { echo "Corrupted ISO"; exit 1; } - fi - - ia upload "$IDENTIFIER" "$ISO" \ - --metadata="title:Antergos NeXT $(date +%Y.%m.%d)" \ - --metadata="mediatype:software" \ - --metadata="collection:open_source_software" \ - --metadata="description:Antergos NeXT technical successor ISO — KDE Plasma, Dinit, Calamares installer" \ - --metadata="subject:Antergos; Linux; Artix; Dinit; KDE Plasma; Calamares" \ - --retries 5 - - echo "Uploaded to: https://archive.org/details/$IDENTIFIER" diff --git a/.github/workflows/pages.yml b/.github/workflows/pages.yml deleted file mode 100644 index 228b0b0..0000000 --- a/.github/workflows/pages.yml +++ /dev/null @@ -1,55 +0,0 @@ -name: Deploy docs to Pages - -on: - push: - branches: ["master"] - paths: ["docs/**"] - workflow_dispatch: - -permissions: - contents: read - pages: write - id-token: write - -concurrency: - group: "pages" - cancel-in-progress: true - -jobs: - build: - runs-on: ubuntu-latest - defaults: - run: - working-directory: docs - steps: - - name: Checkout - uses: actions/checkout@v7 - - name: Setup Ruby - uses: ruby/setup-ruby@v1 - with: - ruby-version: '3.3' - bundler-cache: true - cache-version: 0 - working-directory: '${{ github.workspace }}/docs' - - name: Setup Pages - id: pages - uses: actions/configure-pages@v6 - - name: Build with Jekyll - run: bundle exec jekyll build --baseurl "${{ steps.pages.outputs.base_path }}" - env: - JEKYLL_ENV: production - - name: Upload artifact - uses: actions/upload-pages-artifact@v4 - with: - path: docs/_site/ - - deploy: - environment: - name: github-pages - url: ${{ steps.deployment.outputs.page_url }} - runs-on: ubuntu-latest - needs: build - steps: - - name: Deploy to GitHub Pages - id: deployment - uses: actions/deploy-pages@v5 diff --git a/docker-compose.gitea-pages.yml b/docker-compose.gitea-pages.yml new file mode 100644 index 0000000..1723acb --- /dev/null +++ b/docker-compose.gitea-pages.yml @@ -0,0 +1,8 @@ +services: + caddy: + image: caddy:latest + ports: + - "443:443" + volumes: + - /volume1/docker/gitea-docs:/usr/share/caddy:ro + restart: always