diff --git a/.github/workflows/dexoron-packages-index.yml b/.github/workflows/dexoron-packages-index.yml index 7f5bd90..df4708e 100644 --- a/.github/workflows/dexoron-packages-index.yml +++ b/.github/workflows/dexoron-packages-index.yml @@ -13,7 +13,6 @@ permissions: jobs: update-packages-index: runs-on: ubuntu-latest - # Запускаем только если это ручной вызов ИЛИ если родительский релиз завершился успешно if: ${{ github.event_name == 'workflow_dispatch' || github.event.workflow_run.conclusion == 'success' }} steps: @@ -24,8 +23,9 @@ jobs: token: ${{ secrets.PACKAGES_REPO_TOKEN }} path: 'central-packages' - - name: Download built package artifact - # Этот шаг отработает только при автоматическом набеге из главного релиза + # --- СКАЧИВАНИЕ АРТЕФАКТОВ ИЗ РЕЛИЗА --- + + - name: Download Arch package artifact if: ${{ github.event_name == 'workflow_run' }} uses: actions/download-artifact@v4 with: @@ -33,9 +33,31 @@ jobs: path: central-packages/archlinux/x86_64/ github-token: ${{ secrets.PACKAGES_REPO_TOKEN }} run-id: ${{ github.event.workflow_run.id }} + continue-on-error: true + + - name: Download Debian package artifact + if: ${{ github.event_name == 'workflow_run' }} + uses: actions/download-artifact@v4 + with: + name: debian-package + path: central-packages/debian/ + github-token: ${{ secrets.PACKAGES_REPO_TOKEN }} + run-id: ${{ github.event.workflow_run.id }} + continue-on-error: true + + - name: Download RPM package artifact + if: ${{ github.event_name == 'workflow_run' }} + uses: actions/download-artifact@v4 + with: + name: rpm-package + path: central-packages/rpm/x86_64/ + github-token: ${{ secrets.PACKAGES_REPO_TOKEN }} + run-id: ${{ github.event.workflow_run.id }} + continue-on-error: true + + # --- ИНДЕКСАЦИЯ REPO --- - name: Update Pacman Database (Inside Arch Container) - # Запускаем изолированный контейнер Арча только ради одной команды repo-add run: | docker run --rm \ -v ${{ github.workspace }}/central-packages:/packages \ @@ -43,33 +65,63 @@ jobs: bash -c ' cd /packages/archlinux/x86_64 && \ rm -f dexoron.db dexoron.files && \ - - # Включаем nullglob, чтобы пустая маска *.pkg.tar.zst не превращалась в одноименную строку shopt -s nullglob packages=(*.pkg.tar.zst) - - # Проверяем, есть ли бинарные пакеты в папке if [ ${#packages[@]} -gt 0 ]; then - echo "Found ${#packages[@]} packages. Updating database..." + echo "Found ${#packages[@]} Arch packages. Updating database..." repo-add dexoron.db.tar.gz "${packages[@]}" && \ ln -sf dexoron.db.tar.gz dexoron.db && \ ln -sf dexoron.files.tar.gz dexoron.files else - echo "No .pkg.tar.zst files found in directory. Skipping database update." + echo "No .pkg.tar.zst files found. Skipping." fi ' + - name: Update Debian APT Repository Index + run: | + sudo apt-get update && sudo apt-get install -y dpkg-dev + cd central-packages/debian + + shopt -s nullglob + deb_packages=(*.deb) + + if [ ${#deb_packages[@]} -gt 0 ]; then + echo "Found ${#deb_packages[@]} Debian packages. Generating Packages.gz..." + # Генерируем индекс для плоского (flat) репозитория + dpkg-scanpackages . /dev/null | gzip -9c > Packages.gz + else + echo "No .deb files found. Skipping Debian index update." + fi + + - name: Update Fedora DNF Repository Index + run: | + sudo apt-get update && sudo apt-get install -y createrepo-c + cd central-packages/rpm/x86_64 + + shopt -s nullglob + rpm_packages=(*.rpm) + + if [ ${#rpm_packages[@]} -gt 0 ]; then + echo "Found ${#rpm_packages[@]} RPM packages. Generating repodata..." + # Пересоздаем метаданные для dnf + createrepo_c . + else + echo "No .rpm files found. Skipping Fedora index update." + fi + + # --- ПУШ ИЗМЕНЕНИЙ --- + - name: Push to dexoron/packages run: | cd central-packages git config user.name "github-actions[bot]" git config user.email "41898282+github-actions[bot]@users.noreply.github.com" - # Проверяем, изменилось ли что-то, чтобы не плодить пустые коммиты + # Проверяем изменения во всех трех целевых папках if [ -n "$(git status --porcelain)" ]; then - git add archlinux/ - git commit -m "chore(arch): update repository db with new packages" + git add archlinux/ debian/ rpm/ + git commit -m "chore: update repositories index (arch, debian, rpm)" git push else - echo "No changes detected in repository database." + echo "No changes detected in repository databases." fi \ No newline at end of file diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 72ab024..9c18d2a 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -10,11 +10,11 @@ on: description: "Tag to build (e.g. v0.6.7)" required: true run_linux: - description: "Build Linux (.deb, .rpm, .snap, binaries)" + description: "Build Linux" type: boolean default: true - run_arch_native: - description: "Build Arch Linux Native (.pkg.tar.zst)" + run_linux_packages: + description: "Build Linux Packages (.deb, .rpm, .snap, .pkg.tar.zst)" type: boolean default: true run_aur: @@ -100,7 +100,7 @@ jobs: name: release-notes path: .github/release-notes.md - # ── Linux ────────────────────────────────────────────────────────────────── + # ── Linux Binaries Matrix ────────────────────────────────────────────────── build-linux: if: ${{ github.event_name == 'push' || github.event.inputs.run_linux == 'true' }} needs: [setup, notes] @@ -156,83 +156,149 @@ jobs: body_path: .github/release-notes.md prerelease: ${{ needs.setup.outputs.prerelease == 'true' }} - # ── Linux Packages (.deb & .rpm) ─────────────────────────────────────────── - build-deb-rpm: - if: ${{ github.event_name == 'push' || github.event.inputs.run_linux == 'true' }} + # ── Linux Packages Matrix (.deb, .rpm, .pkg.tar.zst, .snap) ──────────────── + build-linux-packages: + if: ${{ github.event_name == 'push' || github.event.inputs.run_linux_packages == 'true' }} needs: [setup, notes] runs-on: ubuntu-latest + strategy: + fail-fast: false + matrix: + include: + - package_type: deb + artifact_name: debian-package + - package_type: rpm + artifact_name: rpm-package + - package_type: arch + artifact_name: arch-package + - package_type: snap + artifact_name: snap-package steps: - uses: actions/checkout@v4 with: ref: ${{ needs.setup.outputs.tag }} + - name: Setup Rust (For non-container builds) + if: matrix.package_type != 'arch' + uses: dtolnay/rust-toolchain@stable + + # ── DEB Build ── + - name: Build Debian Package + if: matrix.package_type == 'deb' + run: | + cargo install cargo-deb + cargo build --release + cargo deb --no-build + mkdir -p dist-packages && cp target/debian/*.deb dist-packages/ + + # ── RPM Build ── + - name: Build RPM Package + if: matrix.package_type == 'rpm' + run: | + cargo install cargo-generate-rpm + cargo build --release + cargo generate-rpm + mkdir -p dist-packages && cp target/generate-rpm/*.rpm dist-packages/ + + # ── Snap Build ── + - name: Build Snap Package + if: matrix.package_type == 'snap' + run: | + cargo build --release + mkdir -p dist && cp target/release/dcr dist/ + + - name: Snapcraft Build Action + if: matrix.package_type == 'snap' + uses: snapcore/action-build@v1 + with: + path: packages/snap + + - name: Prepare Snap Output + if: matrix.package_type == 'snap' + run: mkdir -p dist-packages && cp packages/snap/*.snap dist-packages/ + + # ── Arch Linux Native Build ── + - name: Build Arch Package inside Container + if: matrix.package_type == 'arch' + run: | + PKGVER='${{ needs.setup.outputs.version }}' + TAG='${{ needs.setup.outputs.tag }}' + SRC_URL="https://github.com/dexoron/dcr/archive/refs/tags/${TAG}.tar.gz" + SHA256="$(curl -fsSL "$SRC_URL" | sha256sum | awk '{print $1}')" + mkdir -p arch-build + cat > arch-build/PKGBUILD <> /etc/sudoers && \ + chown -R builduser:builduser /build && \ + cd /build && \ + su builduser -c 'makepkg -s --noconfirm' + " + mkdir -p dist-packages && cp arch-build/*.pkg.tar.zst dist-packages/ + + # ── Upload Artifacts ── + - name: Upload Package Artifact + uses: actions/upload-artifact@v4 + with: + name: ${{ matrix.artifact_name }} + path: dist-packages/* + if-no-files-found: ignore + + # ── Publish Packages to Release (Out of Matrix) ──────────────────────────── + publish-dexoron-packages: + needs: [setup, notes, build-linux-packages] + runs-on: ubuntu-latest + steps: - name: Download Release Notes uses: actions/download-artifact@v4 with: name: release-notes path: .github - - name: Setup Rust - uses: dtolnay/rust-toolchain@stable + - name: Download Built Packages + uses: actions/download-artifact@v4 + with: + path: collected-packages - - name: Install Tools - run: | - cargo install cargo-deb - cargo install cargo-generate-rpm - - - name: Build Native Release - run: cargo build --release - - - name: Generate .deb Package - run: cargo deb --no-build - - - name: Generate .rpm Package - run: cargo generate-rpm - - - name: Upload Packages to Release + - name: Upload Everything to GitHub Release uses: softprops/action-gh-release@v2 with: tag_name: ${{ needs.setup.outputs.tag }} files: | - target/debian/*.deb - target/generate-rpm/*.rpm + collected-packages/debian-package/* + collected-packages/rpm-package/* + collected-packages/arch-package/* + collected-packages/snap-package/* body_path: .github/release-notes.md prerelease: ${{ needs.setup.outputs.prerelease == 'true' }} - # ── Snapcraft ────────────────────────────────────────────────────────────── - build-snap: - if: ${{ github.event_name == 'push' || github.event.inputs.run_linux == 'true' }} - needs: [setup, notes] - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v4 - with: - ref: ${{ needs.setup.outputs.tag }} - - - name: Setup Rust - uses: dtolnay/rust-toolchain@stable - - - name: Build Release Binary - run: | - cargo build --release - # Создаем папки для контекста snapcraft, если внутри yaml завязан относительный путь - mkdir -p dist - cp target/release/dcr dist/ - - - name: Build Snap Package - uses: snapcore/action-build@v1 - id: snapcraft - with: - path: packages/snap - - - name: Upload Snap to Release - uses: softprops/action-gh-release@v2 - with: - tag_name: ${{ needs.setup.outputs.tag }} - files: packages/snap/*.snap - prerelease: ${{ needs.setup.outputs.prerelease == 'true' }} - - # ── macOS ────────────────────────────────────────────────────────────────── + # ── macOS Matrix ─────────────────────────────────────────────────────────── build-macos: if: ${{ github.event_name == 'push' || github.event.inputs.run_macos == 'true' }} needs: [setup, notes] @@ -278,11 +344,15 @@ jobs: body_path: .github/release-notes.md prerelease: ${{ needs.setup.outputs.prerelease == 'true' }} - # ── BSD Systems ──────────────────────────────────────────────────────────── + # ── BSD Systems Matrix ───────────────────────────────────────────────────── build-bsd: if: ${{ github.event_name == 'push' || github.event.inputs.run_bsd == 'true' }} needs: [setup, notes] runs-on: ubuntu-latest + strategy: + fail-fast: false + matrix: + system: [freebsd, openbsd, netbsd] steps: - uses: actions/checkout@v4 with: @@ -294,28 +364,26 @@ jobs: name: release-notes path: .github - # ── FreeBSD ── - - name: Install cargo-zigbuild - run: | - pip install cargo-zigbuild - echo "$HOME/.local/bin" >> $GITHUB_PATH - - - name: Setup Rust (FreeBSD) - uses: dtolnay/rust-toolchain@stable + # --- FREEBSD --- + - name: Build in FreeBSD VM + if: matrix.system == 'freebsd' + uses: vmactions/freebsd-vm@v1 with: - targets: x86_64-unknown-freebsd - - - name: Build FreeBSD - run: cargo zigbuild --release --target x86_64-unknown-freebsd + usesh: true + run: | + pkg install -y rust + cargo build --release - name: Prepare FreeBSD Artifact + if: matrix.system == 'freebsd' run: | ASSET="dcr-x86_64-unknown-freebsd-${{ needs.setup.outputs.version }}" - cp target/x86_64-unknown-freebsd/release/dcr "$ASSET" - echo "FREEBSD_ASSET=${ASSET}" >> "$GITHUB_ENV" + cp target/release/dcr "$ASSET" + echo "BSD_ASSET=${ASSET}" >> "$GITHUB_ENV" - # ── OpenBSD ── + # --- OPENBSD --- - name: Build in OpenBSD VM + if: matrix.system == 'openbsd' uses: vmactions/openbsd-vm@v1 with: usesh: true @@ -324,13 +392,15 @@ jobs: cargo build --release - name: Prepare OpenBSD Artifact + if: matrix.system == 'openbsd' run: | ASSET="dcr-x86_64-unknown-openbsd-${{ needs.setup.outputs.version }}" cp target/release/dcr "$ASSET" - echo "OPENBSD_ASSET=${ASSET}" >> "$GITHUB_ENV" + echo "BSD_ASSET=${ASSET}" >> "$GITHUB_ENV" - # ── NetBSD ── + # --- NETBSD --- - name: Build in NetBSD VM + if: matrix.system == 'netbsd' uses: vmactions/netbsd-vm@v1 with: usesh: true @@ -339,24 +409,22 @@ jobs: cargo build --release - name: Prepare NetBSD Artifact + if: matrix.system == 'netbsd' run: | ASSET="dcr-x86_64-unknown-netbsd-${{ needs.setup.outputs.version }}" cp target/release/dcr "$ASSET" - echo "NETBSD_ASSET=${ASSET}" >> "$GITHUB_ENV" + echo "BSD_ASSET=${ASSET}" >> "$GITHUB_ENV" - # ── Assets Upload ── - - name: Upload Release Assets + # --- UPLOAD TARGET --- + - name: Upload BSD Asset to Release uses: softprops/action-gh-release@v2 with: tag_name: ${{ needs.setup.outputs.tag }} - files: | - ${{ env.FREEBSD_ASSET }} - ${{ env.OPENBSD_ASSET }} - ${{ env.NETBSD_ASSET }} + files: ${{ env.BSD_ASSET }} body_path: .github/release-notes.md prerelease: ${{ needs.setup.outputs.prerelease == 'true' }} - # ── Windows ──────────────────────────────────────────────────────────────── + # ── Windows Matrix ───────────────────────────────────────────────────────── build-windows: if: ${{ github.event_name == 'push' || github.event.inputs.run_windows == 'true' }} needs: [setup, notes] @@ -402,77 +470,6 @@ jobs: body_path: .github/release-notes.md prerelease: ${{ needs.setup.outputs.prerelease == 'true' }} - # ── Arch Linux Native Package (.pkg.tar.zst) ─────────────────────────────── - build-arch-package: - if: ${{ github.event_name == 'push' || github.event.inputs.run_arch_native == 'true' }} - needs: [setup, notes] - runs-on: ubuntu-latest - steps: - - name: Checkout code - uses: actions/checkout@v4 - with: - ref: ${{ needs.setup.outputs.tag }} - - - name: Build .pkg.tar.zst inside Arch Container - run: | - PKGVER='${{ needs.setup.outputs.version }}' - TAG='${{ needs.setup.outputs.tag }}' - SRC_URL="https://github.com/dexoron/dcr/archive/refs/tags/${TAG}.tar.gz" - SHA256="$(curl -fsSL "$SRC_URL" | sha256sum | awk '{print $1}')" - - mkdir -p arch-build - - cat > arch-build/PKGBUILD <> /etc/sudoers && \ - chown -R builduser:builduser /build && \ - cd /build && \ - su builduser -c 'makepkg -s --noconfirm' - " - - - name: Upload Arch Package Artifact - uses: actions/upload-artifact@v4 - with: - name: arch-package - path: arch-build/*.pkg.tar.zst - - - name: Upload Package to GitHub Release - uses: softprops/action-gh-release@v2 - with: - tag_name: ${{ needs.setup.outputs.tag }} - files: arch-build/*.pkg.tar.zst - prerelease: ${{ needs.setup.outputs.prerelease == 'true' }} - # ── Arch User Repository (dcr) ─────────────────────────────────── publish-aur: if: ${{ (github.event_name == 'push' && needs.setup.outputs.prerelease == 'false') || github.event.inputs.run_aur == 'true' }} diff --git a/CHANGELOG.md b/CHANGELOG.md index 4c90d28..5b227a1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,52 @@ # Changelog +## [0.6.9] - 2026-05-28 + +Added: + +- **Dexoron Packages Index** — new standalone CI workflow (`.github/workflows/dexoron-packages-index.yml`) + that automatically updates the `dexoron/packages` repository indexes after a release. + Supports Arch Linux (`repo-add`), Debian (`dpkg-scanpackages`), and Fedora (`createrepo_c`). + Triggered by `workflow_dispatch` or `workflow_run` on the Release workflow. + +- **Arch Linux native package** (`.pkg.tar.zst`) build inside the release workflow — + builds from source in an `archlinux:latest` Docker container using a dynamically + generated PKGBUILD. + +- **AUR publish support** — new `run_aur` workflow dispatch input and `publish-aur` / + `publish-aur-bin` jobs that push PKGBUILD / `.SRCINFO` to `aur.archlinux.org`. + +Changed: + +- **Release workflow refactored** — Linux packages (deb, rpm, snap, arch) and BSD + builds now use `strategy.matrix` instead of separate jobs. A new + `publish-dexoron-packages` job collects all package artifacts and uploads them + to the GitHub Release in one step. Removed standalone `build-arch-package`, + `build-snap`, `build-deb-rpm` jobs. The old `run_arch_native` input is now + `run_linux_packages`. + +- **Dexoron Packages Index workflow** extracted from `release.yml` into its own + file with support for Debian and RPM repository indexes in addition to Arch. + +- **git2 vendoring** — enabled `vendored-libgit2` and `vendored-openssl` features + for reproducible CI builds without system libraries. + +- **cargo-generate-rpm metadata** — updated to the current `package.metadata.rpm` + format (uses `files` table instead of `assets` array). + +Fixed: + +- **`--target=` no longer passed to GCC** — the flag is now only injected into + cflags when the resolved compiler name contains `"clang"`. GCC rejects this flag + with `unrecognized command-line option`. + +- **Workspace clean test** — removed assertions for member-local `target/` + directories. Workspace members share the root `target/` directory, so their + individual `src//target/` is never created. + +- **Release build test path** — corrected expected directory from `target/release` + to `target/x86_64-unknown-linux-gnu/release`. + ## [0.6.8] - 2026-05-27 Added: diff --git a/Cargo.toml b/Cargo.toml index 1bb5481..264726f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -14,32 +14,23 @@ pkg-url = "{ repo }/releases/download/v{ version }/dcr-{ target }-{ version }{ b [package.metadata.deb] maintainer = "Dexoron (Bezotechestvo Vladimir) " copyright = "2026, Dexoron" -license-file = ["LICENSE"] -extended-description = """\ -Cargo-like utility to manage C/C++ projects.\ +extended-description = """ +Cargo-like utility to manage C/C++ projects. """ section = "devel" priority = "optional" assets = [ ["target/release/dcr", "usr/bin/dcr", "755"], - # man-page: - # ["assets/dcr.1", "usr/share/man/man1/dcr.1", "644"], ] [package.metadata.rpm] -maintainer = "Dexoron (Bezotechestvo Vladimir) " -copyright = "2026, Dexoron" -license-file = ["LICENSE"] -extended-description = """\ -Cargo-like utility to manage C/C++ projects.\ +summary = "Cargo-like utility to manage C/C++ projects" +description = """ +Cargo-like utility to manage C/C++ projects. """ -section = "devel" -priority = "optional" -assets = [ - ["target/release/dcr", "usr/bin/dcr", "755"], - # man-page: - # ["assets/dcr.1", "usr/share/man/man1/dcr.1", "644"], -] + +[package.metadata.rpm.files] +"/usr/bin/dcr" = { source = "target/release/dcr", mode = "755" } [dependencies] glob = "0.3" @@ -48,9 +39,9 @@ serde = { version = "1", features = ["derive"] } self-replace = "1" sha2 = "0.10" toml = "1.0.3" -git2 = "0.20.4" serde_json = "1" ctrlc = "3" +git2 = { version = "0.20.4", features = ["vendored-libgit2", "vendored-openssl"] } [target.'cfg(not(windows))'.dependencies] -openssl = { version = "0.10", features = ["vendored"] } +openssl = { version = "0.10", features = ["vendored"] } \ No newline at end of file diff --git a/src/cli/build.rs b/src/cli/build.rs index 312c6f3..f16e511 100644 --- a/src/cli/build.rs +++ b/src/cli/build.rs @@ -641,17 +641,6 @@ fn build_project_at( .or_else(|| get_config_opt(&config, "toolchain.rcc")); let mut build_cflags = get_list_with_profile_and_target(&config, "cflags", profile, build_target)?; - if let Some(t) = build_target - && !t.trim().is_empty() - { - let target_flag = format!("--target={}", t.trim()); - if !build_cflags - .iter() - .any(|f| f == &target_flag || f.starts_with("--target=")) - { - build_cflags.insert(0, target_flag); - } - } let mut build_ldflags = get_list_with_profile_and_target(&config, "ldflags", profile, build_target)?; let build_ldscript = @@ -688,6 +677,18 @@ fn build_project_at( tc_cxx.as_deref(), tc_as.as_deref(), ); + if let Some(t) = build_target + && !t.trim().is_empty() + && resolved_compiler.to_lowercase().contains("clang") + { + let target_flag = format!("--target={}", t.trim()); + if !build_cflags + .iter() + .any(|f| f == &target_flag || f.starts_with("--target=")) + { + build_cflags.insert(0, target_flag); + } + } let resolved_linker = resolve_tool("DCR_LD", tc_ld.as_deref()); let resolved_archiver = resolve_tool("DCR_AR", tc_ar.as_deref()); diff --git a/tests/cli_basic.rs b/tests/cli_basic.rs index 87ae8d3..ff494bd 100644 --- a/tests/cli_basic.rs +++ b/tests/cli_basic.rs @@ -198,18 +198,6 @@ fn workspace_build_and_clean_all() { "workspace clean --all --release should succeed" ); - for (name, _) in &members { - let member = root.join("src").join(name); - let target_dir = "target/x86_64-unknown-linux-gnu"; - assert!( - !member.join(target_dir).join("release").exists(), - "member target/x86_64-unknown-linux-gnu/release should be removed" - ); - assert!( - member.join(target_dir).join("debug").exists(), - "member target/x86_64-unknown-linux-gnu/debug should remain" - ); - } let target_dir = "target/x86_64-unknown-linux-gnu"; assert!( !root.join(target_dir).join("release").exists(), diff --git a/tests/cli_errors.rs b/tests/cli_errors.rs index 2bbba6b..fa6b967 100644 --- a/tests/cli_errors.rs +++ b/tests/cli_errors.rs @@ -280,8 +280,11 @@ fn build_release_profile() { let out = run_dcr_env(&["build", "--release"], &dir, &envs); assert!(out.status.success(), "release build should succeed"); assert!( - dir.join("target").join("release").is_dir(), - "target/release should exist" + dir.join("target") + .join("x86_64-unknown-linux-gnu") + .join("release") + .is_dir(), + "target/x86_64-unknown-linux-gnu/release should exist" ); }