Add GitHub Actions workflow for build and test process #1
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: Build and Test | |
| on: | |
| push: | |
| branches: [ main, develop ] | |
| pull_request: | |
| branches: [ main, develop ] | |
| workflow_dispatch: | |
| env: | |
| IMAGE_NAME: handbuilt-linux | |
| REGISTRY: ghcr.io | |
| jobs: | |
| # =========================================================================== | |
| # Build Job | |
| # =========================================================================== | |
| build: | |
| name: Build Distribution | |
| runs-on: ubuntu-latest | |
| permissions: | |
| contents: read | |
| packages: write | |
| steps: | |
| - name: Checkout code | |
| uses: actions/checkout@v4 | |
| - name: Set up Docker Buildx | |
| uses: docker/setup-buildx-action@v3 | |
| - name: Log in to Container Registry | |
| if: github.event_name != 'pull_request' | |
| uses: docker/login-action@v3 | |
| with: | |
| registry: ${{ env.REGISTRY }} | |
| username: ${{ github.actor }} | |
| password: ${{ secrets.GITHUB_TOKEN }} | |
| - name: Extract metadata | |
| id: meta | |
| uses: docker/metadata-action@v5 | |
| with: | |
| images: ${{ env.REGISTRY }}/${{ github.repository }} | |
| tags: | | |
| type=ref,event=branch | |
| type=ref,event=pr | |
| type=semver,pattern={{version}} | |
| type=semver,pattern={{major}}.{{minor}} | |
| type=sha,prefix={{branch}}- | |
| type=raw,value=latest,enable={{is_default_branch}} | |
| - name: Build Docker image | |
| uses: docker/build-push-action@v5 | |
| with: | |
| context: . | |
| push: false | |
| load: true | |
| tags: ${{ env.IMAGE_NAME }}:test | |
| cache-from: type=gha | |
| cache-to: type=gha,mode=max | |
| build-args: | | |
| BUILD_JOBS=auto | |
| - name: Test Docker image | |
| run: | | |
| docker run --rm ${{ env.IMAGE_NAME }}:test test -f /distro/output.iso | |
| docker run --rm ${{ env.IMAGE_NAME }}:test test -f /distro/bzImage | |
| docker run --rm ${{ env.IMAGE_NAME }}:test test -f /distro/initramfs | |
| - name: Extract artifacts | |
| run: | | |
| mkdir -p artifacts | |
| docker run --rm ${{ env.IMAGE_NAME }}:test cat /distro/output.iso > artifacts/output.iso | |
| docker run --rm ${{ env.IMAGE_NAME }}:test cat /distro/bzImage > artifacts/bzImage | |
| docker run --rm ${{ env.IMAGE_NAME }}:test cat /distro/initramfs > artifacts/initramfs | |
| - name: Upload artifacts | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: linux-distribution | |
| path: artifacts/ | |
| retention-days: 30 | |
| - name: Build and push Docker image | |
| if: github.event_name != 'pull_request' | |
| uses: docker/build-push-action@v5 | |
| with: | |
| context: . | |
| push: true | |
| tags: ${{ steps.meta.outputs.tags }} | |
| labels: ${{ steps.meta.outputs.labels }} | |
| cache-from: type=gha | |
| cache-to: type=gha,mode=max | |
| # =========================================================================== | |
| # Test Job | |
| # =========================================================================== | |
| test: | |
| name: Run Tests | |
| runs-on: ubuntu-latest | |
| needs: build | |
| steps: | |
| - name: Checkout code | |
| uses: actions/checkout@v4 | |
| - name: Set up Docker Buildx | |
| uses: docker/setup-buildx-action@v3 | |
| - name: Build Docker image for testing | |
| uses: docker/build-push-action@v5 | |
| with: | |
| context: . | |
| load: true | |
| tags: ${{ env.IMAGE_NAME }}:test | |
| cache-from: type=gha | |
| - name: Download artifacts | |
| uses: actions/download-artifact@v4 | |
| with: | |
| name: linux-distribution | |
| path: ./artifacts | |
| - name: Run test suite | |
| run: | | |
| chmod +x scripts/*.sh | |
| docker tag ${{ env.IMAGE_NAME }}:test handbuilt-linux:latest | |
| ./scripts/test.sh | |
| - name: Validate ISO | |
| run: | | |
| file artifacts/output.iso | grep -q "ISO 9660" | |
| - name: Validate initramfs | |
| run: | | |
| file artifacts/initramfs | grep -q "gzip compressed" | |
| - name: Check script syntax | |
| run: | | |
| bash -n build.sh | |
| sh -n init.sh | |
| # =========================================================================== | |
| # Lint Job | |
| # =========================================================================== | |
| lint: | |
| name: Lint and Code Quality | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: Checkout code | |
| uses: actions/checkout@v4 | |
| - name: Run hadolint (Dockerfile linter) | |
| uses: hadolint/hadolint-action@v3.1.0 | |
| with: | |
| dockerfile: Dockerfile | |
| ignore: DL3008 | |
| - name: Run shellcheck | |
| uses: ludeeus/action-shellcheck@master | |
| with: | |
| scandir: './scripts' | |
| format: gcc | |
| severity: warning | |
| - name: Check shell scripts | |
| run: | | |
| bash -n build.sh | |
| sh -n init.sh | |
| for script in scripts/*.sh; do | |
| bash -n "$script" | |
| done | |
| # =========================================================================== | |
| # Security Scan Job | |
| # =========================================================================== | |
| security: | |
| name: Security Scan | |
| runs-on: ubuntu-latest | |
| needs: build | |
| permissions: | |
| security-events: write | |
| steps: | |
| - name: Checkout code | |
| uses: actions/checkout@v4 | |
| - name: Build Docker image | |
| uses: docker/build-push-action@v5 | |
| with: | |
| context: . | |
| load: true | |
| tags: ${{ env.IMAGE_NAME }}:scan | |
| cache-from: type=gha | |
| - name: Run Trivy vulnerability scanner | |
| uses: aquasecurity/trivy-action@master | |
| with: | |
| image-ref: ${{ env.IMAGE_NAME }}:scan | |
| format: 'sarif' | |
| output: 'trivy-results.sarif' | |
| - name: Upload Trivy results to GitHub Security | |
| uses: github/codeql-action/upload-sarif@v3 | |
| if: always() | |
| with: | |
| sarif_file: 'trivy-results.sarif' | |
| # =========================================================================== | |
| # Release Job (only on tags) | |
| # =========================================================================== | |
| release: | |
| name: Create Release | |
| runs-on: ubuntu-latest | |
| needs: [build, test, lint] | |
| if: startsWith(github.ref, 'refs/tags/v') | |
| permissions: | |
| contents: write | |
| steps: | |
| - name: Checkout code | |
| uses: actions/checkout@v4 | |
| - name: Download artifacts | |
| uses: actions/download-artifact@v4 | |
| with: | |
| name: linux-distribution | |
| path: ./artifacts | |
| - name: Create checksums | |
| run: | | |
| cd artifacts | |
| sha256sum * > checksums.txt | |
| - name: Create Release | |
| uses: softprops/action-gh-release@v1 | |
| with: | |
| files: | | |
| artifacts/output.iso | |
| artifacts/bzImage | |
| artifacts/initramfs | |
| artifacts/checksums.txt | |
| generate_release_notes: true | |
| env: | |
| GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} |