diff --git a/.codacy/markdownlint.rb b/.codacy/markdownlint.rb new file mode 100644 index 0000000..fcd51bc --- /dev/null +++ b/.codacy/markdownlint.rb @@ -0,0 +1,2 @@ +all +rule 'MD033', :allowed_elements => ["a","img","picture","source"] \ No newline at end of file diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000..06aa2e2 --- /dev/null +++ b/.dockerignore @@ -0,0 +1,5 @@ +.devcontainer +.github +.gitignore +action.yml +Containerfile diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md index b443a7a..4cac71d 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.md +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -12,6 +12,7 @@ A clear and concise description of what the bug is. **To Reproduce** Steps to reproduce the behavior: + 1. Go to '...' 2. Click on '....' 3. Scroll down to '....' @@ -24,8 +25,9 @@ A clear and concise description of what you expected to happen. If applicable, add screenshots to help explain your problem. **Desktop (please complete the following information):** - - OS: [e.g. iOS] - - Version [e.g. 22] + +- OS: [e.g. iOS] +- Version [e.g. 22] **Additional context** Add any other context about the problem here. diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 0000000..00c7839 --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,17 @@ +# To get started with Dependabot version updates, you'll need to specify which +# package ecosystems to update and where the package manifests are located. +# Please see the documentation for all configuration options: +# https://docs.github.com/code-security/dependabot/dependabot-version-updates/configuration-options-for-the-dependabot.yml-file + +version: 2 +updates: + - package-ecosystem: "github-actions" # See documentation for possible values + directory: "/" # Location of package manifests + schedule: + interval: "daily" + - package-ecosystem: "github-actions" # See documentation for possible values + directory: "/external" # Location of package manifests + schedule: + interval: "daily" + ignore: + - dependency-name: "lorax" diff --git a/.github/workflows/bot_commands.yml b/.github/workflows/bot_commands.yml new file mode 100644 index 0000000..44522d1 --- /dev/null +++ b/.github/workflows/bot_commands.yml @@ -0,0 +1,105 @@ +name: Bot commands +on: issue_comment + +jobs: + permissions: + name: Check Permissions + runs-on: ubuntu-latest + steps: + - name: Check association + run: | + allowed=("OWNER" "COLLABORATOR") + value="\<${{ github.event.issue.author_association }}\>" + + if [[ ${allowed[@]} =~ $value ]] + then + exit 0 + else + exit 1 + fi + + load_vars: + uses: ./.github/workflows/build_vars.yml + + run-all_tests: + name: Run All Tests + if: > + github.event.issue.pull_request && + contains(github.event.comment.body, '/run tests') + permissions: + contents: read + packages: write + statuses: write + needs: + - permissions + uses: ./.github/workflows/tests.yml + with: + pr: ${{ github.event.issue.number }} + parent_job_name: Run All Tests + + run_build_container: + name: Run Build Container + if: > + github.event.issue.pull_request && + contains(github.event.comment.body, '/run build container') + permissions: + contents: read + packages: write + statuses: write + needs: + - permissions + uses: ./.github/workflows/build_container.yml + with: + pr: ${{ github.event.issue.number }} + parent_job_name: Run Build Container + + run_build_iso: + name: Run Build ISO + if: > + github.event.issue.pull_request && + contains(github.event.comment.body, '/run build iso') + permissions: + contents: read + packages: write + statuses: write + needs: + - permissions + uses: ./.github/workflows/build_iso.yml + with: + pr: ${{ github.event.issue.number }} + parent_job_name: Run Build ISO + + run_test_iso: + name: Run ISO Tests + if: > + github.event.issue.pull_request && + contains(github.event.comment.body, '/run test iso') + permissions: + contents: read + packages: write + statuses: write + needs: + - permissions + - load_vars + uses: ./.github/workflows/test_iso.yml + with: + pr: ${{ github.event.issue.number }} + parent_job_name: Run ISO Tests + + run_test_deployment: + name: Run ISO Deployment Tests + if: > + github.event.issue.pull_request && + contains(github.event.comment.body, '/run test iso') + permissions: + contents: read + packages: write + statuses: write + needs: + - permissions + - load_vars + - run_test_iso + uses: ./.github/workflows/test_deployment.yml + with: + pr: ${{ github.event.issue.number }} + parent_job_name: Run ISO Deployment Tests diff --git a/.github/workflows/build-and-test.yml b/.github/workflows/build-and-test.yml deleted file mode 100644 index 821dbac..0000000 --- a/.github/workflows/build-and-test.yml +++ /dev/null @@ -1,104 +0,0 @@ -name: Create and publish an ISO - -on: - push: - branches: - - 'main' - tags: - - 'v*' - pull_request: - -# Test Values -env: - ARCH: 'x86_64' - IMAGE_NAME: 'base' - IMAGE_REPO: 'quay.io/fedora-ostree-desktops' - VERSION: '39' - VARIANT: 'Server' - -jobs: - build-container: - runs-on: ubuntu-latest - permissions: - contents: read - packages: write - steps: - - name: Checkout repo - uses: actions/checkout@v4 - - - name: Docker meta - id: meta - uses: docker/metadata-action@v5 - with: - images: | - ghcr.io/${{ github.repository }} - tags: | - type=ref,event=branch - type=ref,event=pr - type=semver,pattern={{version}} - type=semver,pattern={{major}}.{{minor}} - - - name: Buildah Build - id: build-image - uses: redhat-actions/buildah-build@v2 - with: - containerfiles: Containerfile - tags: ${{ steps.meta.outputs.tags }} - - - name: Push image - uses: redhat-actions/push-to-registry@v2 - with: - image: ${{ steps.build-image.outputs.image }} - tags: ${{ steps.build-image.outputs.tags }} - username: ${{ github.actor }} - password: ${{ github.token }} - - - build-and-push-iso: - runs-on: ubuntu-latest - needs: - - build-container - permissions: - contents: read - packages: write - steps: - - name: Checkout repo - uses: actions/checkout@v4 - - - name: Lowercase Registry - id: registry_case - uses: ASzc/change-string-case-action@v6 - with: - string: ${{ env.IMAGE_REPO }} - - - name: Get image version - id: meta - uses: docker/metadata-action@v5 - with: - tags: | - type=ref,event=branch - type=ref,event=pr - - - name: Build ISO - uses: ./ - with: - arch: ${{ env.ARCH}} - image_name: ${{ env.IMAGE_NAME}} - image_repo: ${{ env.IMAGE_REPO}} - version: ${{ env.VERSION }} - variant: ${{ env.VARIANT }} - action_version: ${{ steps.meta.outputs.tags }} - - - name: Rename ISO - run: | - mv build/deploy.iso build/${{ env.IMAGE_NAME }}-${{ env.VERSION }}.iso - - - name: Upload ISO as artifact - uses: actions/upload-artifact@v4 - with: - name: ${{ env.IMAGE_NAME }}-${{ env.VERSION }}.iso - path: build/*.iso - if-no-files-found: error - retention-days: 0 - compression-level: 0 - overwrite: true diff --git a/.github/workflows/build_container.yml b/.github/workflows/build_container.yml new file mode 100644 index 0000000..53f412d --- /dev/null +++ b/.github/workflows/build_container.yml @@ -0,0 +1,144 @@ +name: Build Container + +on: + workflow_call: + inputs: + pr: + required: false + type: string + parent_job_name: + required: true + type: string + +jobs: + build-container: + if: > + github.event_name == 'push' || + github.event_name == 'issue_comment' || + github.event_name == 'workflow_dispatch' + name: Build Container Image + env: + JOB_NAME: Build Container Image + runs-on: ubuntu-latest + permissions: + contents: read + packages: write + statuses: write + steps: + - name: Checkout + uses: actions/checkout@v5 + with: + submodules: recursive + fetch-depth: 0 + fetch-tags: 'true' + + - name: Switch branch + if: inputs.pr + env: + GITHUB_USER: ${{ github.actor }} + GITHUB_TOKEN: ${{ github.token }} + run: | + sudo apt-get update + sudo apt-get install -y hub + hub pr checkout ${{ inputs.pr }} + echo "sha=$(git rev-parse HEAD)" >> $GITHUB_ENV + + - name: Get Current Job Log URL + if: inputs.pr && always() + uses: Tiryoh/gha-jobid-action@v1 + id: jobs + with: + github_token: ${{ secrets.GITHUB_TOKEN }} + job_name: "${{ inputs.parent_job_name }} / ${{ env.JOB_NAME }}" + per_page: 100 + + - name: Set status + if: inputs.pr && always() + uses: myrotvorets/set-commit-status-action@v2.0.1 + with: + token: ${{ secrets.GITHUB_TOKEN }} + status: pending + context: ${{ env.JOB_NAME }} + sha: ${{ env.sha }} + targetUrl: ${{ steps.jobs.outputs.html_url }} + + - name: Docker meta + if: inputs.pr == '' + id: meta + uses: docker/metadata-action@v5 + with: + images: | + ghcr.io/${{ github.repository }} + tags: | + type=ref,event=branch + type=ref,event=pr + type=raw,value=${{ github.sha }} + type=semver,pattern=v{{version}} + type=semver,pattern=v{{major}}.{{minor}} + type=semver,pattern=v{{major}}.{{minor}}.{{patch}} + + - name: Docker meta for PR + if: inputs.pr + id: meta_pr + uses: docker/metadata-action@v5 + with: + images: | + ghcr.io/${{ github.repository }} + tags: | + pr-${{ inputs.pr }} + ${{ github.sha }} + + - name: Buildah Build + id: build-image + uses: redhat-actions/buildah-build@v2 + with: + containerfiles: Containerfile + tags: ${{ steps.meta.outputs.tags || steps.meta_pr.outputs.tags }} + labels: ${{ steps.meta.outputs.labels || steps.meta_pr.outputs.labels }} + + - name: Login to GitHub Container Registry + uses: docker/login-action@v3.6.0 + with: + registry: ghcr.io + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} + + - name: Push image + uses: redhat-actions/push-to-registry@v2 + with: + image: ${{ steps.build-image.outputs.image }} + tags: ${{ steps.build-image.outputs.tags }} + username: ${{ github.actor }} + password: ${{ github.token }} + + - name: Set status + if: inputs.pr && always() + uses: myrotvorets/set-commit-status-action@v2.0.1 + with: + token: ${{ secrets.GITHUB_TOKEN }} + status: ${{ job.status }} + context: ${{ env.JOB_NAME }} + sha: ${{ env.sha }} + targetUrl: ${{ steps.jobs.outputs.html_url }} + + - name: Install Cosign + if: startsWith(github.ref, 'refs/tags/v') + uses: sigstore/cosign-installer@v3.10.0 + + - name: Sign the images + if: startsWith(github.ref, 'refs/tags/v') + env: + TAGS: ${{ steps.build-image.outputs.tags }} + COSIGN_PRIVATE_KEY: ${{ secrets.COSIGN_PRIVATE_KEY }} + COSIGN_PASSWORD: ${{ secrets.COSIGN_PASSWORD }} + run: | + images="" + digest="" + for tag in ${TAGS}; do + if [[ -z "${digest}" ]] + then + digest=$(cat $(echo ${tag} | tr '/:' '--')_digest.txt) + fi + images+="${tag}@${digest} " + done + cosign sign --key env://COSIGN_PRIVATE_KEY --yes ${images} diff --git a/.github/workflows/build_iso.yml b/.github/workflows/build_iso.yml new file mode 100644 index 0000000..6cd33ef --- /dev/null +++ b/.github/workflows/build_iso.yml @@ -0,0 +1,144 @@ +name: Build ISO + +on: + workflow_call: + inputs: + pr: + required: false + type: string + parent_job_name: + required: true + type: string + +jobs: + load_vars: + name: Load Variables + uses: ./.github/workflows/build_vars.yml + + build_iso: + name: Build ISO + env: + JOB_NAME: Build ISO + runs-on: ubuntu-latest + needs: + - load_vars + permissions: + contents: read + packages: write + statuses: write + continue-on-error: false + strategy: + fail-fast: false + matrix: ${{ fromJson(needs.load_vars.outputs.BUILD_MATRIX) }} + steps: + - name: Checkout + uses: actions/checkout@v5 + with: + submodules: recursive + + - name: Switch branch + if: inputs.pr + env: + GITHUB_USER: ${{ github.actor }} + GITHUB_TOKEN: ${{ github.token }} + run: | + sudo apt-get update + sudo apt-get install -y hub + hub pr checkout ${{ inputs.pr }} + echo "sha=$(git rev-parse HEAD)" >> $GITHUB_ENV + + - name: Get Current Job Log URL + if: inputs.pr && always() + uses: Tiryoh/gha-jobid-action@v1 + id: jobs + with: + github_token: ${{ secrets.GITHUB_TOKEN }} + job_name: "${{ inputs.parent_job_name }} / ${{ env.JOB_NAME }} (${{ matrix.version }}, ${{ matrix.flatpaks }}, ${{ matrix.image_repo }})" + per_page: 100 + + - name: Set status + if: inputs.pr && always() + uses: myrotvorets/set-commit-status-action@v2.0.1 + with: + token: ${{ secrets.GITHUB_TOKEN }} + status: pending + context: "${{ inputs.parent_job_name }} / ${{ env.JOB_NAME }} (${{ matrix.version }}, ${{ matrix.flatpaks }}, ${{ matrix.image_repo }})" + sha: ${{ env.sha }} + targetUrl: ${{ steps.jobs.outputs.html_url }} + + - name: Free Disk Space (Ubuntu) + uses: jlumbroso/free-disk-space@main + with: + # this might remove tools that are actually needed, + # if set to "true" but frees about 6 GB + tool-cache: false + + # all of these default to true, but feel free to set to + # "false" if necessary for your workflow + android: true + dotnet: true + haskell: true + large-packages: true + docker-images: true + swap-storage: true + + - name: Lowercase Registry + id: registry_case + uses: ASzc/change-string-case-action@v6 + with: + string: ${{ needs.load_vars.outputs.IMAGE_REPO }} + + - name: Get image version + id: meta + uses: docker/metadata-action@v5 + with: + tags: | + type=ref,event=branch + type=ref,event=pr + + - name: Login to Registry + run: | + echo ${{ secrets.GITHUB_TOKEN }} | docker login ghcr.io -u ${{ github.actor }} --password-stdin + + - name: Build ISO + uses: ./ + id: build + with: + arch: ${{ needs.load_vars.outputs.ARCH }} + image_name: ${{ matrix.image_name }} + image_repo: ${{ matrix.image_repo}} + image_src: ${{ matrix.image_src }} + image_tag: ${{ matrix.version }} + version: ${{ matrix.version }} + repos: ${{ matrix.repos }} + variant: ${{ needs.load_vars.outputs.VARIANT }} + flatpak_remote_refs: ${{ matrix.flatpaks == 'flatpak_refs' && needs.load_vars.outputs.FLATPAK_REMOTE_REFS || '' }} + flatpak_remote_refs_dir: ${{ matrix.flatpaks == 'flatpak_refs_dir' && needs.load_vars.outputs.FLATPAK_REMOTE_REFS_DIR || '' }} + secure_boot_key_url: ${{ needs.load_vars.outputs.SECURE_BOOT_KEY_URL }} + enrollment_password: ${{ needs.load_vars.outputs.ENROLLMENT_PASSWORD }} + iso_name: build/${{ matrix.image_name }}-${{ matrix.version }}${{ matrix.flatpaks == 'false' && '' || format('-{0}', matrix.flatpaks) }}.iso + + - name: Upload ISO as artifact + if: matrix.version != 'fake' + id: upload + uses: actions/upload-artifact@v4 + with: + name: ${{ matrix.image_name }}-${{ matrix.version }}${{ matrix.flatpaks == 'false' && '' || format('-{0}', matrix.flatpaks) }} + path: | + build/${{ matrix.image_name }}-${{ matrix.version }}${{ matrix.flatpaks == 'false' && '' || format('-{0}', matrix.flatpaks) }}.iso + build/${{ matrix.image_name }}-${{ matrix.version }}${{ matrix.flatpaks == 'false' && '' || format('-{0}', matrix.flatpaks) }}.iso-CHECKSUM + if-no-files-found: error + retention-days: 0 + compression-level: 0 + overwrite: true + + - name: Set status + if: inputs.pr && always() + uses: myrotvorets/set-commit-status-action@v2.0.1 + with: + token: ${{ secrets.GITHUB_TOKEN }} + status: ${{ job.status }} + context: "${{ inputs.parent_job_name }} / ${{ env.JOB_NAME }} (${{ matrix.version }}, ${{ matrix.flatpaks }}, ${{ matrix.image_repo }})" + sha: ${{ env.sha }} + targetUrl: ${{ steps.jobs.outputs.html_url }} + diff --git a/.github/workflows/build_vars.yml b/.github/workflows/build_vars.yml new file mode 100644 index 0000000..8a60657 --- /dev/null +++ b/.github/workflows/build_vars.yml @@ -0,0 +1,82 @@ +name: Build Vars + +on: + workflow_call: + outputs: + ARCH: + value: 'x86_64' + BUILD_MATRIX: + value: ' + { + "version": [ + "41", + "42", + "43" + ], + "flatpaks": [ + "false", + "flatpak_refs_dir", + "flatpak_refs" + ], + "image_repo": [ + "ghcr.io/ublue-os", + "quay.io/fedora", + "quay.io/fedora-ostree-desktops" + ], + "include": [ + { + "image_repo": "ghcr.io/ublue-os", + "image_name": "base-main", + }, + { + "image_repo": "quay.io/fedora", + "image_name": "fedora-bootc" + }, + { + "image_repo": "quay.io/fedora-ostree-desktops", + "image_name": "base-atomic" + } + ], + "exclude": [ + { + "image_repo": "quay.io/fedora", + "flatpaks": "flatpak_refs_dir" + }, + { + "image_repo": "quay.io/fedora", + "flatpaks": "flatpak_refs" + }, + { + "image_repo": "quay.io/fedora-ostree-desktops", + "flatpaks": "flatpak_refs_dir" + }, + { + "image_repo": "quay.io/fedora-ostree-desktops", + "flatpaks": "flatpak_refs" + }, + { + "image_repo": "ghcr.io/ublue-os", + "version": "43" + } + ] + }' + VARIANT: + value: 'Server' + FLATPAK_REMOTE_REFS_DIR: + value: flatpak_refs + FLATPAK_REMOTE_REFS: + value: "app/org.mozilla.firefox/x86_64/stable app/org.videolan.VLC/x86_64/stable" + SECURE_BOOT_KEY_URL: + value: 'https://github.com/ublue-os/akmods/raw/main/certs/public_key.der' + ENROLLMENT_PASSWORD: + value: 'container-installer' + + +jobs: + load-vars: + name: Load Variables + runs-on: ubuntu-latest + steps: + - name: Sucess + run: + echo "Vars loaded" diff --git a/.github/workflows/clean_repo.yml b/.github/workflows/clean_repo.yml new file mode 100644 index 0000000..a19ddd5 --- /dev/null +++ b/.github/workflows/clean_repo.yml @@ -0,0 +1,143 @@ +name: Clean Container Registry +on: +# schedule: +# - cron: '0 21 * * 0' + + workflow_dispatch: + +jobs: + delete_untagged: + name: Delete Untagged Packages + runs-on: ubuntu-latest + steps: + - name: Delete Untagged Packages + uses: Chizkiyahu/delete-untagged-ghcr-action@v5 + with: + token: ${{ secrets.PACKAGE_DELETER }} + repository_owner: ${{ github.repository_owner }} + repository: ${{ github.repository }} + untagged_only: true + owner_type: user + + delete_old_pr: + name: Delete Old PR Packages + runs-on: ubuntu-latest + permissions: + packages: read + steps: + - name: Delete Old PR Packages + id: all_tags + run: | + curl -L \ + -H "Accept: application/vnd.github+json" \ + -H "Authorization: Bearer ${{ github.token }}" \ + -H "X-GitHub-Api-Version: 2022-11-28" \ + "https://api.github.com/user/packages/container/build-container-installer/versions" > all_packages.json + curl -L \ + -H "Accept: application/vnd.github+json" \ + -H "Authorization: Bearer ${{ github.token }}" \ + -H "X-GitHub-Api-Version: 2022-11-28" \ + https://api.github.com/repos/${{ github.repository }}/pulls | \ + jq -r '.[] | select(.state == "open") | .number' | \ + sed 's/^/pr-/g' > open_prs + cat << EOF | python + import json + import re + + prs = open("open_prs", "r") + open_prs = prs.readlines() + open_prs = [x.strip() for x in open_prs] + + all_packages = open('all_packages.json') + data = json.load(all_packages) + + delete_versions = open("delete_versions", "w") + + for i in data: + delete = True + for tag in i['metadata']['container']['tags']: + if not re.match('pr-.*', tag): + delete = False + continue + if tag in open_prs: + delete = False + if delete: + print("delete", i['id']) + delete_versions.write(str(i['id'])) + delete_versions.write("\n") + print(i['metadata']['container']['tags']) + EOF + + for id in $(cat delete_versions) + do + curl -L \ + -X DELETE \ + -H "Accept: application/vnd.github+json" \ + -H "Authorization: Bearer ${{ secrets.PACKAGE_DELETER }}" \ + -H "X-GitHub-Api-Version: 2022-11-28" \ + https://api.github.com/user/packages/container/build-container-installer/versions/${id} + done + + + delete_old_branches: + name: Delete Old Branch Packages + runs-on: ubuntu-latest + permissions: + packages: read + steps: + - name: Delete Old Branch Packages + run: | + curl -L \ + -H "Accept: application/vnd.github+json" \ + -H "Authorization: Bearer ${{ github.token }}" \ + -H "X-GitHub-Api-Version: 2022-11-28" \ + "https://api.github.com/user/packages/container/build-container-installer/versions" > all_packages.json + curl -L \ + -H "Accept: application/vnd.github+json" \ + -H "Authorization: Bearer ${{ github.token }}" \ + -H "X-GitHub-Api-Version: 2022-11-28" \ + https://api.github.com/repos/${{ github.repository }}/branches | jq -r '.[].name' > branches + + cat << EOF | python + import json + import re + + branches_f = open("branches", "r") + branches = branches_f.readlines() + branches = [x.strip() for x in branches] + + all_packages_f = open('all_packages.json') + data = json.load(all_packages_f) + + delete_versions = open("delete_versions", "w") + + for i in data: + delete = True + for tag in i['metadata']['container']['tags']: + if re.match('v[0-9]+\\\.[0-9]+\\\.[0-9]+', tag): + delete = False + continue + if re.match('pr-.*', tag): + delete = False + continue + if tag in branches: + delete = False + continue + if tag == "latest": + delete = False + if delete: + print("delete", i['id']) + delete_versions.write(str(i['id'])) + delete_versions.write("\n") + print(i['metadata']['container']['tags']) + EOF + + for id in $(cat delete_versions) + do + curl -L \ + -X DELETE \ + -H "Accept: application/vnd.github+json" \ + -H "Authorization: Bearer ${{ secrets.PACKAGE_DELETER }}" \ + -H "X-GitHub-Api-Version: 2022-11-28" \ + https://api.github.com/user/packages/container/build-container-installer/versions/${id} + done diff --git a/.github/workflows/stale.yml b/.github/workflows/stale.yml new file mode 100644 index 0000000..ac6193f --- /dev/null +++ b/.github/workflows/stale.yml @@ -0,0 +1,32 @@ +# This workflow warns and then closes issues and PRs that have had no activity for a specified amount of time. +# +# You can adjust the behavior by modifying this file. +# For more information, see: +# https://github.com/actions/stale +name: Mark stale issues and pull requests + +on: + schedule: + - cron: '0 21 * * *' + +jobs: + stale: + + runs-on: ubuntu-latest + permissions: + issues: write + pull-requests: write + + steps: + - uses: actions/stale@v9 + with: + repo-token: ${{ secrets.GITHUB_TOKEN }} + stale-issue-message: 'Issue is stale and will be closed in 14 days if there is no further activity' + stale-pr-message: 'Pull request is stale and will be closed in 14 days if there is no further activity' + stale-issue-label: 'no-issue-activity' + stale-pr-label: 'no-pr-activity' + days-before-stale: 60 + days-before-close: 17 + remove-stale-when-updated: true + only-issue-labels: help wanted + diff --git a/.github/workflows/test_deployment.yml b/.github/workflows/test_deployment.yml new file mode 100644 index 0000000..8738ded --- /dev/null +++ b/.github/workflows/test_deployment.yml @@ -0,0 +1,112 @@ +name: Test Deployment + +on: + workflow_call: + inputs: + pr: + required: true + type: string + parent_job_name: + required: true + type: string + +jobs: + load_vars: + name: Load Variables + uses: ./.github/workflows/build_vars.yml + + test-deployment: + name: Test deployment + env: + JOB_NAME: Test deployment + runs-on: ubuntu-latest + needs: + - load_vars + permissions: + contents: read + statuses: write + continue-on-error: false + strategy: + fail-fast: false + matrix: ${{ fromJson(needs.load_vars.outputs.BUILD_MATRIX) }} + steps: + - name: Checkout + uses: actions/checkout@v5 + with: + submodules: recursive + + - name: Switch branch + if: inputs.pr + env: + GITHUB_USER: ${{ github.actor }} + GITHUB_TOKEN: ${{ github.token }} + run: | + sudo apt-get update + sudo apt-get install -y hub + hub pr checkout ${{ inputs.pr }} + echo "sha=$(git rev-parse HEAD)" >> $GITHUB_ENV + + - name: Get Current Job Log URL + if: inputs.pr && always() + uses: Tiryoh/gha-jobid-action@v1 + id: jobs + with: + github_token: ${{ secrets.GITHUB_TOKEN }} + job_name: "${{ inputs.parent_job_name }} / ${{ env.JOB_NAME }} (${{ matrix.version }}, ${{ matrix.flatpaks }}, ${{ matrix.image_repo }})" + per_page: 100 + + - name: Set status + if: inputs.pr && always() + uses: myrotvorets/set-commit-status-action@v2.0.1 + with: + token: ${{ secrets.GITHUB_TOKEN }} + status: pending + context: "${{ inputs.parent_job_name }} / ${{ env.JOB_NAME }} (${{ matrix.version }}, ${{ matrix.flatpaks }}, ${{ matrix.image_repo }})" + sha: ${{ env.sha }} + targetUrl: ${{ steps.jobs.outputs.html_url }} + + - name: Install test tools + run: | + sudo apt-get update + sudo apt-get install -y unzip make + sudo make test/vm/install-deps PACKAGE_MANAGER=apt-get + + - name: Download generated ISO + uses: actions/download-artifact@v4 + with: + name: ${{ matrix.image_name }}-${{ matrix.version }}${{ matrix.flatpaks == 'false' && '' || format('-{0}', matrix.flatpaks) }} + + - name: Run VM Tests + env: + VM_USER: core + VM_PASS: foobar + VM_IP: "127.0.0.1" + VM_PORT: "5555" + run: | + make test/vm \ + ARCH=${{ needs.load_vars.outputs.ARCH}} \ + ENROLLMENT_PASSWORD=${{ needs.load_vars.outputs.ENROLLMENT_PASSWORD }} \ + ${{ matrix.flatpaks == 'flatpak_refs' && format('FLATPAK_REMOTE_REFS="{0}"', needs.load_vars.outputs.FLATPAK_REMOTE_REFS) || '' }} \ + ${{ matrix.flatpaks == 'flatpak_refs_dir' && format('FLATPAK_REMOTE_REFS_DIR="{0}"', needs.load_vars.outputs.FLATPAK_REMOTE_REFS_DIR) || '' }} \ + IMAGE_NAME=${{ matrix.image_name }} \ + IMAGE_REPO=${{ matrix.image_repo }} \ + IMAGE_TAG=${{ matrix.version }} \ + ISO_NAME=${{ matrix.image_name }}-${{ matrix.version }}${{ matrix.flatpaks == 'false' && '' || format('-{0}', matrix.flatpaks) }}.iso \ + ${{ matrix.repos != '' && format('REPOS="{0}"', matrix.repos) || '' }} \ + SECURE_BOOT_KEY_URL=${{ needs.load_vars.outputs.SECURE_BOOT_KEY_URL }} \ + VARIANT=${{ needs.load_vars.outputs.VARIANT }} \ + VERSION=${{ matrix.version }} \ + VM_IP=${VM_IP} \ + VM_PASS=${VM_PASS} \ + VM_PORT=${VM_PORT} \ + VM_USER=${VM_USER} + + - name: Set status + if: inputs.pr && always() + uses: myrotvorets/set-commit-status-action@v2.0.1 + with: + token: ${{ secrets.GITHUB_TOKEN }} + status: ${{ job.status }} + context: "${{ inputs.parent_job_name }} / ${{ env.JOB_NAME }} (${{ matrix.version }}, ${{ matrix.flatpaks }}, ${{ matrix.image_repo }})" + sha: ${{ env.sha }} + targetUrl: ${{ steps.jobs.outputs.html_url }} diff --git a/.github/workflows/test_iso.yml b/.github/workflows/test_iso.yml new file mode 100644 index 0000000..049fc11 --- /dev/null +++ b/.github/workflows/test_iso.yml @@ -0,0 +1,103 @@ +name: Test ISO + +on: + workflow_call: + inputs: + pr: + required: false + type: string + parent_job_name: + required: true + type: string + +jobs: + load_vars: + name: Load Variables + uses: ./.github/workflows/build_vars.yml + + test-iso: + name: Test ISO + env: + JOB_NAME: Test ISO + runs-on: ubuntu-latest + needs: + - load_vars + permissions: + contents: read + statuses: write + continue-on-error: false + strategy: + fail-fast: false + matrix: ${{ fromJson(needs.load_vars.outputs.BUILD_MATRIX) }} + steps: + - name: Checkout + uses: actions/checkout@v5 + with: + submodules: recursive + + - name: Switch branch + if: inputs.pr + env: + GITHUB_USER: ${{ github.actor }} + GITHUB_TOKEN: ${{ github.token }} + run: | + sudo apt-get update + sudo apt-get install -y hub + hub pr checkout ${{ inputs.pr }} + echo "sha=$(git rev-parse HEAD)" >> $GITHUB_ENV + + - name: Get Current Job Log URL + if: inputs.pr && always() + uses: Tiryoh/gha-jobid-action@v1 + id: jobs + with: + github_token: ${{ secrets.GITHUB_TOKEN }} + job_name: "${{ inputs.parent_job_name }} / ${{ env.JOB_NAME }} (${{ matrix.version }}, ${{ matrix.flatpaks }}, ${{ matrix.image_repo }})" + per_page: 100 + + - name: Set status + if: inputs.pr && always() + uses: myrotvorets/set-commit-status-action@v2.0.1 + with: + token: ${{ secrets.GITHUB_TOKEN }} + status: pending + context: "${{ inputs.parent_job_name }} / ${{ env.JOB_NAME }} (${{ matrix.version }}, ${{ matrix.flatpaks }}, ${{ matrix.image_repo }})" + sha: ${{ env.sha }} + targetUrl: ${{ steps.jobs.outputs.html_url }} + + - name: Install test tools + run: | + sudo apt-get update + sudo apt-get install -y make + sudo make test/iso/install-deps PACKAGE_MANAGER=apt-get + + - name: Download generated ISO + uses: actions/download-artifact@v4 + with: + name: ${{ matrix.image_name }}-${{ matrix.version }}${{ matrix.flatpaks == 'false' && '' || format('-{0}', matrix.flatpaks) }} + + - name: Run ISO checks + run: | + make test/iso \ + ARCH=${{ needs.load_vars.outputs.ARCH}} \ + ENROLLMENT_PASSWORD=${{ needs.load_vars.outputs.ENROLLMENT_PASSWORD }} \ + ${{ matrix.flatpaks == 'flatpak_refs' && format('FLATPAK_REMOTE_REFS="{0}"', needs.load_vars.outputs.FLATPAK_REMOTE_REFS) || '' }} \ + ${{ matrix.flatpaks == 'flatpak_refs_dir' && format('FLATPAK_REMOTE_REFS_DIR="{0}"', needs.load_vars.outputs.FLATPAK_REMOTE_REFS_DIR) || '' }} \ + IMAGE_NAME=${{ matrix.image_name }} \ + IMAGE_REPO=${{ matrix.image_repo }} \ + IMAGE_TAG=${{ matrix.version }} \ + ISO_NAME=${{ matrix.image_name }}-${{ matrix.version }}${{ matrix.flatpaks == 'false' && '' || format('-{0}', matrix.flatpaks) }}.iso \ + ${{ matrix.repos != '' && format('REPOS="{0}"', matrix.repos) || '' }} \ + SECURE_BOOT_KEY_URL=${{ needs.load_vars.outputs.SECURE_BOOT_KEY_URL }} \ + VARIANT=${{ needs.load_vars.outputs.VARIANT }} \ + VERSION=${{ matrix.version }} + + - name: Set status + if: inputs.pr && always() + uses: myrotvorets/set-commit-status-action@v2.0.1 + with: + token: ${{ secrets.GITHUB_TOKEN }} + status: ${{ job.status }} + context: "${{ inputs.parent_job_name }} / ${{ env.JOB_NAME }} (${{ matrix.version }}, ${{ matrix.flatpaks }}, ${{ matrix.image_repo }})" + sha: ${{ env.sha }} + targetUrl: ${{ steps.jobs.outputs.html_url }} diff --git a/.github/workflows/test_repo.yml b/.github/workflows/test_repo.yml new file mode 100644 index 0000000..59071c0 --- /dev/null +++ b/.github/workflows/test_repo.yml @@ -0,0 +1,30 @@ +name: Test Repo + +on: + push: + branches: + - 'main' + tags: + - 'v*' + pull_request: + +concurrency: + group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }} + cancel-in-progress: true + +jobs: + variables: + name: Check variables are listed + runs-on: ubuntu-latest + permissions: + contents: read + steps: + - name: Checkout repo + uses: actions/checkout@v5 + + - name: Run test + run: | + sudo apt-get update + sudo apt-get install -y make + sudo make test/repo/install-deps + make test/repo \ No newline at end of file diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml new file mode 100644 index 0000000..52e8305 --- /dev/null +++ b/.github/workflows/tests.yml @@ -0,0 +1,60 @@ +name: All Tests + +on: + push: + branches: + - 'main' + tags: + - 'v*' + + workflow_dispatch: + + workflow_call: + inputs: + pr: + required: true + type: string + parent_job_name: + required: true + type: string + + +concurrency: + group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }} + cancel-in-progress: true + +jobs: + build_container: + name: Build Container + uses: ./.github/workflows/build_container.yml + secrets: inherit + with: + pr: ${{ inputs.pr }} + parent_job_name: ${{ inputs.parent_job_name && format('{0} / ', inputs.parent_job_name) }}Build Container + + build_isos: + name: Build ISOs + needs: + - build_container + uses: ./.github/workflows/build_iso.yml + with: + pr: ${{ inputs.pr }} + parent_job_name: ${{ inputs.parent_job_name && format('{0} / ', inputs.parent_job_name) }}Build ISOs + + test_isos: + name: Test ISOs + needs: + - build_isos + uses: ./.github/workflows/test_iso.yml + with: + pr: ${{ inputs.pr }} + parent_job_name: ${{ inputs.parent_job_name && format('{0} / ', inputs.parent_job_name) }}Test ISOs + + test_deployments: + name: Test Deployments + needs: + - build_isos + uses: ./.github/workflows/test_deployment.yml + with: + pr: ${{ inputs.pr }} + parent_job_name: ${{ inputs.parent_job_name && format('{0} / ', inputs.parent_job_name) }}Test Deployments diff --git a/.github/workflows/update_wiki.yml b/.github/workflows/update_wiki.yml new file mode 100644 index 0000000..fce015c --- /dev/null +++ b/.github/workflows/update_wiki.yml @@ -0,0 +1,50 @@ +name: Update Wiki +on: + push: + branches: + - main + paths: + - 'docs/**' + - '.github/workflows/update_wiki.yml' + +jobs: + update-wiki: + name: Update Wiki + runs-on: ubuntu-latest + permissions: + contents: write + steps: + - name: Install packages + run: | + sudo apt install -y make rsync + # Checkout Main Repo + - uses: actions/checkout@v5 + + # Checkout Wiki Repo + - uses: actions/checkout@v5 + with: + repository: ${{github.repository}}.wiki + persist-credentials: true + path: wiki + ref: master + + # Generate final files + - name: Generate Files + run: | + cd ${GITHUB_WORKSPACE}/docs + make + + # Copy Docs + - name: Copy files + run: | + rsync -av --exclude='.git/*' ${GITHUB_WORKSPACE}/docs/ ${GITHUB_WORKSPACE}/wiki/ + + # Push Changes + - name: Push changes + run: | + cd ${GITHUB_WORKSPACE}/wiki/ + git config --local user.email "action@github.com" + git config --local user.name "GitHub Action" + git add . + git commit -m "Add changes" + git push diff --git a/.gitignore b/.gitignore index 8f65d56..df805b5 100644 --- a/.gitignore +++ b/.gitignore @@ -1,14 +1,16 @@ /debugdata /build +/flatpaks/script.sh +/flatpaks/repo +/flatpaks/list.txt +/lorax_templates/post_* /pkglists -/repos +/repos/*.repo /results -/lorax_templates/*.tmpl /xorriso/input.txt -/xorriso/*.sh /original-pkgsizes.txt /final-pkgsizes.txt /lorax.conf /output /*.log - +/cache \ No newline at end of file diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000..3ac6662 --- /dev/null +++ b/.gitmodules @@ -0,0 +1,7 @@ +[submodule "external/fedora-lorax-templates"] + path = external/fedora-lorax-templates + url = https://pagure.io/fedora-lorax-templates.git + branch = f40 +[submodule "external/lorax"] + path = external/lorax + url = https://github.com/weldr/lorax.git diff --git a/.mdlrc b/.mdlrc new file mode 100644 index 0000000..17717c6 --- /dev/null +++ b/.mdlrc @@ -0,0 +1 @@ +style "#{File.dirname(__FILE__)}/.codacy/markdownlint.rb" \ No newline at end of file diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..2625bca --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,5 @@ +{ + "files.associations": { + "Makefile.inputs": "makefile" + } +} \ No newline at end of file diff --git a/Containerfile b/Containerfile index 196a151..18b844b 100644 --- a/Containerfile +++ b/Containerfile @@ -1,6 +1,6 @@ -FROM fedora:39 +FROM fedora:42 -ARG VERSION=39 +ARG VERSION=42 ENV ARCH="x86_64" ENV IMAGE_NAME="base" @@ -11,16 +11,15 @@ ENV VERSION="${VERSION}" ENV WEB_UI="false" RUN mkdir /build-container-installer -COPY /lorax_templates /build-container-installer/lorax_templates -COPY /xorriso /build-container-installer/xorriso -COPY /Makefile /build-container-installer -COPY /entrypoint.sh / + +COPY / /build-container-installer/ WORKDIR /build-container-installer - -RUN dnf install -y make && make install-deps - VOLUME /build-container-installer/build +VOLUME /build-container-installer/repos +VOLUME /cache -ENTRYPOINT ["/bin/bash", "/entrypoint.sh"] +RUN dnf install -y make && make install-deps && dnf clean all + +ENTRYPOINT ["/bin/bash", "/build-container-installer/entrypoint.sh"] diff --git a/Makefile b/Makefile index 0ef451f..9f85c58 100644 --- a/Makefile +++ b/Makefile @@ -1,106 +1,148 @@ -# Configuration vars -## Formatting = UPPERCASE -ARCH = x86_64 -VERSION = 39 -IMAGE_REPO = quay.io/fedora-ostree-desktops -IMAGE_NAME = base -IMAGE_TAG = $(VERSION) -VARIANT = Server -WEB_UI = false -REPOS = /etc/yum.repos.d/fedora.repo /etc/yum.repos.d/fedora-updates.repo -ADDITIONAL_TEMPLATES = "" -ROOTFS_SIZE = 4 +include Makefile.inputs -# Generated vars +################### +# Hidden vars + +export SHELL := /bin/sh +# Cache +export DNF_CACHE := +export PACKAGE_MANAGER := dnf + +# Functions +## Formatting = lowercase +# Get a list of templates for the feature +# $1 = feature +define get_templates + $(wildcard lorax_templates/$(1)_*.tmpl) + $(foreach file,$(notdir $(wildcard lorax_templates/scripts/post/$(1)_*)),lorax_templates/post_$(file).tmpl) +endef + +define install_pkg + $(PACKAGE_MANAGER) install -y $(if $(findstring dnf,$(PACKAGE_MANAGER)),--disablerepo='*-testing') +endef +export install_pkg + +# Generated/internal vars ## Formatting = _UPPERCASE -_BASE_DIR = $(shell pwd) -_IMAGE_REPO_ESCAPED = $(subst /,\/,$(IMAGE_REPO)) -_IMAGE_REPO_DOUBLE_ESCAPED = $(subst \,\\\,$(_IMAGE_REPO_ESCAPED)) -_VOLID = $(firstword $(subst -, ,$(IMAGE_NAME)))-$(ARCH)-$(IMAGE_TAG) -_REPO_FILES = $(subst /etc/yum.repos.d,repos,$(REPOS)) -_LORAX_TEMPLATES = $(subst .in,,$(shell ls lorax_templates/*.tmpl.in)) +_IMAGE_REPO_ESCAPED := $(subst /,\/,$(IMAGE_REPO)) +_IMAGE_REPO_DOUBLE_ESCAPED := $(subst \,\\\,$(_IMAGE_REPO_ESCAPED)) +_LORAX_ARGS := +export _LORAX_TEMPLATES := $(call get_templates,install) lorax_templates/install_include_post.tmpl +_REPO_FILES := $(subst /etc/yum.repos.d,repos,$(REPOS)) +_TEMP_DIR := $(shell mktemp -d) +_TEMPLATE_VARS := ARCH IMAGE_NAME IMAGE_REPO _IMAGE_REPO_DOUBLE_ESCAPED _IMAGE_REPO_ESCAPED IMAGE_SIGNED IMAGE_TAG REPOS _RHEL VARIANT VERSION WEB_UI +_VOLID := $(firstword $(subst -, ,$(IMAGE_NAME)))-$(ARCH)-$(IMAGE_TAG) -ifeq ($(VARIANT),Server) -_LORAX_ARGS = --macboot --noupgrade +ifeq ($(findstring redhat.repo,$(REPOS)),redhat.repo) +export _RHEL := true +export _LORAX_TEMPLATES += $(call get_templates,rhel) else -_LORAX_ARGS = --nomacboot +undefine _RHEL +endif + +ifeq ($(_RHEL),true) +_LORAX_ARGS += --nomacboot --noupgrade +else ifeq ($(VARIANT),Server) +_LORAX_ARGS += --macboot --noupgrade --squashfs-only +else +_LORAX_ARGS += --nomacboot --squashfs-only endif ifeq ($(WEB_UI),true) _LORAX_ARGS += -i anaconda-webui endif -# Step 7: Buid end ISO +ifneq ($(DNF_CACHE),) + _LORAX_ARGS += --cachedir $(DNF_CACHE) +export _LORAX_TEMPLATES += $(call get_templates,cache) + _TEMPLATE_VARS += DNF_CACHE +endif + +ifneq ($(FLATPAK_DIR),) + _FLATPAK_REPO_GPG := $(shell curl -L $(FLATPAK_REMOTE_URL) | grep -i '^GPGKey=' | cut -d= -f2) +export _FLATPAK_REPO_URL := $(shell curl -L $(FLATPAK_REMOTE_URL) | grep -i '^URL=' | cut -d= -f2) + _LORAX_ARGS += -i flatpak-libs +export _LORAX_TEMPLATES += $(call get_templates,flatpak) + _TEMPLATE_VARS += FLATPAK_DIR FLATPAK_REMOTE_NAME FLATPAK_REMOTE_REFS FLATPAK_REMOTE_URL _FLATPAK_REPO_GPG _FLATPAK_REPO_URL +else +ifneq ($(FLATPAK_REMOTE_REFS_DIR),) + COLLECTED_REFS := $(foreach file,$(filter-out README.md Makefile,$(wildcard $(FLATPAK_REMOTE_REFS_DIR)/*)),$(shell cat $(file))) +export FLATPAK_REMOTE_REFS += $(sort $(COLLECTED_REFS)) +endif + +ifneq ($(FLATPAK_REMOTE_REFS),) + _FLATPAK_REPO_GPG := $(shell curl -L $(FLATPAK_REMOTE_URL) | grep -i '^GPGKey=' | cut -d= -f2) +export _FLATPAK_REPO_URL := $(shell curl -L $(FLATPAK_REMOTE_URL) | grep -i '^URL=' | cut -d= -f2) + _LORAX_ARGS += -i flatpak-libs +export _LORAX_TEMPLATES += $(call get_templates,flatpak) \ + external/fedora-lorax-templates/ostree-based-installer/lorax-embed-flatpaks.tmpl + _TEMPLATE_VARS += FLATPAK_DIR FLATPAK_REMOTE_NAME FLATPAK_REMOTE_REFS FLATPAK_REMOTE_URL _FLATPAK_REPO_GPG _FLATPAK_REPO_URL +endif +endif + + +ifneq ($(SECURE_BOOT_KEY_URL),) +export _LORAX_TEMPLATES += $(call get_templates,secureboot) + _TEMPLATE_VARS += ENROLLMENT_PASSWORD +endif + +_SUBDIRS := container external flatpak_refs lorax_templates repos xorriso test + +# Create checksum ## Default action -build/deploy.iso: boot.iso container/$(IMAGE_NAME)-$(IMAGE_TAG) xorriso/input.txt - mkdir $(_BASE_DIR)/build || true - xorriso -dialog on < $(_BASE_DIR)/xorriso/input.txt - implantisomd5 build/deploy.iso +$(ISO_NAME)-CHECKSUM: $(ISO_NAME) + cd $(dir $(ISO_NAME)) && sha256sum $(notdir $(ISO_NAME)) > $(notdir $(ISO_NAME))-CHECKSUM -# Step 1: Generate Lorax Templates -lorax_templates/%.tmpl: lorax_templates/%.tmpl.in - $(eval _VARS = IMAGE_NAME IMAGE_TAG _IMAGE_REPO_DOUBLE_ESCAPED) - $(foreach var,$(_VARS),$(var)=$($(var))) envsubst '$(foreach var,$(_VARS),$$$(var))' < $(_BASE_DIR)/lorax_templates/$*.tmpl.in > $(_BASE_DIR)/lorax_templates/$*.tmpl +# Build end ISO +$(ISO_NAME): results/images/boot.iso container/$(IMAGE_NAME)-$(IMAGE_TAG) xorriso/input.txt + $(if $(wildcard $(dir $(ISO_NAME))),,mkdir -p $(dir $(ISO_NAME)); chmod ugo=rwX $(dir $(ISO_NAME))) + xorriso -dialog on < xorriso/input.txt + implantisomd5 $(ISO_NAME) + chmod ugo=r $(ISO_NAME) + $(if $(GITHUB_OUTPUT), echo "iso_name=$(ISO_NAME)" >> $(GITUHB_OUTPUT)) +# Download the secure boot key +sb_pubkey.der: + curl --fail -L -o sb_pubkey.der $(SECURE_BOOT_KEY_URL) -# Step 2: Replace vars in repo files -repos/%.repo: /etc/yum.repos.d/%.repo - mkdir repos || true - cp /etc/yum.repos.d/$*.repo $(_BASE_DIR)/repos/$*.repo - sed -i "s/\$$releasever/${VERSION}/g" $(_BASE_DIR)/repos/$*.repo - sed -i "s/\$$basearch/${ARCH}/g" $(_BASE_DIR)/repos/$*.repo +# Build boot.iso using Lorax +results/images/boot.iso: external/lorax/branch-$(VERSION) $(filter lorax_templates/%,$(_LORAX_TEMPLATES)) $(filter repos/%,$(_REPO_FILES)) $(if $(SECURE_BOOT_KEY_URL),sb_pubkey.der) + $(if $(wildcard results), rm -Rf results) + $(if $(wildcard /etc/rpm/macros.image-language-conf),mv /etc/rpm/macros.image-language-conf $(_TEMP_DIR)/macros.image-language-conf) -# Don't do anything for custom repos -%.repo: - -# Step 3: Build boot.iso using Lorax -boot.iso: $(_LORAX_TEMPLATES) $(_REPO_FILES) - rm -Rf $(_BASE_DIR)/results || true - rm /etc/rpm/macros.image-language-conf || true lorax -p $(IMAGE_NAME) -v $(VERSION) -r $(VERSION) -t $(VARIANT) \ - --isfinal --squashfs-only --buildarch=$(ARCH) --volid=$(_VOLID) \ - $(_LORAX_ARGS) \ - $(foreach file,$(_REPO_FILES),--repo $(_BASE_DIR)/$(file)) \ - $(foreach file,$(_LORAX_TEMPLATES),--add-template $(_BASE_DIR)/$(file)) \ - $(foreach file,$(ADDITIONAL_TEMPLATES),--add-template $(file)) \ - --rootfs-size $(ROOTFS_SIZE) \ - $(_BASE_DIR)/results/ - mv $(_BASE_DIR)/results/images/boot.iso $(_BASE_DIR)/ - -# Step 4: Download container image -container/$(IMAGE_NAME)-$(IMAGE_TAG): - mkdir container || true - podman pull $(IMAGE_REPO)/$(IMAGE_NAME):$(IMAGE_TAG) - podman save --format oci-dir -o $(_BASE_DIR)/container/$(IMAGE_NAME)-$(IMAGE_TAG) $(IMAGE_REPO)/$(IMAGE_NAME):$(IMAGE_TAG) - podman rmi $(IMAGE_REPO)/$(IMAGE_NAME):$(IMAGE_TAG) - -# Step 5: Generate xorriso script -xorriso/%.sh: xorriso/%.sh.in - $(eval _VARS = IMAGE_NAME IMAGE_TAG ARCH VERSION) - $(foreach var,$(_VARS),$(var)=$($(var))) envsubst '$(foreach var,$(_VARS),$$$(var))' < $(_BASE_DIR)/xorriso/$*.sh.in > $(_BASE_DIR)/xorriso/$*.sh - -# Step 6: Generate xorriso input -xorriso/input.txt: xorriso/gen_input.sh - bash $(_BASE_DIR)/xorriso/gen_input.sh | tee $(_BASE_DIR)/xorriso/input.txt + --isfinal --buildarch=$(ARCH) --volid=$(_VOLID) --sharedir $(PWD)/external/lorax/share/templates.d/99-generic \ + $(_LORAX_ARGS) \ + $(foreach file,$(_REPO_FILES),--repo $(patsubst repos/%,$(PWD)/repos/%,$(file))) \ + $(foreach file,$(_LORAX_TEMPLATES),--add-template $(PWD)/$(file)) \ + $(foreach file,$(ADDITIONAL_TEMPLATES),--add-template $(file)) \ + $(foreach file,$(_FLATPAK_TEMPLATES),--add-template $(file)) \ + $(foreach file,$(_EXTERNAL_TEMPLATES),--add-template $(PWD)/external/$(file)) \ + --rootfs-size $(ROOTFS_SIZE) \ + $(foreach var,$(_TEMPLATE_VARS),--add-template-var "$(shell echo $(var) | tr '[:upper:]' '[:lower:]')=$($(var))") \ + results/ + $(if $(wildcard $(_TEMP_DIR)/macros.image-language-conf),mv -f $(_TEMP_DIR)/macros.image-language-conf /etc/rpm/macros.image-language-conf) +FILES_TO_CLEAN := $(wildcard build debugdata pkglists results original-pkgsizes.txt final-pkgsizes.txt lorax.conf *.iso *log) +.PHONY: clean clean: - rm -Rf $(_BASE_DIR)/build || true - rm -Rf $(_BASE_DIR)/container || true - rm -Rf $(_BASE_DIR)/debugdata || true - rm -Rf $(_BASE_DIR)/pkglists || true - rm -Rf $(_BASE_DIR)/repos || true - rm -Rf $(_BASE_DIR)/results || true - rm -f $(_BASE_DIR)/lorax_templates/*.tmpl || true - rm -f $(_BASE_DIR)/xorriso/input.txt || true - rm -f $(_BASE_DIR)/xorriso/*.sh || true - rm -f $(_BASE_DIR)/{original,final}-pkgsizes.txt || true - rm -f $(_BASE_DIR)/lorax.conf || true - rm -f $(_BASE_DIR)/*.iso || true - rm -f $(_BASE_DIR)/*.log || true + rm -Rf $(FILES_TO_CLEAN) + $(foreach DIR,$(_SUBDIRS),$(MAKE) -w -C $(DIR) clean;) +.PHONY: install-deps install-deps: - dnf install -y lorax xorriso podman - -.PHONY: clean install-deps + $(install_pkg) lorax xorriso coreutils gettext syslinux-nonlinux + $(foreach DIR,$(filter-out test,$(_SUBDIRS)),$(MAKE) -w -C $(DIR) install-deps;) + +.PHONY: $(_SUBDIRS) $(wildcard test/*) $(wildcard test/*/*) +test $(addsuffix /*,$(_SUBDIRS)): + $(eval DIR=$(firstword $(subst /, ,$@))) + $(if $(filter-out $(DIR),$@), $(eval TARGET=$(subst $(DIR)/,,$@)),$(eval TARGET=)) + $(MAKE) -w -C $(DIR) $(TARGET) + +.DEFAULT: + $(eval DIR=$(firstword $(subst /, ,$@))) + $(if $(filter-out $(DIR),$@), $(eval TARGET=$(subst $(DIR)/,,$@)),$(eval TARGET=)) + $(MAKE) -w -C $(DIR) $(TARGET) diff --git a/Makefile.inputs b/Makefile.inputs new file mode 100644 index 0000000..a77e4f2 --- /dev/null +++ b/Makefile.inputs @@ -0,0 +1,26 @@ +# Configuration vars +## Formatting = UPPERCASE +# General +export ADDITIONAL_TEMPLATES := +export ARCH := x86_64 +export EXTRA_BOOT_PARAMS := +export IMAGE_NAME := base +export IMAGE_REPO := quay.io/fedora-ostree-desktops +export IMAGE_SRC := +export IMAGE_TAG = $(VERSION) +export IMAGE_SIGNED := true + REPOS := $(subst :,\:,$(wildcard /etc/yum.repos.d/*.repo)) +export ROOTFS_SIZE := 4 +export VARIANT := Server +export VERSION := 39 +export WEB_UI := false +# Flatpak +export FLATPAK_REMOTE_NAME := flathub +export FLATPAK_REMOTE_URL := https://flathub.org/repo/flathub.flatpakrepo +export FLATPAK_REMOTE_REFS := +export FLATPAK_REMOTE_REFS_DIR := +export FLATPAK_DIR := +# Secure boot +export ENROLLMENT_PASSWORD := +export SECURE_BOOT_KEY_URL := +export ISO_NAME := build/deploy.iso diff --git a/README.md b/README.md index 3c80ebb..fdea723 100644 --- a/README.md +++ b/README.md @@ -1,109 +1,50 @@ -![Build status](https://github.com/jasonn3/build-container-installer/actions/workflows/build-and-test.yml/badge.svg??event=push) +[![Build status](https://github.com/jasonn3/build-container-installer/actions/workflows/tests.yml/badge.svg?event=push)](https://github.com/jasonn3/build-container-installer/actions/workflows/tests.yml) +[![Codacy Badge](https://app.codacy.com/project/badge/Grade/35a48e77e64f469ba19d60a1a1e0be71)](https://app.codacy.com/gh/JasonN3/build-container-installer/dashboard?utm_source=gh&utm_medium=referral&utm_content=&utm_campaign=Badge_grade) -# Bulid Container Installer Action -This action is used to generate an ISO for installing OSTrees stored in a container. This utilizes the anaconda command `ostreecontainer` +# Build Container Installer Action + +This action is used to generate an ISO for installing an OSTree stored in a container image. This utilizes the anaconda command `ostreecontainer`, which also supports bootc. ## Usage + This action is designed to be called from a GitHub workflow using the following format + ```yaml - name: Build ISO - uses: jasonn3/build-container-installer/v1.0.0 + uses: jasonn3/build-container-installer@main + id: build with: arch: ${{ env.ARCH}} image_name: ${{ env.IMAGE_NAME}} image_repo: ${{ env.IMAGE_REPO}} + image_tag: ${{ env.IMAGE_TAG }} version: ${{ env.VERSION }} variant: ${{ env.VARIANT }} - action_version: v1.0.0 + iso_name: ${{ env.IMAGE_NAME }}-${{ env.IMAGE_TAG }}-${{ env.VERSION }}.iso + +# This example is for uploading your ISO as a Github artifact. You can do something similar using any cloud storage, so long as you copy the output +- name: Upload ISO as artifact + id: upload + uses: actions/upload-artifact@v4 + with: + name: ${{ steps.build.outputs.iso_name }} + path: | + ${{ steps.build.outputs.iso_path }}/${{ steps.build.outputs.iso_name }} + ${{ steps.build.outputs.iso_path }}/${{ steps.build.outputs.iso_name }}-CHECKSUM + if-no-files-found: error + retention-days: 0 + compression-level: 0 ``` -See [Customizing](#customizing) for information about customizing the ISO that gets created using `with` +**See the [Wiki](https://github.com/JasonN3/build-container-installer/wiki) for development and usage information.** -## Customizing -The following variables can be used to customize the created ISO. -| Variable | Description | Default Value | -| ----------------- | -------------------------------------------------------- | ------------------------------ | -| ARCH | Architecture for image to build | x86_64 | -| VERSION | Fedora version of installer to build | 39 | -| IMAGE_REPO | Repository containing the source container image | quay.io/fedora-ostree-desktops | -| IMAGE_NAME | Name of the source container image | base | -| IMAGE_TAG | Tag of the source container image | *VERSION* | -| EXTRA_BOOT_PARAMS | Extra params used by grub to boot the anaconda installer | \[empty\] | -| VARIANT | Source container variant\* | Server | -| WEB_UI | Enable Anaconda WebUI (experimental) | false | - -Available options for VARIANT can be found by running `dnf provides system-release`. -Variant will be the third item in the package name. Example: `fedora-release-kinoite-39-34.noarch` will be kinoite - -## Development -### Makefile -The Makefile contains all of the commands that are run in the action. There are separate targets for each file generated, however `make` can be used to generate the final image and `make clean` can be used to clean up the workspace. The resulting ISO will be stored in the `build` directory. - -`make install-deps` can be used to install the necessary packages - -See [Customizing](#customizing) for information about customizing the ISO that gets created. - -### Container -A container with `make install-deps` already run is provided at `ghcr.io/jasonn3/build-container-installer:latest` - -To use the container file, run `docker run --privileged --volume .:/build-container-installer/build ghcr.io/jasonn3/build-container-installer:latest`. - -This will create an ISO with the baked in defaults of the container image. - -See [Customizing](#customizing) for information about customizing the ISO that gets created. The variable can either be defined as environment variables. -Examples: - -Building an ISO to install Fedora 38 -```bash -docker run --rm --privileged --volume .:/build-container-installer/build -e VERSION=38 -e IMAGE_NAME=base -e IMAGE_TAG=38 -e VARIANT=Server ghcr.io/jasonn3/build-container-installer:latest -``` - -Building an ISO to install Fedora 39 -```bash -docker run --rm --privileged --volume .:/build-container-installer/build -e VERSION=39 -e IMAGE_NAME=base -e IMAGE_TAG=39 -e VARIANT=Server ghcr.io/jasonn3/build-container-installer:latest -``` - -### VSCode Dev Container -There is a dev container configuration provided for development. By default it will use the existing container image available at `ghcr.io/jasonn3/build-container-installer:latest`, however, you can have it build a new image by editing `.devcontainer/devcontainer.json` and replacing `image` with `build`. `Ctrl+/` can be used to comment and uncomment blocks of code within VSCode. - -The code from VSCode will be available at `/workspaces/build-container-installer` once the container has started. - -Privileged is required for access to loop devices for lorax. - -Use existing container image: -``` -{ - "name": "Existing Dockerfile", - // "build": { - // "context": "..", - // "dockerfile": "../Containerfile", - // "args": { - // "version": "39" - // } - // }, - "image": "ghcr.io/jasonn3/build-container-installer:latest", - "overrideCommand": true, - "shutdownAction": "stopContainer", - "privileged": true -} -``` - -Build a new container image: -``` -{ - "name": "Existing Dockerfile", - "build": { - "context": "..", - "dockerfile": "../Containerfile", - "args": { - "version": "39" - } - }, - //"image": "ghcr.io/jasonn3/build-container-installer:latest", - "overrideCommand": true, - "shutdownAction": "stopContainer", - "privileged": true -} -``` +## Star History + + + + + Star History Chart + + diff --git a/action.yml b/action.yml index 3dd4042..3615f05 100644 --- a/action.yml +++ b/action.yml @@ -1,11 +1,56 @@ -name: Build Contianer Installer -description: generate an ISO for installing OSTrees stored in a container +name: Build Container Installer +description: Generates an ISO for installing an OSTree stored in a container image inputs: + action_version: + description: Version of the action container to run + deprecationMessage: No longer used. github.action_ref replaces the need for this. Will be removed in a future version. + required: false + additional_templates: + description: Space delimited list of additional Lorax templates to include + required: false arch: description: Architecture for image to build required: true default: x86_64 + dnf_cache_key: + description: Overrides the dnf cache key + required: false + enable_cache_dnf: + description: Whether to enable caching for dnf + required: false + default: "true" + enable_cache_skopeo: + description: Whether to enable caching for skopeo + required: false + default: "false" + enable_flatpak_dependencies: + description: Whether to enable automatically determining Flatpak dependencies + required: false + default: "true" + enrollment_password: + description: Used for supporting secure boot (requires SECURE_BOOT_KEY_URL to be defined) + required: false + default: "container-installer" + extra_boot_params: + description: Extra params used by grub to boot the anaconda installer + required: false + flatpak_remote_name: + description: Name of the Flatpak repo on the destination OS + required: false + default: "flathub" + flatpak_remote_refs: + description: Space separated list of flatpak refs to install + required: false + default: "" + flatpak_remote_refs_dir: + description: Directory that contains files that list the flatpak refs to install + required: false + default: "" + flatpak_remote_url: + description: URL of the flatpakrepo file + required: false + default: https://flathub.org/repo/flathub.flatpakrepo image_name: description: Name of the source container image required: true @@ -14,42 +59,201 @@ inputs: description: Repository containing the source container image required: true default: quay.io/fedora-ostree-desktops + image_signed: + description: Whether the container image is signed. The policy to test the signing must be configured inside the container image + required: false + default: "true" + image_src: + description: Overrides the source of the container image. Must be formatted for the skopeo copy command + required: false + image_tag: + description: Tag of the source container image + required: false + iso_name: + description: Name of the ISO you wish to output when completed + required: false + default: build/deploy.iso + make_target: + description: Overrides the default make target + required: false + repos: + description: List of repo files for Lorax to use + required: false + rootfs_size: + description: The size (in GiB) for the squashfs runtime volume + default: "2" + secure_boot_key_url: + description: Secure boot key that is installed from URL location + required: false + skopeo_cache_key: + description: Overrides the skopeo cache key + required: false variant: - description: "Source container variant. Available options can be found by running `dnf provides system-release`. Variant will be the third item in the package name. Example: `fedora-release-kinoite-39-34.noarch` will be kinonite" + description: "Source container variant. Available options can be found by running `dnf provides system-release`. Variant will be the third item in the package name. Example: `fedora-release-kinoite-39-34.noarch` will be kinoite" required: true default: Server version: description: Fedora version of installer to build required: true default: "39" - image_tag: - description: Tag of the source container image. Defaults to the installer version - required: false web_ui: description: Enable Anaconda WebUI required: false default: "false" - action_version: - description: Version of the action container to run - required: true - default: "latest" - additional_templates: - description: Space delimetered list of additional Lorax templates to include - required: false + +outputs: + iso_name: + value: ${{ steps.docker.outputs.iso_name }} + description: The name of the resulting .iso + iso_path: + value: ${{ steps.docker.outputs.iso_path }} + description: The path of the resulting .iso + flatpak_refs: + value: ${{ steps.docker.outputs.flatpak_refs }} + description: The list of Flatpak refs runs: using: composite steps: - - name: Run docker image + - name: Make cache directory shell: bash run: | - docker run --privileged --volume .:/github/workspace/ ghcr.io/jasonn3/build-container-installer:${{ inputs.action_version }} \ - ARCH=${{ inputs.arch }} \ - IMAGE_NAME=${{ inputs.image_name }} \ - IMAGE_REPO=${{ inputs.image_repo }} \ - VARIANT=${{ inputs.variant }} \ - VERSION=${{ inputs.version }} \ - IMAGE_TAG=${{ inputs.image_tag || inputs.version }} \ - WEB_UI=${{ inputs.web_ui }} \ - "ADDITIONAL_TEMPLATES=${{ inputs.additional_templates }}" + sudo mkdir /cache + sudo chmod 777 /cache + - name: Load dnf cache + id: load_dnf_cache + env: + dnf_cache_key: dnf-${{ inputs.version }} + if: inputs.enable_cache_dnf == 'true' + uses: actions/cache/restore@v4 + with: + path: /cache/dnf + key: ${{ inputs.dnf_cache_key || env.dnf_cache_key }} + + - name: Load skopeo cache + id: load_skopeo_cache + env: + skopeo_cache_key: skopeo-${{ inputs.image_name }}-${{ inputs.version || inputs.image_tag }} + if: inputs.enable_cache_skopeo == 'true' + uses: actions/cache/restore@v4 + with: + path: /cache/skopeo + key: ${{ inputs.skopeo_cache_key || env.skopeo_cache_key }} + + - name: Ensure cache directories exist + shell: bash + run: | + mkdir /cache/dnf || true + mkdir /cache/dnf_new || true + mkdir /cache/skopeo || true + + - name: Determine Flatpak dependencies + if: inputs.enable_flatpak_dependencies == 'true' && (inputs.flatpak_remote_refs != '' || inputs.flatpak_remote_refs_dir != '') + id: flatpak_dependencies + shell: bash + run: | + cd ${{ github.action_path }} + make flatpaks/repo \ + FLATPAK_REMOTE_NAME="${{ inputs.flatpak_remote_name }}" \ + ${{ inputs.flatpak_remote_refs && format('FLATPAK_REMOTE_REFS="{0}"', inputs.flatpak_remote_refs) || ''}} \ + ${{ inputs.flatpak_remote_refs_dir && format('FLATPAK_REMOTE_REFS_DIR="{0}/{1}"', github.workspace, inputs.flatpak_remote_refs_dir) || ''}} \ + FLATPAK_REMOTE_URL="${{ inputs.flatpak_remote_url }}" \ + IMAGE_NAME="${{ inputs.image_name }}" \ + IMAGE_REPO="${{ inputs.image_repo }}" \ + IMAGE_SRC="${{ inputs.image_src }}" \ + IMAGE_TAG="${{ inputs.image_tag || inputs.version }}" + + - name: Run docker image + id: docker + env: + ACTION_REPO: ${{ github.action_repository }} + ACTION_REF: ${{ github.action_ref }} + shell: bash + run: | + image=$(echo "ghcr.io/${ACTION_REPO}" | tr [:upper:] [:lower:]) + # Check if running inside of the action repo + if [[ -z "${ACTION_REPO}" ]] + then + image=$(echo "ghcr.io/${{ github.repository }}" | tr [:upper:] [:lower:]) + if [[ -n "${{ github.event.issue.number }}" ]] + then + tag="pr-${{ github.event.issue.number }}" + else + tag="${{ github.ref_name }}" + fi + else + tag="${ACTION_REF}" + fi + if [[ "${{ inputs.enable_cache_dnf }}" == "true" ]] + then + cache="${cache} -v /cache/dnf:/cache/dnf" + fi + if [[ "${{ inputs.enable_cache_skopeo }}" == "true" ]] + then + cache="${cache} -v /cache/skopeo:/cache/skopeo" + fi + if [[ "${{ steps.load_dnf_cache.outputs.cache-hit }}" != "true" ]] + then + cache="${cache} -v /cache/dnf_new:/cache/dnf_new" + fi + vars="" + if [[ -n "${{ inputs.flatpak_remote_refs }}" ]] && [[ -n "${{ inputs.flatpak_remote_refs_dir }}" ]] + then + echo "ERROR: flatpak_remote_refs is mutually exclusive to flatpak_remote_refs_dir" + exit 1 + fi + docker run --privileged --volume ${{ github.workspace }}:/github/workspace/ ${cache} ${image}:${tag} \ + ${{ inputs.make_target }} \ + ADDITIONAL_TEMPLATES="${{ inputs.additional_templates }}" \ + ARCH="${{ inputs.arch }}" \ + DNF_CACHE="/cache/dnf" \ + ENROLLMENT_PASSWORD="${{ inputs.enrollment_password }}" \ + EXTRA_BOOT_PARAMS="${{ inputs.extra_boot_params }}" \ + FLATPAK_REMOTE_NAME="${{ inputs.flatpak_remote_name }}" \ + ${{ inputs.flatpak_remote_refs && format('FLATPAK_REMOTE_REFS="{0}"', inputs.flatpak_remote_refs) || ''}} \ + ${{ inputs.flatpak_remote_refs_dir && format('FLATPAK_REMOTE_REFS_DIR="/github/workspace/{0}"', inputs.flatpak_remote_refs_dir) || ''}} \ + FLATPAK_REMOTE_URL="${{ inputs.flatpak_remote_url }}" \ + FLATPAK_DIR="${{ steps.flatpak_dependencies.outputs.flatpak_dir && format('/github/workspace/{0}', steps.flatpak_dependencies.outputs.flatpak_dir) || '' }}" \ + IMAGE_NAME="${{ inputs.image_name }}" \ + IMAGE_REPO="${{ inputs.image_repo }}" \ + IMAGE_SIGNED="${{ inputs.image_signed }}" \ + IMAGE_SRC="${{ inputs.image_src }}" \ + IMAGE_TAG="${{ inputs.image_tag || inputs.version }}" \ + ISO_NAME=/github/workspace/${{ inputs.iso_name }} \ + ${{ inputs.repos && format('REPOS="{0}"', inputs.repos) || '' }} \ + SECURE_BOOT_KEY_URL="${{ inputs.secure_boot_key_url }}" \ + VARIANT="${{ inputs.variant }}" \ + VERSION="${{ inputs.version }}" \ + WEB_UI="${{ inputs.web_ui }}" + echo "iso_path=$(dirname ${{ inputs.iso_name }})" >> $GITHUB_OUTPUT + echo "iso_name=$(basename ${{ inputs.iso_name }})" >> $GITHUB_OUTPUT + if [[ "${{ steps.flatpak_dependencies.outputs.flatpak_dir }}" != '' ]] + then + echo "flatpak_refs=$(cat ${{ github.workspace }}/${{ steps.flatpak_dependencies.outputs.flatpak_dir }}/list.txt | tr '\n' ' ')" >> $GITHUB_OUTPUT + else + if [[ "${{ inputs.flatpak_remote_refs_dir }}" != '' ]] + then + echo "flatpak_refs=$(cat ${{ github.workspace }}/${{ inputs.flatpak_remote_refs_dir }}/* | tr '\n' ' ')" >> $GITHUB_OUTPUT + else + echo "flatpak_refs=${{ inputs.flatpak_remote_refs}}" >> $GITHUB_OUTPUT + fi + fi + + - name: Save dnf cache + env: + dnf_cache_key: dnf-${{ inputs.version }} + if: inputs.enable_cache_dnf == 'true' && steps.load_dnf_cache.outputs.cache-hit != 'true' + uses: actions/cache/save@v4 + with: + path: /cache/dnf_new + key: ${{ inputs.dnf_cache_key || env.dnf_cache_key }} + + - name: Save skopeo cache + env: + skopeo_cache_key: skopeo-${{ inputs.image_name }}-${{ inputs.version || inputs.image_tag }} + if: inputs.enable_cache_skopeo == 'true' && steps.load_dnf_cache.outputs.cache-hit != 'true' + uses: actions/cache/save@v4 + with: + path: /cache/skopeo + key: ${{ inputs.skopeo_cache_key || env.skopeo_cache_key }} diff --git a/container/Makefile b/container/Makefile new file mode 100644 index 0000000..9e662dc --- /dev/null +++ b/container/Makefile @@ -0,0 +1,11 @@ +$(IMAGE_NAME)-$(IMAGE_TAG): + skopeo copy $(if $(IMAGE_SRC),$(IMAGE_SRC),docker://$(IMAGE_REPO)/$(IMAGE_NAME):$(IMAGE_TAG)) oci:$(IMAGE_NAME)-$(IMAGE_TAG) + +install-deps: + $(install_pkg) skopeo + +FILES=$(filter-out Makefile,$(wildcard *)) +clean: +ifneq ($(FILES),) + rm -Rf $(FILES) +endif \ No newline at end of file diff --git a/cosign.pub b/cosign.pub new file mode 100644 index 0000000..4d5e06d --- /dev/null +++ b/cosign.pub @@ -0,0 +1,4 @@ +-----BEGIN PUBLIC KEY----- +MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEY4ljyIhI2w9DOptB4WT20S+K5ts3 +GJTEKRkXmIYEXGfyKpJMdlGCWeg2kOam5dNhWKXXl46d3eBBo9S53TPpyQ== +-----END PUBLIC KEY----- diff --git a/docs/Makefile b/docs/Makefile new file mode 100644 index 0000000..49f871b --- /dev/null +++ b/docs/Makefile @@ -0,0 +1,12 @@ +SHELL = /bin/bash + +docs: + find -name '*.md' -print0 | xargs -0 -I {} bash -c ' \ + source_file=$${1:2}; \ + final_file=$${source_file//\//_}; \ + mv "$${source_file}" "$${final_file}"; \ + no_ext_source=$${source_file:0:-3}; \ + no_ext_final=$${final_file:0:-3}; \ + sed -i "s;(\(../\)*$${source_file});($${no_ext_final});g" $$(find -name '\''*.md'\''); \ + ' _ {} + find . -type d -empty -delete diff --git a/docs/README.md b/docs/README.md new file mode 100644 index 0000000..2091ec8 --- /dev/null +++ b/docs/README.md @@ -0,0 +1 @@ +These are the files for the [wiki](https://github.com/JasonN3/build-container-installer/wiki) \ No newline at end of file diff --git a/docs/_Sidebar.md b/docs/_Sidebar.md new file mode 100644 index 0000000..7e637e7 --- /dev/null +++ b/docs/_Sidebar.md @@ -0,0 +1,11 @@ +- [Home](home.md) +- [Usage](usage.md) +- Development + - [Using the Makefile](development/makefile.md) + - [Using the Container](development/container.md) + - [Using the VSCode Dev Container](development/vscode.md) + +- Examples + - [Adding Flatpaks](examples/adding-flatpaks.md) + +- [Known Errors](known_errors.md) diff --git a/docs/development/container.md b/docs/development/container.md new file mode 100644 index 0000000..0e0a0ef --- /dev/null +++ b/docs/development/container.md @@ -0,0 +1,22 @@ +# Using the Container + +A container with `make install-deps` already run is provided at `ghcr.io/jasonn3/build-container-installer:latest` + +To use the container file, run `podman run --privileged --volume .:/build-container-installer/build ghcr.io/jasonn3/build-container-installer:latest`. + +This will create an ISO with the baked in defaults of the container image. The resulting file will be called `deploy.iso` + +See [Inputs](usage#inputs) for information about customizing the ISO that gets created. The variables can be defined as environment variables or command arguments. All variables should be specified in CAPITALIZED form. +Examples: + +Building an ISO to install Fedora 39 +```bash +podman run --rm --privileged --volume .:/build-container-installer/build ghcr.io/jasonn3/build-container-installer:latest VERSION=39 IMAGE_NAME=base IMAGE_TAG=39 VARIANT=Server +``` + +Building an ISO to install Fedora 40 +```bash +podman run --rm --privileged --volume .:/build-container-installer/build ghcr.io/jasonn3/build-container-installer:latest VERSION=40 IMAGE_NAME=base IMAGE_TAG=40 VARIANT=Server +``` + +The same commands are also available using `docker` by replacing `podman` with `docker` in each command. diff --git a/docs/development/makefile.md b/docs/development/makefile.md new file mode 100644 index 0000000..be37851 --- /dev/null +++ b/docs/development/makefile.md @@ -0,0 +1,7 @@ +# Using the Makefile + +The Makefile contains all the commands that are run in the action. There are separate targets for each file generated, however `make` can be used to generate the final image and `make clean` can be used to clean up the workspace. The resulting ISO will be stored in the `build` directory. + +`make install-deps` can be used to install the necessary packages. + +See [Inputs](usage#inputs) for information about the available parameters. All variables should be specified in CAPITALIZED form. diff --git a/docs/development/vscode.md b/docs/development/vscode.md new file mode 100644 index 0000000..4b22fe9 --- /dev/null +++ b/docs/development/vscode.md @@ -0,0 +1,46 @@ +# Using the VSCode Dev Container + +There is a dev container configuration provided for development. By default, it will use the existing container image available at `ghcr.io/jasonn3/build-container-installer:latest`. However, you can have it build a new image by editing `.devcontainer/devcontainer.json` and replacing `image` with `build`. `Ctrl+/` can be used to comment and uncomment blocks of code within VSCode. + +The code from VSCode will be available at `/workspaces/build-container-installer` once the container has started. + +Privileged is required for access to loop devices for lorax. + +## Use existing container image + +```diff +{ + "name": "Existing Image", +- "build": { +- "context": "..", +- "dockerfile": "../Containerfile", +- "args": { +- "version": "39" +- } +- }, ++ "image": "ghcr.io/jasonn3/build-container-installer:latest", + "overrideCommand": true, + "shutdownAction": "stopContainer", + "privileged": true +} +``` + +## Build a new container image + +```diff +{ + "name": "New Image", ++ "build": { ++ "context": "..", ++ "dockerfile": "../Containerfile", ++ "args": { ++ "version": "39" ++ } ++ }, +- "image": "ghcr.io/jasonn3/build-container-installer:latest", + "overrideCommand": true, + "shutdownAction": "stopContainer", + "privileged": true +} +``` + diff --git a/docs/examples/adding-flatpaks.md b/docs/examples/adding-flatpaks.md new file mode 100644 index 0000000..153b740 --- /dev/null +++ b/docs/examples/adding-flatpaks.md @@ -0,0 +1,74 @@ +# Adding Flatpaks + +- [Directly using refs](#directly-using-refs) +- [Using a directory](#using-a-directory) + +## Directly using refs + +Action: +Specify the following in your workflow: + +```yaml +- name: Build ISO + uses: jasonn3/build-container-installer@main + id: build + with: + flatpak_remote_name: flathub + flatpak_remote_url: https://flathub.org/repo/flathub.flatpakrepo + flatpak_remote_refs: app/org.videolan.VLC/x86_64/stable runtime/org.kde.Platform/x86_64/5.15-23.08 +``` + +Podman: +Run the following command: + +```bash +podman run --privileged --volume ./:/github/workspace/ ghcr.io/jasonn3/build-container-installer:main \ + FLATPAK_REMOTE_NAME=flathub \ + FLATPAK_REMOTE_URL=https://flathub.org/repo/flathub.flatpakrepo \ + FLATPAK_REMOTE_REFS="app/org.videolan.VLC/x86_64/stable runtime/org.kde.Platform/x86_64/5.15-23.08" +``` + +--- + +## Using a directory + +Action: + +1. Create a directory within your GitHub repo named flatpak_refs +1. Create a file within flatpak_refs with the following content + +```plaintext +app/org.videolan.VLC/x86_64/stable +runtime/org.kde.Platform/x86_64/5.15-23.08 +``` + +Specify the following in your workflow: + +```yaml +- name: Build ISO + uses: jasonn3/build-container-installer@main + id: build + with: + flatpak_remote_name: flathub + flatpak_remote_url: https://flathub.org/repo/flathub.flatpakrepo + flatpak_remote_refs_dir: /github/workspace/flatpak_refs +``` + +Podman: + +1. Create a directory named flatpak_refs +1. Create a file within flatpak_refs with the following content + +```plaintext +app/org.videolan.VLC/x86_64/stable +runtime/org.kde.Platform/x86_64/5.15-23.08 +``` + +Run the following command: + +```bash +podman run --privileged --volume ./:/github/workspace/ ghcr.io/jasonn3/build-container-installer:main \ + FLATPAK_REMOTE_NAME=flathub \ + FLATPAK_REMOTE_URL=https://flathub.org/repo/flathub.flatpakrepo \ + FLATPAK_REMOTE_REFS="app/org.videolan.VLC/x86_64/stable runtime/org.kde.Platform/x86_64/5.15-23.08" +``` diff --git a/docs/home.md b/docs/home.md new file mode 100644 index 0000000..f7e2096 --- /dev/null +++ b/docs/home.md @@ -0,0 +1,14 @@ +Welcome to the build-container-installer wiki! + +## Index + +- [Usage](usage.md) +- Development + - [Using the Makefile](development/makefile.md) + - [Using the Container](development/container.md) + - [Using the VSCode Dev Container](development/vscode.md) + +- Examples + - [Adding Flatpaks](examples/adding-flatpaks.md) + +- [Known Errors](known_errors.md) diff --git a/docs/known_errors.md b/docs/known_errors.md new file mode 100644 index 0000000..bda0b22 --- /dev/null +++ b/docs/known_errors.md @@ -0,0 +1,7 @@ +# Known Errors + +This page describes known errors and how to resolve them. + +## failed to write boot loader configuration + +Add `RUN bootupctl backend generate-update-metadata` at the end of your Dockerfile/Containerfile \ No newline at end of file diff --git a/docs/usage.md b/docs/usage.md new file mode 100644 index 0000000..9ffeb8e --- /dev/null +++ b/docs/usage.md @@ -0,0 +1,68 @@ +# Usage + +This action is designed to be called from a GitHub workflow using the following format + +```yaml +- name: Build ISO + uses: jasonn3/build-container-installer@main + id: build + with: + arch: ${{ env.ARCH}} + image_name: ${{ env.IMAGE_NAME}} + image_repo: ${{ env.IMAGE_REPO}} + image_tag: ${{ env.IMAGE_TAG }} + version: ${{ env.VERSION }} + variant: ${{ env.VARIANT }} + iso_name: ${{ env.IMAGE_NAME }}-${{ env.IMAGE_TAG }}-${{ env.VERSION }}.iso + +# This example is for uploading your ISO as a Github artifact. You can do something similar using any cloud storage, so long as you copy the output +- name: Upload ISO as artifact + id: upload + uses: actions/upload-artifact@v4 + with: + name: ${{ steps.build.outputs.iso_name }} + path: | + ${{ steps.build.outputs.iso_path }}/${{ steps.build.outputs.iso_name }} + ${{ steps.build.outputs.iso_path }}/${{ steps.build.outputs.iso_name }}-CHECKSUM + if-no-files-found: error + retention-days: 0 + compression-level: 0 +``` + +## Inputs + +| Variable | Description | Default Value | Action | Container/Makefile | +| ----------------------- | ---------------------------------------------------------------------------- | ---------------------------------------------- | ------------------ | ------------------ | +| additional_templates | Space delimited list of additional Lorax templates to include | \[empty\] | :white_check_mark: | :white_check_mark: | +| arch | Architecture for image to build | x86_64 | :white_check_mark: | :white_check_mark: | +| enrollment_password | Used for supporting secure boot (requires SECURE_BOOT_KEY_URL to be defined) | container-installer | :white_check_mark: | :white_check_mark: | +| extra_boot_params | Extra params used by grub to boot the anaconda installer | \[empty\] | :white_check_mark: | :white_check_mark: | +| flatpak_remote_name | Name of the Flatpak repo on the destination OS | flathub | :white_check_mark: | :white_check_mark: | +| flatpak_remote_refs | Space separated list of flatpak refs to install | \[empty\] | :white_check_mark: | :white_check_mark: | +| flatpak_remote_refs_dir | Directory that contains files that list the flatpak refs to install | \[empty\] | :white_check_mark: | :white_check_mark: | +| flatpak_remote_url | URL of the flatpakrepo file | | :white_check_mark: | :white_check_mark: | +| image_name | Name of the source container image | base | :white_check_mark: | :white_check_mark: | +| image_repo | Repository containing the source container image | quay.io/fedora-ostree-desktops | :white_check_mark: | :white_check_mark: | +| image_signed | Whether the container image is signed. The policy to test the signing must be configured inside the container image | true | :white_check_mark: | :white_check_mark: | +| image_src | Overrides the source of the container image. Must be formatted for the skopeo copy command | \[empty\] | :white_check_mark: | :white_check_mark: | +| image_tag | Tag of the source container image | *VERSION* | :white_check_mark: | :white_check_mark: | +| iso_name | Name of the ISO you wish to output when completed | build/deploy.iso | :white_check_mark: | :white_check_mark: | +| make_target | Overrides the default make target | *ISO_NAME*-Checksum | :white_check_mark: | :x: | +| repos | List of repo files for Lorax to use | /etc/yum.repos.d/*.repo | :white_check_mark: | :white_check_mark: | +| rootfs_size | The size (in GiB) for the squashfs runtime volume | 2 | :white_check_mark: | :white_check_mark: | +| secure_boot_key_url | Secure boot key that is installed from URL location\*\* | \[empty\] | :white_check_mark: | :white_check_mark: | +| variant | Source container variant\* | Server | :white_check_mark: | :white_check_mark: | +| version | Fedora version of installer to build | 39 | :white_check_mark: | :white_check_mark: | +| web_ui | Enable Anaconda WebUI (experimental) | false | :white_check_mark: | :white_check_mark: | + +\*Available options for VARIANT can be found by running `dnf provides system-release`. +Variant will be the third item in the package name. Example: `fedora-release-kinoite-39-34.noarch` will be kinoite + +\*\* If you need to reference a local file, you can use `file://*path*` + +## Outputs + +| Variable | Description | Usage | +| -------- | ----------------------------------------| ------------------------------------------------ | +| iso_name | The name of the resulting .iso | ${{ steps.YOUR_ID_FOR_ACTION.outputs.iso_name }} | +| iso_path | The path to the resulting .iso | ${{ steps.YOUR_ID_FOR_ACTION.outputs.iso_path }} | diff --git a/entrypoint.sh b/entrypoint.sh index 5005737..ba58634 100644 --- a/entrypoint.sh +++ b/entrypoint.sh @@ -2,24 +2,18 @@ set -ex -for entry in $@ -do - export $entry -done +# Create /dev/loop0 if it doesn't already exist. `losetup` has an issue creating it during the first run +mknod -m 0660 /dev/loop0 b 7 0 2>/dev/null || true -# Pull container -make container/${IMAGE_NAME}-${IMAGE_TAG} $@ +if [[ -d /cache/skopeo ]] +then + ln -s /cache/skopeo /build-container-installer/container +fi -# Build base ISO -make boot.iso $@ - -# Add container to ISO -make build/deploy.iso $@ - -# Make output dir in github workspace -mkdir /github/workspace/build || true - -# Copy resulting iso to github workspace and fix permissions -cp build/deploy.iso /github/workspace/build -chmod -R ugo=rwX /github/workspace/build +if [[ ! -d /cache/dnf ]] +then + mkdir /cache/dnf +fi +# Run make command +make "$@" diff --git a/external/Makefile b/external/Makefile new file mode 100644 index 0000000..0cac3e7 --- /dev/null +++ b/external/Makefile @@ -0,0 +1,12 @@ +lorax/branch-$(VERSION): + git config advice.detachedHead false + cd lorax && git reset --hard HEAD && git checkout $(if $(_RHEL),rhel$(word 1,$(subst ., ,$(VERSION)))-branch,tags/$(shell cd lorax && git tag -l lorax-$(VERSION).* --sort=creatordate | grep -v 'lorax-40\.5' | tail -n 1)) + touch lorax/branch-$(VERSION) + +install-deps: +# Used by external/fedora-lorax-templates/ostree-based-installer/lorax-embed-flatpaks.tmpl + $(install_pkg) flatpak dbus-daemon ostree +# Used to clone proper lorax branch + $(install_pkg) git + +clean: \ No newline at end of file diff --git a/external/fedora-lorax-templates b/external/fedora-lorax-templates new file mode 160000 index 0000000..cc11553 --- /dev/null +++ b/external/fedora-lorax-templates @@ -0,0 +1 @@ +Subproject commit cc1155372046baa58f9d2cc27a9e5473bf05a3fb diff --git a/external/lorax b/external/lorax new file mode 160000 index 0000000..ffba307 --- /dev/null +++ b/external/lorax @@ -0,0 +1 @@ +Subproject commit ffba3078beab843c5d663f6443dca28d8e820948 diff --git a/flatpak_refs/Firefox b/flatpak_refs/Firefox new file mode 100644 index 0000000..6bc6e1d --- /dev/null +++ b/flatpak_refs/Firefox @@ -0,0 +1 @@ +app/org.mozilla.firefox/x86_64/stable diff --git a/flatpak_refs/VLC b/flatpak_refs/VLC new file mode 100644 index 0000000..496d8d6 --- /dev/null +++ b/flatpak_refs/VLC @@ -0,0 +1 @@ +app/org.videolan.VLC/x86_64/stable diff --git a/flatpaks/Makefile b/flatpaks/Makefile new file mode 100644 index 0000000..7729d01 --- /dev/null +++ b/flatpaks/Makefile @@ -0,0 +1,43 @@ +IMAGE := $(IMAGE_REPO)/$(IMAGE_NAME):$(IMAGE_TAG) +FLATPAK_DIR := $(if $(GITHUB_WORKSPACE),$(shell mktemp -d -p $(GITHUB_WORKSPACE) flatpak.XXX),$(PWD)/flatpaks) + +.PHONY: full_list +full_list: repo + cat $(FLATPAK_DIR)/list.txt >&2 + + +repo: script.sh + $(if $(GITHUB_WORKSPACE),cp script.sh $(FLATPAK_DIR)/) + docker run --rm --privileged --entrypoint bash -e FLATPAK_SYSTEM_DIR=/flatpak/flatpak -e FLATPAK_TRIGGERSDIR=/flatpak/triggers --volume $(FLATPAK_DIR):/flatpak_dir $(IMAGE) /flatpak_dir/script.sh + $(if $(GITHUB_OUTPUT),echo "flatpak_dir=$(subst $(GITHUB_WORKSPACE)/,,$(FLATPAK_DIR))" >> $(GITHUB_OUTPUT)) + docker rmi $(IMAGE) + +script.sh: + cat << EOF > script.sh + which flatpak &> /dev/null || dnf install -y flatpak + mkdir -p /flatpak/flatpak /flatpak/triggers + mkdir /var/tmp || true + chmod -R 1777 /var/tmp + flatpak config --system --set languages "*" + flatpak remote-add --system $(FLATPAK_REMOTE_NAME) $(FLATPAK_REMOTE_URL) + flatpak install --system -y $(FLATPAK_REMOTE_REFS) + ostree init --repo=/flatpak_dir/repo --mode=archive-z2 + for i in \$$(ostree refs --repo=\$${FLATPAK_SYSTEM_DIR}/repo | grep '^deploy/' | sed 's/^deploy\///g') + do + echo "Copying \$${i}..." + ostree --repo=/flatpak_dir/repo pull-local \$${FLATPAK_SYSTEM_DIR}/repo \$$(ostree --repo=\$${FLATPAK_SYSTEM_DIR}/repo rev-parse $(FLATPAK_REMOTE_NAME)/\$${i}) + mkdir -p \$$(dirname /flatpak_dir/repo/refs/heads/\$${i}) + ostree --repo=\$${FLATPAK_SYSTEM_DIR}/repo rev-parse $(FLATPAK_REMOTE_NAME)/\$${i} > /flatpak_dir/repo/refs/heads/\$${i} + done + flatpak build-update-repo /flatpak_dir/repo + ostree refs --repo=/flatpak_dir/repo | tee /flatpak_dir/list.txt + EOF + +install-deps: + +clean: + $(if $(wildcard script.sh),rm script.sh) + $(if $(wildcard repo),rm -Rf repo) + $(if $(wildcard list.txt),rm list.txt) + +.ONESHELL: \ No newline at end of file diff --git a/lorax_templates/Makefile b/lorax_templates/Makefile new file mode 100644 index 0000000..b2e80e5 --- /dev/null +++ b/lorax_templates/Makefile @@ -0,0 +1,52 @@ +# Converts a post script to a template +# $1 = script to convert +# $2 = file on ISO to write +# $3 = whether to copy the '<%' lines to the template +define convert_post_to_tmpl + header=0; \ + skip=0; \ + while read -r line; \ + do \ + if [[ $$line =~ ^\<\% ]]; \ + then \ + if [[ '$(3)' == 'true' ]]; \ + then \ + echo $$line >> post_$(1).tmpl; \ + fi; \ + echo >> post_$(1).tmpl; \ + else \ + if [[ $$header == 0 ]]; \ + then \ + if [[ $$line =~ ^\#\#\ (.*)$$ ]]; \ + then \ + echo "append $(2) \"%post --erroronfail $${BASH_REMATCH[1]}\"" >> post_$(1).tmpl; \ + skip=1; \ + else \ + echo "append $(2) \"%post --erroronfail\"" >> post_$(1).tmpl; \ + fi; \ + header=1; \ + fi; \ + if [[ $$skip == 0 ]]; \ + then \ + echo "append $(2) \"$${line//\"/\\\"}\"" >> post_$(1).tmpl; \ + fi; \ + skip=0; \ + fi; \ + done < scripts/post/$(1); \ + echo "append $(2) \"%end\"" >> post_$(1).tmpl +endef + +post_%.tmpl: scripts/post/% + $(call convert_post_to_tmpl,$*,usr/share/anaconda/post-scripts/$*.ks,true) + +install_include_post.tmpl: + echo '<%page />' > install_include_post.tmpl + for file in $(patsubst post_%.tmpl, %, $(filter post_%, $(notdir $(_LORAX_TEMPLATES)))); do echo "append usr/share/anaconda/interactive-defaults.ks \"%include /usr/share/anaconda/post-scripts/$${file}.ks\"" >> install_include_post.tmpl; done + +install-deps: + +FILES=$(wildcard post_*) install_include_post.tmpl +clean: +ifneq ($(FILES),) + rm -Rf $(FILES) +endif diff --git a/lorax_templates/cache_copy_dnf.tmpl b/lorax_templates/cache_copy_dnf.tmpl new file mode 100644 index 0000000..43d4354 --- /dev/null +++ b/lorax_templates/cache_copy_dnf.tmpl @@ -0,0 +1,3 @@ +<%page args="dnf_cache"/> + +runcmd bash -c "if [[ -e ${dnf_cache}_new ]]; then cp -R ${dnf_cache}/* ${dnf_cache}_new/; fi" \ No newline at end of file diff --git a/lorax_templates/configure_upgrades.tmpl.in b/lorax_templates/configure_upgrades.tmpl.in deleted file mode 100644 index eb75fa7..0000000 --- a/lorax_templates/configure_upgrades.tmpl.in +++ /dev/null @@ -1,8 +0,0 @@ -append usr/share/anaconda/interactive-defaults.ks "%post --erroronfail" -append usr/share/anaconda/interactive-defaults.ks "sed -i 's/container-image-reference=.*/container-image-reference=ostree-image-signed:docker:\/\/${_IMAGE_REPO_DOUBLE_ESCAPED}\/${IMAGE_NAME}:${IMAGE_TAG}/' /ostree/deploy/default/deploy/*.origin" -append usr/share/anaconda/interactive-defaults.ks "%end" - -append usr/share/anaconda/post-scripts/configure_upgrades.ks "%post --erroronfail" -append usr/share/anaconda/post-scripts/configure_upgrades.ks "sed -i 's/container-image-reference=.*/container-image-reference=ostree-image-signed:docker:\/\/${_IMAGE_REPO_DOUBLE_ESCAPED}\/${IMAGE_NAME}:${IMAGE_TAG}/' /ostree/deploy/default/deploy/*.origin" -append usr/share/anaconda/post-scripts/configure_upgrades.ks "%end" - diff --git a/lorax_templates/flatpak_link.tmpl b/lorax_templates/flatpak_link.tmpl new file mode 100644 index 0000000..a38341b --- /dev/null +++ b/lorax_templates/flatpak_link.tmpl @@ -0,0 +1,5 @@ +<%page args="flatpak_dir"/> + +%if flatpak_dir != "": +symlink /run/install/repo/flatpak /flatpak +%endif \ No newline at end of file diff --git a/lorax_templates/flatpak_set_repo.tmpl b/lorax_templates/flatpak_set_repo.tmpl new file mode 100644 index 0000000..b7fae2d --- /dev/null +++ b/lorax_templates/flatpak_set_repo.tmpl @@ -0,0 +1,8 @@ +<%page args="flatpak_remote_name, _flatpak_repo_url, version"/> +% if int(version) >= 41: +append etc/anaconda/conf.d/anaconda.conf "[Payload]" +append etc/anaconda/conf.d/anaconda.conf "flatpak_remote = ${flatpak_remote_name} ${_flatpak_repo_url}" +% else: +replace "flatpak_manager\.add_remote\(\".*\", \".*\"\)" "flatpak_manager.add_remote(\"${flatpak_remote_name}\", \"${_flatpak_repo_url}\")" /usr/lib64/python*/site-packages/pyanaconda/modules/payloads/payload/rpm_ostree/flatpak_installation.py +replace "flatpak_manager\.replace_installed_refs_remote\(\".*\"\)" "flatpak_manager.replace_installed_refs_remote(\"${flatpak_remote_name}\")" /usr/lib64/python*/site-packages/pyanaconda/modules/payloads/payload/rpm_ostree/flatpak_installation.py +% endif diff --git a/lorax_templates/install_set_installer.tmpl b/lorax_templates/install_set_installer.tmpl new file mode 100644 index 0000000..fafd61e --- /dev/null +++ b/lorax_templates/install_set_installer.tmpl @@ -0,0 +1,4 @@ +<%page args="image_name, image_tag"/> + +append usr/share/anaconda/interactive-defaults.ks "ostreecontainer --url=/run/install/repo/${image_name}-${image_tag} --transport=oci --no-signature-verification" + diff --git a/lorax_templates/scripts/post/flatpak_configure b/lorax_templates/scripts/post/flatpak_configure new file mode 100644 index 0000000..5331c05 --- /dev/null +++ b/lorax_templates/scripts/post/flatpak_configure @@ -0,0 +1,16 @@ +<%page args="_flatpak_repo_gpg, flatpak_remote_name"/> + +if [[ -d /ostree/deploy/default/var/lib/flatpak/repo ]] +then + echo ${_flatpak_repo_gpg} | base64 -d > /ostree/deploy/default/var/lib/flatpak/repo/flathub.trustedkeys.gpg +elif [[ -d /var/lib/flatpak/repo ]] +then + echo ${_flatpak_repo_gpg} | base64 -d > /var/lib/flatpak/repo/flathub.trustedkeys.gpg +else + echo "Could not find Flatpaks repo" +fi + +if [[ "${flatpak_remote_name}" != 'fedora' ]] +then + systemctl disable flatpak-add-fedora-repos.service +fi diff --git a/lorax_templates/scripts/post/install_configure_upgrades b/lorax_templates/scripts/post/install_configure_upgrades new file mode 100644 index 0000000..20ca2ae --- /dev/null +++ b/lorax_templates/scripts/post/install_configure_upgrades @@ -0,0 +1,18 @@ +<%page args="image_repo, _image_repo_double_escaped, image_name, image_signed, image_tag, _rhel, version"/> + +if (which bootc &> /dev/null) && [ ${_rhel} == 'false' && ${version} -ge 39 ] +then + if [ ${image_signed} == 'true' ] + then + bootc switch --mutate-in-place --enforce-container-sigpolicy --transport registry ${image_repo}/${image_name}:${image_tag} + else + bootc switch --mutate-in-place --transport registry ${image_repo}/${image_name}:${image_tag} + fi +else + if [ ${image_signed} == 'true' ] + then + sed -i 's/container-image-reference=.*/container-image-reference=ostree-image-signed:docker:\/\/${_image_repo_double_escaped}\/${image_name}:${image_tag}/' /ostree/deploy/default/deploy/*.origin + else + sed -i 's/container-image-reference=.*/container-image-reference=ostree-unverified-image:docker:\/\/${_image_repo_double_escaped}\/${image_name}:${image_tag}/' /ostree/deploy/default/deploy/*.origin + fi +fi diff --git a/lorax_templates/scripts/post/secureboot_enroll_key b/lorax_templates/scripts/post/secureboot_enroll_key new file mode 100755 index 0000000..21def9e --- /dev/null +++ b/lorax_templates/scripts/post/secureboot_enroll_key @@ -0,0 +1,26 @@ +<%page args="enrollment_password"/> +## --nochroot + +set -oue pipefail + +readonly ENROLLMENT_PASSWORD=${enrollment_password} +readonly SECUREBOOT_KEY="/run/install/repo/sb_pubkey.der" + +if [[ ! -d "/sys/firmware/efi" ]]; then + echo "EFI mode not detected. Skipping key enrollment." + exit 0 +fi + +if [[ ! -f "$SECUREBOOT_KEY" ]]; then + echo "Secure boot key not provided: $SECUREBOOT_KEY" + exit 0 +fi + +SYS_ID="$(cat /sys/devices/virtual/dmi/id/product_name)" +if [[ ":Jupiter:Galileo:" =~ ":$SYS_ID:" ]]; then + echo "Steam Deck hardware detected. Skipping key enrollment." + exit 0 +fi + +mokutil --timeout -1 || : +echo -e "$ENROLLMENT_PASSWORD\n$ENROLLMENT_PASSWORD" | mokutil --import "$SECUREBOOT_KEY" || : diff --git a/lorax_templates/set_installer.tmpl.in b/lorax_templates/set_installer.tmpl.in deleted file mode 100644 index 66f01e0..0000000 --- a/lorax_templates/set_installer.tmpl.in +++ /dev/null @@ -1,2 +0,0 @@ -append usr/share/anaconda/interactive-defaults.ks "ostreecontainer --url=/run/install/repo/${IMAGE_NAME}-${IMAGE_TAG} --transport=oci --no-signature-verification" - diff --git a/repos/Makefile b/repos/Makefile new file mode 100644 index 0000000..63e2f7f --- /dev/null +++ b/repos/Makefile @@ -0,0 +1,15 @@ +repos: $(_REPO_FILES) + +# Step 2: Replace vars in repo files +%.repo: /etc/yum.repos.d/%.repo + cp /etc/yum.repos.d/$*.repo $*.repo + sed -i "s/\$$releasever/$(VERSION)/g" $*.repo + sed -i "s/\$$basearch/$(ARCH)/g" $*.repo + +install-deps: + +FILES=$(wildcard *.repo) +clean: +ifneq ($(FILES),) + rm -Rf $(FILES) +endif \ No newline at end of file diff --git a/test/Makefile b/test/Makefile new file mode 100644 index 0000000..c9785c7 --- /dev/null +++ b/test/Makefile @@ -0,0 +1,23 @@ +all: $(filter-out README.md Makefile,$(wildcard *)) + +$(filter-out README.md Makefile,$(wildcard *)): + $(eval DIR=$(firstword $(subst /, ,$@))) + $(MAKE) -w -C $(DIR) + +$(filter-out README.md Makefile,$(wildcard */*)): + $(eval DIR=$(firstword $(subst /, ,$@))) + $(eval TARGET=$(subst $(DIR)/,,$@)) + $(MAKE) -w -C $(DIR) $(TARGET) + +.DEFAULT: + $(eval DIR=$(firstword $(subst /, ,$@))) + $(if $(filter-out $(DIR),$@), $(eval TARGET=$(subst $(DIR)/,,$@)),$(eval TARGET=)) + $(MAKE) -w -C $(DIR) $(TARGET) + +install-deps: + $(foreach DIR,$(filter-out README.md Makefile,$(wildcard *)),$(MAKE) -w -C $(DIR) install-deps;) + +clean: + $(foreach DIR,$(filter-out README.md Makefile,$(wildcard *)),$(MAKE) -w -C $(DIR) clean;) + +.PHONY: all $(filter-out README.md Makefile,$(wildcard *)) $(filter-out README.md Makefile,$(wildcard */*)) \ No newline at end of file diff --git a/test/iso/Makefile b/test/iso/Makefile new file mode 100644 index 0000000..3f3f76f --- /dev/null +++ b/test/iso/Makefile @@ -0,0 +1,25 @@ +ISO_NAME=deploy.iso +ISO_TESTS=$(wildcard install_*) $(if $(FLATPAK_REMOTE_REFS),$(wildcard flatpak_*))$(if $(FLATPAK_DIR),$(wildcard flatpak_*)) + +all: $(ISO_TESTS) clean + +$(ISO_TESTS): mnt/iso + $(eval _VARS = ISO_NAME VERSION FLATPAK_REMOTE_NAME _FLATPAK_REPO_URL) + chmod +x $@ + $(foreach var,$(_VARS),$(var)=$($(var))) ./$@ + +mnt/iso: + sudo modprobe loop + sudo mkdir -p mnt/iso mnt/install + sudo mount -o loop ../../$(ISO_NAME) mnt/iso + sudo mount -t squashfs -o loop mnt/iso/images/install.img mnt/install + +clean: + sudo umount mnt/install || true + sudo umount mnt/iso || true + sudo rmdir mnt/install mnt/iso + +install-deps: + $(install_pkg) isomd5sum coreutils squashfs-tools curl + +.PHONY: all $(ISO_TESTS) clean \ No newline at end of file diff --git a/test/iso/README.md b/test/iso/README.md new file mode 100644 index 0000000..bd511d9 --- /dev/null +++ b/test/iso/README.md @@ -0,0 +1 @@ +Place scripts that will test the ISO. The ISO file will be passed as the first argument \ No newline at end of file diff --git a/test/iso/flatpak_repo_updated.sh b/test/iso/flatpak_repo_updated.sh new file mode 100644 index 0000000..c8187ff --- /dev/null +++ b/test/iso/flatpak_repo_updated.sh @@ -0,0 +1,54 @@ +#!/bin/bash + +if [[ ${VERSION} -ge 41 ]] +then + result=0 + grep "^\[Payload\]" mnt/install/etc/anaconda/conf.d/anaconda.conf > /dev/null || { + echo "Missing [Payload] header" + result=1 + } + grep "^flatpak_remote = ${FLATPAK_REMOTE_NAME} ${_FLATPAK_REPO_URL}" mnt/install/etc/anaconda/conf.d/anaconda.conf > /dev/null || { + echo "Missing flatpak_remote option" + result=1 + } + exit ${result} +fi + +add_line=$(grep flatpak_manager.add_remote mnt/install/usr/lib64/python*/site-packages/pyanaconda/modules/payloads/payload/rpm_ostree/flatpak_installation.py) + +add_line_repo=$(echo "${add_line}" | grep "${FLATPAK_REMOTE_NAME}") +add_line_url=$(echo "${add_line}" | grep "${_FLATPAK_REPO_URL}") + +result=0 +if [ -z "${add_line_repo}" ] +then + echo "Repo name not updated on add_remote line" + echo "${add_line}" + result=1 +else + echo "Repo name found on add_remote line" +fi + +if [ -z "${add_line_url}" ] +then + echo "Repo url not updated on add_remote line" + echo "${add_line}" + result=1 +else + echo "Repo url found on add_remote line" +fi + +replace_line=$(grep flatpak_manager.replace_installed_refs_remote mnt/install/usr/lib64/python*/site-packages/pyanaconda/modules/payloads/payload/rpm_ostree/flatpak_installation.py) + +replace_line_repo=$(echo "${replace_line}" | grep "${FLATPAK_REMOTE_NAME}") + +if [ -z "${replace_line_repo}" ] +then + echo "Repo name not updated on replace_installed_refs line" + echo "${replace_line}" + result=1 +else + echo "Repo name found on replace_installed_refs line" +fi + +exit ${result} \ No newline at end of file diff --git a/test/iso/install_hash.sh b/test/iso/install_hash.sh new file mode 100644 index 0000000..6989399 --- /dev/null +++ b/test/iso/install_hash.sh @@ -0,0 +1,14 @@ +#!/bin/bash + +#set -ex + +checkisomd5 "../../${ISO_NAME}" +if [[ $? != 0 ]] +then + echo "Found:" + checkisomd5 --md5sumonly "../../${ISO_NAME}" + echo "Expected:" + implantisomd5 --force "../../${ISO_NAME}" +fi + +cd "$(dirname "../../${ISO_NAME}")" && sha256sum -c "$(basename "${ISO_NAME}")-CHECKSUM" \ No newline at end of file diff --git a/test/iso/install_os-release.sh b/test/iso/install_os-release.sh new file mode 100644 index 0000000..788111a --- /dev/null +++ b/test/iso/install_os-release.sh @@ -0,0 +1,14 @@ +#!/bin/bash + +FOUND_VERSION=$(grep VERSION_ID mnt/install/etc/os-release | cut -d= -f2 | tr -d '"') + +if [[ ${FOUND_VERSION} != ${VERSION} ]] +then + echo "Version mismatch" + echo "Expected: ${VERSION}" + echo "Found: ${FOUND_VERSION}" + exit 1 +else + echo "Correct version found" + exit 0 +fi \ No newline at end of file diff --git a/test/repo/Makefile b/test/repo/Makefile new file mode 100644 index 0000000..3c395c3 --- /dev/null +++ b/test/repo/Makefile @@ -0,0 +1,11 @@ +REPO_TESTS=$(filter-out README.md Makefile,$(wildcard *)) + +all: $(REPO_TESTS) + +$(REPO_TESTS): + chmod +x $@ + ./$@ + +install-deps: + +.PHONY: $(REPO_TESTS) \ No newline at end of file diff --git a/test/repo/vars.py b/test/repo/vars.py new file mode 100755 index 0000000..497b67e --- /dev/null +++ b/test/repo/vars.py @@ -0,0 +1,122 @@ +#!/usr/bin/env python + +makefile = open('../../Makefile.inputs', 'r') +makefile_lines = makefile.readlines() + +inputs = {} +outputs = {} +errors = 0 + +for line in makefile_lines: + if line.startswith('#'): + makefile_lines.remove(line) + continue + parts = line.split('=', 1) + if parts[0].startswith('export'): + var_name = parts[0].strip().split(' ')[1].lower() + else: + var_name = parts[0].strip().lower() + inputs[var_name] = {'default_value': parts[1].strip(), 'makefile': True} + +action = open('../../action.yml', 'r') +action_lines = action.readlines() + +at_inputs = False +at_outputs = False +for line in action_lines: + if not at_inputs: + if line.strip() == 'inputs:': + at_inputs = True + continue + else: + if line.startswith(' '): + parts = line.strip().split(':', 1) + if parts[0] == 'description': + inputs[var_name]['description'] = parts[1].strip() + if parts[0] == 'deprecationMessage': + inputs[var_name]['deprecated'] = True + if parts[0] == 'default': + if 'default' in inputs[var_name]: + if inputs[var_name]['default_value'] != parts[1].strip().strip('"'): + print("ERROR: Default value for " + var_name + " in action.yml does not match Makefile") + errors += 1 + else: + inputs[var_name]['default_value'] = parts[1].strip().strip('"') + elif line.startswith(' '): + var_name = line.strip().strip(':').lower() + if not var_name in inputs: + inputs[var_name] = {} + inputs[var_name]['action'] = True + else: + at_inputs = False + + if not at_outputs: + if line.strip() == 'outputs:': + at_outputs = True + continue + else: + if line.startswith(' '): + parts = line.strip().split(':', 1) + if parts[0] == 'description': + outputs[var_name]['description'] = parts[1].strip() + if parts[0] == 'deprecationMessage': + outputs[var_name]['deprecated'] = True + if parts[0] == 'default': + outputs[var_name]['default_value'] = parts[1].strip().strip('"') + elif line.startswith(' '): + var_name = line.strip().strip(':').lower() + outputs[var_name] = {} + else: + at_outputs = False + + +readme = open('../../README.md', 'r') +readme_lines = readme.readlines() + +at_inputs = False +skip_header = True +at_outputs = False +for line in readme_lines: + if not at_inputs: + if line.strip() == '### Inputs': + at_inputs = True + continue + else: + if skip_header: + if line.startswith('| -----'): + skip_header = False + continue + else: + if not line.startswith('|'): + at_inputs = False + continue + parts = line.split('|') + var_name = parts[1].strip().lower() + if not var_name in inputs: + print("ERROR: " + var_name + " is not listed in action.yml or Makefile") + errors += 1 + continue + if 'description' in inputs[var_name]: + if parts[2].strip().strip('\*') != inputs[var_name]['description']: + print("WARNING: " + var_name + " description in README.md does not match action.yml") + if 'default_value' in inputs[var_name]: + if not parts[3].strip().strip('"<>').startswith('*'): + if inputs[var_name]['default_value'] == "": + if parts[3].strip().strip('"') != '\\[empty\\]': + print("ERROR: " + var_name + " default value in README.md does not match action.yml") + print("Found " + parts[3].strip().strip('"<>')) + print("Expected " + inputs[var_name]['default_value']) + errors += 1 + elif parts[3].strip().strip('"<>') != inputs[var_name]['default_value']: + print("ERROR: " + var_name + " default value in README.md does not match action.yml") + print("Found " + parts[3].strip().strip('"<>')) + print("Expected " + inputs[var_name]['default_value']) + errors += 1 + if 'action' in inputs[var_name] and inputs[var_name]['action']: + if parts[4].strip() != ':white_check_mark:': + print("WARNING: " + var_name + " not labeled as in action.yml in the README.md") + if 'makefile' in inputs[var_name] and inputs[var_name]['makefile']: + if parts[4].strip() != ':white_check_mark:': + print("WARNING: " + var_name + " not labeled as in Makefile in the README.md") + +exit(errors) \ No newline at end of file diff --git a/test/vm/Makefile b/test/vm/Makefile new file mode 100644 index 0000000..6578595 --- /dev/null +++ b/test/vm/Makefile @@ -0,0 +1,100 @@ +VM_TESTS=$(wildcard install_*) $(if $(FLATPAK_REMOTE_REFS),$(wildcard flatpak_*))$(if $(FLATPAK_DIR),$(wildcard flatpak_*)) + +all: $(VM_TESTS) clean + +$(VM_TESTS): start_vm ansible_inventory + $(eval _VARS = IMAGE_REPO IMAGE_NAME IMAGE_TAG) + + ansible -i ansible_inventory -m ansible.builtin.wait_for_connection vm + + chmod +x $@ + $(foreach var,$(_VARS),$(var)=$($(var))) ./$@ + +ansible_inventory: + echo "ungrouped:" > ansible_inventory + echo " hosts:" >> ansible_inventory + echo " vm:" >> ansible_inventory + echo " ansible_host: $(VM_IP)" >> ansible_inventory + echo " ansible_port: $(VM_PORT)" >> ansible_inventory + echo " ansible_user: $(VM_USER)" >> ansible_inventory + echo " ansible_password: $(VM_PASS)" >> ansible_inventory + echo " ansible_become_pass: $(VM_PASS)" >> ansible_inventory + echo " ansible_ssh_common_args: '-o StrictHostKeyChecking=no'" >> ansible_inventory + +.PHONY: $(VM_TESTS) install-deps + +install-deps: + $(install_pkg) qemu-system qemu-utils xorriso qemu-system-x86 ncat socat jq ansible curl + +files/mnt/iso: + $(if $(wildcard files/mnt),,mkdir files/mnt) + $(if $(wildcard files/mnt/iso),,mkdir files/mnt/iso) + sudo mount -o loop ../../$(ISO_NAME) files/mnt/iso + +files/grub.cfg: files/mnt/iso + cp files/mnt/iso/$(if $(_RHEL),isolinux/grub.conf,boot/grub2/grub.cfg) files/grub.cfg + sed -i 's/quiet/console=ttyS0,115200n8 inst.ks=cdrom:\/ks.cfg/' files/grub.cfg + sed -i 's/set default="1"/set default="0"/' files/grub.cfg + sed -i 's/set timeout=60/set timeout=1/' files/grub.cfg + +.PHONY: clean +clean: + $(if $(wildcard start_vm), kill "$(shell cat start_vm)") + $(if $(wildcard files/mnt/iso),sudo umount files/mnt/iso) + $(if $(wildcard files/mnt/iso),rmdir files/mnt/iso) + $(if $(wildcard ansible_inventory),rm ansible_inventory) + $(if $(wildcard files/install.iso),rm files/install.iso) + $(if $(wildcard files/disk.qcow2),rm files/disk.qcow2) + $(if $(wildcard install_os),rm install_os) + $(if $(wildcard start_vm),rm start_vm) + +files/install.iso: files/grub.cfg + xorriso -dialog on << EOF + -indev ../../$(ISO_NAME) + -outdev files/install.iso + -boot_image any replay + -joliet on + -compliance joliet_long_names + -map files/ks.cfg ks.cfg + -chmod 0444 ks.cfg + -map files/grub.cfg $(if $(_RHEL),isolinux/grub.conf,boot/grub2/grub.cfg) + -end + EOF + +files/disk.qcow2: + qemu-img create -f qcow2 files/disk.qcow2 50G + +install_os: files/install.iso files/disk.qcow2 + timeout 1h qemu-system-x86_64 -name "Anaconda" -boot d -m 4096 -cpu qemu64 -display none -cdrom files/install.iso -smp 2 -hda files/disk.qcow2 -serial telnet:localhost:4321,server=on,wait=off & QEMU_PID=$$! + echo "PID: $$QEMU_PID" + timeout 1m bash -c "while ! (echo > /dev/tcp/127.0.0.1/4321); do sleep 0.1; done" + (nc localhost 4321 | tee vm.stdout) & + wait $$QEMU_PID + touch install_os + +.ONESHELL: + +start_vm: install_os + mkfifo vm.stdin + qemu-system-x86_64 -name "Anaconda" \ + -m 4096 -cpu qemu64 -display none -smp 2 \ + -chardev socket,path=/tmp/qga.sock,server=on,wait=off,id=qga0 \ + -device e1000,netdev=net0 \ + -netdev user,id=net0,hostfwd=tcp::$(VM_PORT)-:22 \ + -device virtio-serial \ + -device virtserialport,chardev=qga0,name=org.qemu.guest_agent.0 \ + -boot c -hda files/disk.qcow2 -serial telnet:localhost:4321,server=on,wait=off & export QEMU_PID=$$! + echo "PID: $$QEMU_PID" + + timeout 1m bash -c "while ! (echo > /dev/tcp/127.0.0.1/4321); do sleep 0.1; done" + (tail -f vm.stdin | nc localhost 4321 | tee vm.stdout) & + + timeout 30m bash -c "while ! (echo > /dev/tcp/$(VM_IP)/$(VM_PORT)); do sleep 1; done" + + if ! (echo > /dev/tcp/$(VM_IP)/$(VM_PORT)) + then + echo "SSH must be installed and enabled inside the container" + fi + + echo "VM ready for tests at IP $(VM_IP):$(VM_PORT)" + echo $$QEMU_PID > start_vm diff --git a/test/vm/README.md b/test/vm/README.md new file mode 100644 index 0000000..39840b4 --- /dev/null +++ b/test/vm/README.md @@ -0,0 +1 @@ +Place scripts that will test the VM. The VM will be available at ${VM_IP} using username ${VM_USER} and password ${VM_PASS} \ No newline at end of file diff --git a/test/vm/files/ks.cfg b/test/vm/files/ks.cfg new file mode 100644 index 0000000..280583d --- /dev/null +++ b/test/vm/files/ks.cfg @@ -0,0 +1,9 @@ +lang en_US.UTF-8 +keyboard us +timezone Americas/New_York +zerombr +clearpart --all --initlabel +autopart +poweroff +user --name=core --groups=wheel --password=foobar +%include /usr/share/anaconda/interactive-defaults.ks diff --git a/test/vm/flatpak_fedora_repo_disabled.yml b/test/vm/flatpak_fedora_repo_disabled.yml new file mode 100644 index 0000000..eb87099 --- /dev/null +++ b/test/vm/flatpak_fedora_repo_disabled.yml @@ -0,0 +1,18 @@ +#!/usr/bin/env -S ansible-playbook -i ./ansible_inventory +--- +- name: Test fedora flatpak repo wasn't enabled + hosts: vm + gather_facts: no + + tasks: + - name: Collect facts about system services + service_facts: + register: services_state + + - name: Check that flatpak-add-fedora-repos is disabled + when: services_state['ansible_facts']['services']['flatpak-add-fedora-repos.service'] is defined + ansible.builtin.assert: + that: + - services_state['ansible_facts']['services']['flatpak-add-fedora-repos.service']['status'] == 'disabled' + fail_msg: 'flatpak-add-fedora-repos.service is not disabled' + success_msg: 'flatpak-add-fedora-repos.service is correctly disabled' diff --git a/test/vm/flatpak_installed.yml b/test/vm/flatpak_installed.yml new file mode 100644 index 0000000..da4f331 --- /dev/null +++ b/test/vm/flatpak_installed.yml @@ -0,0 +1,25 @@ +#!/usr/bin/env -S ansible-playbook -i ./ansible_inventory +--- +- name: Test for installed flatpaks + hosts: vm + gather_facts: no + + tasks: + # Verifies that the flatpaks are installed + - name: Get list of installed Flatpaks + become: true + ansible.builtin.command: + cmd: /usr/bin/flatpak list + register: flatpaks + + - name: Check that VLC is installed + ansible.builtin.assert: + that: + - "'VLC' in flatpaks.stdout" + fail_msg: 'VLC is not installed' + + - name: Check that Firefox is installed + ansible.builtin.assert: + that: + - "'Firefox' in flatpaks.stdout" + fail_msg: 'Firefox is not installed' diff --git a/test/vm/flatpak_update.yml b/test/vm/flatpak_update.yml new file mode 100644 index 0000000..3f80685 --- /dev/null +++ b/test/vm/flatpak_update.yml @@ -0,0 +1,12 @@ +#!/usr/bin/env -S ansible-playbook -i ./ansible_inventory +--- +- name: Test flatpak update + hosts: vm + gather_facts: no + + tasks: + # Verifies that the GPG key is functional + - name: Test updating flatpak packages + become: true + ansible.builtin.command: + cmd: /usr/bin/flatpak update -y --noninteractive diff --git a/test/vm/install_image_source.yml b/test/vm/install_image_source.yml new file mode 100644 index 0000000..1b21331 --- /dev/null +++ b/test/vm/install_image_source.yml @@ -0,0 +1,25 @@ +#!/usr/bin/env -S ansible-playbook -i ./ansible_inventory +--- +- name: Test Container Image source updates + hosts: vm + gather_facts: no + + tasks: + # Get list of origins + - name: Get origin + become: true + ansible.builtin.command: + cmd: /bin/bash -c "cat /ostree/deploy/default/deploy/*.origin" + register: origin + + - name: Get vars + ansible.builtin.set_fact: + image_repo: "{{ lookup('ansible.builtin.env', 'IMAGE_REPO') }}" + image_name: "{{ lookup('ansible.builtin.env', 'IMAGE_NAME') }}" + image_tag: "{{ lookup('ansible.builtin.env', 'IMAGE_TAG') }}" + + - name: Tests + ansible.builtin.assert: + that: + - (image_repo + '/' + image_name + ':' + image_tag) in origin.stdout + fail_msg: 'Origin not configured' diff --git a/xorriso/Makefile b/xorriso/Makefile new file mode 100644 index 0000000..b2f5d87 --- /dev/null +++ b/xorriso/Makefile @@ -0,0 +1,14 @@ +input.txt: gen_input.sh + find + $(if $(wildcard ../results/boot/grub2/grub.cfg),sed -i 's/quiet/quiet $(EXTRA_BOOT_PARAMS)/g' ../results/boot/grub2/grub.cfg) + sed -i 's/quiet/quiet $(EXTRA_BOOT_PARAMS)/g' ../results/EFI/BOOT/grub.cfg + $(eval _VARS = ARCH FLATPAK_DIR IMAGE_NAME IMAGE_TAG ISO_NAME VERSION) + $(foreach var,$(_VARS),$(var)=$($(var))) bash gen_input.sh | tee input.txt + +install-deps: + +FILES=$(wildcard input.txt) +clean: +ifneq ($(FILES),) + rm -Rf $(FILES) +endif \ No newline at end of file diff --git a/xorriso/gen_input.sh b/xorriso/gen_input.sh new file mode 100644 index 0000000..0329186 --- /dev/null +++ b/xorriso/gen_input.sh @@ -0,0 +1,53 @@ +#!/bin/bash + +echo "-report_about WARNING" +echo "-indev ${PWD}/../results/images/boot.iso" +echo "-outdev ${ISO_NAME}" +echo "-boot_image any replay" +echo "-joliet on" +echo "-compliance joliet_long_names" +pushd "${PWD}/../results" > /dev/null +#for file in $(find .) +for file in ./boot/grub2/grub.cfg ./EFI/BOOT/grub.cfg +do + if [[ "$file" == "./images/boot.iso" ]] + then + continue + fi + if [[ -f ${PWD}/${file} ]] + then + echo "-map ${PWD}/${file} ${file:2}" + echo "-chmod 0444 ${file:2}" + fi +done +popd > /dev/null + +if [[ -n "${FLATPAK_DIR}" ]] +then + pushd "${FLATPAK_DIR}" > /dev/null + for file in $(find repo) + do + if [[ "${file}" == "repo/.lock" ]] + then + continue + fi + echo "-map ${PWD}/${file} flatpak/${file}" + echo "-chmod 0444 flatpak/${file}" + done + popd > /dev/null +fi + +if [ -f "${PWD}/../sb_pubkey.der" ] +then + echo "-map ${PWD}/../sb_pubkey.der sb_pubkey.der" + echo "-chmod 0444 /sb_pubkey.der" +fi + +pushd "${PWD}/../container" > /dev/null +for file in $(find "${IMAGE_NAME}-${IMAGE_TAG}" -type f) +do + echo "-map ${PWD}/${file} ${file}" + echo "-chmod 0444 ${file}" +done +popd > /dev/null +echo "-end" diff --git a/xorriso/gen_input.sh.in b/xorriso/gen_input.sh.in deleted file mode 100644 index b660e1b..0000000 --- a/xorriso/gen_input.sh.in +++ /dev/null @@ -1,16 +0,0 @@ -#!/bin/bash - -echo "-indev $(pwd)/boot.iso" -echo "-outdev $(pwd)/build/deploy.iso" -echo "-boot_image any replay" -echo "-joliet on" -echo "-compliance joliet_long_names" -pushd container > /dev/null -for file in $(find ${IMAGE_NAME}-${IMAGE_TAG}) -do - echo "-map $(pwd)/${file} ${file}" - echo "-chmod 0444 ${file}" -done -popd > /dev/null -echo "-end" -