name: Release on: workflow_dispatch: inputs: tag: description: "Tag to release (e.g., v1.0.1)" required: true type: string permissions: contents: write actions: write concurrency: group: release-${{ inputs.tag }} cancel-in-progress: true jobs: build-core: runs-on: ubuntu-latest strategy: matrix: arch: [amd64, arm64] defaults: run: working-directory: core env: TAG: ${{ inputs.tag }} steps: - name: Checkout uses: actions/checkout@v4 with: ref: ${{ inputs.tag }} fetch-depth: 0 - name: Set up Go uses: actions/setup-go@v5 with: go-version-file: ./core/go.mod - name: Format check run: | if [ "$(gofmt -s -l . | wc -l)" -gt 0 ]; then echo "The following files are not formatted:" gofmt -s -l . exit 1 fi - name: Run tests run: go test -v ./... - name: Build dankinstall (${{ matrix.arch }}) env: GOOS: linux CGO_ENABLED: 0 GOARCH: ${{ matrix.arch }} run: | set -eux cd cmd/dankinstall go build -trimpath -ldflags "-s -w -X main.Version=${TAG}" \ -o ../../dankinstall-${{ matrix.arch }} cd ../.. gzip -9 -k dankinstall-${{ matrix.arch }} sha256sum dankinstall-${{ matrix.arch }}.gz > dankinstall-${{ matrix.arch }}.gz.sha256 - name: Build dms (${{ matrix.arch }}) env: GOOS: linux CGO_ENABLED: 0 GOARCH: ${{ matrix.arch }} run: | set -eux cd cmd/dms go build -trimpath -ldflags "-s -w -X main.Version=${TAG}" \ -o ../../dms-${{ matrix.arch }} cd ../.. gzip -9 -k dms-${{ matrix.arch }} sha256sum dms-${{ matrix.arch }}.gz > dms-${{ matrix.arch }}.gz.sha256 - name: Generate shell completions if: matrix.arch == 'amd64' run: | set -eux chmod +x dms-amd64 ./dms-amd64 completion bash > completion.bash ./dms-amd64 completion fish > completion.fish ./dms-amd64 completion zsh > completion.zsh - name: Build dms-distropkg (${{ matrix.arch }}) env: GOOS: linux CGO_ENABLED: 0 GOARCH: ${{ matrix.arch }} run: | set -eux cd cmd/dms go build -trimpath -tags distro_binary -ldflags "-s -w -X main.Version=${TAG}" \ -o ../../dms-distropkg-${{ matrix.arch }} cd ../.. gzip -9 -k dms-distropkg-${{ matrix.arch }} sha256sum dms-distropkg-${{ matrix.arch }}.gz > dms-distropkg-${{ matrix.arch }}.gz.sha256 - name: Upload artifacts (${{ matrix.arch }}) if: matrix.arch == 'arm64' uses: actions/upload-artifact@v4 with: name: core-assets-${{ matrix.arch }} path: | core/dankinstall-${{ matrix.arch }}.gz core/dankinstall-${{ matrix.arch }}.gz.sha256 core/dms-${{ matrix.arch }}.gz core/dms-${{ matrix.arch }}.gz.sha256 core/dms-distropkg-${{ matrix.arch }}.gz core/dms-distropkg-${{ matrix.arch }}.gz.sha256 if-no-files-found: error - name: Upload artifacts with completions if: matrix.arch == 'amd64' uses: actions/upload-artifact@v4 with: name: core-assets-${{ matrix.arch }} path: | core/dankinstall-${{ matrix.arch }}.gz core/dankinstall-${{ matrix.arch }}.gz.sha256 core/dms-${{ matrix.arch }}.gz core/dms-${{ matrix.arch }}.gz.sha256 core/dms-distropkg-${{ matrix.arch }}.gz core/dms-distropkg-${{ matrix.arch }}.gz.sha256 core/completion.bash core/completion.fish core/completion.zsh if-no-files-found: error # update-versions: # runs-on: ubuntu-latest # needs: build-core # steps: # - name: Create GitHub App token # id: app_token # uses: actions/create-github-app-token@v1 # with: # app-id: ${{ secrets.APP_ID }} # private-key: ${{ secrets.APP_PRIVATE_KEY }} # - name: Checkout # uses: actions/checkout@v4 # with: # token: ${{ steps.app_token.outputs.token }} # fetch-depth: 0 # - name: Update VERSION # env: # GH_TOKEN: ${{ steps.app_token.outputs.token }} # run: | # set -euo pipefail # git config user.name "dms-ci[bot]" # git config user.email "dms-ci[bot]@users.noreply.github.com" # version="${GITHUB_REF#refs/tags/}" # echo "Updating to version: $version" # echo "${version}" > quickshell/VERSION # git add quickshell/VERSION # if ! git diff --cached --quiet; then # git commit -m "chore: bump version to $version" # git pull --rebase origin master # git push https://x-access-token:${GH_TOKEN}@github.com/${{ github.repository }}.git HEAD:master # fi # git tag -f "${version}" # git push -f https://x-access-token:${GH_TOKEN}@github.com/${{ github.repository }}.git "${version}" release: runs-on: ubuntu-24.04 needs: [build-core] #, update-versions] env: TAG: ${{ inputs.tag }} steps: - name: Checkout uses: actions/checkout@v4 with: ref: ${{ inputs.tag }} fetch-depth: 0 - name: Fetch updated tag after version bump run: | git fetch origin --force tag ${TAG} git checkout ${TAG} - name: Download core artifacts uses: actions/download-artifact@v4 with: pattern: core-assets-* merge-multiple: true path: ./_core_assets - name: Generate Changelog id: changelog run: | set -e PREVIOUS_TAG=$(git describe --tags --abbrev=0 "${TAG}^" 2>/dev/null || echo "") if [ -z "$PREVIOUS_TAG" ]; then CHANGELOG=$(git log --oneline --pretty=format:"%an|%s (%h)" | grep -v "^github-actions\[bot\]|" | sed 's/^[^|]*|/- /' | head -50) else CHANGELOG=$(git log --oneline --pretty=format:"%an|%s (%h)" "${PREVIOUS_TAG}..${TAG}" | grep -v "^github-actions\[bot\]|" | sed 's/^[^|]*|/- /') fi cat > RELEASE_BODY.md << 'EOF' ## Installation ```bash curl -fsSL https://install.danklinux.com | sh ``` ## Assets ### Complete Packages - **`dms-full-amd64.tar.gz`** - Complete package for x86_64 systems (CLI binaries + QML source + shell completions + installation guide) - **`dms-full-arm64.tar.gz`** - Complete package for ARM64 systems (CLI binaries + QML source + shell completions + installation guide) ### Individual Components - **`dms-cli-amd64.gz`** - DMS CLI binary for x86_64 systems - **`dms-cli-arm64.gz`** - DMS CLI binary for ARM64 systems - **`dms-distropkg-amd64.gz`** - DMS CLI binary built with distro_package tag for AMD64 systems - **`dms-distropkg-arm64.gz`** - DMS CLI binary built with distro_package tag for ARM64 systems - **`dankinstall-amd64.gz`** - Installer binary for x86_64 systems - **`dankinstall-arm64.gz`** - Installer binary for ARM64 systems - **`dms-qml.tar.gz`** - QML source code only ### Checksums - **`*.sha256`** - SHA256 checksums for verifying download integrity **Installation:** Extract the `dms-full-*.tar.gz` package for your architecture and follow the `INSTALL.md` instructions inside. --- EOF cat >> RELEASE_BODY.md << EOF ## What's Changed $CHANGELOG **Full Changelog**: https://github.com/${{ github.repository }}/compare/${PREVIOUS_TAG}...${TAG} EOF echo "changelog<> $GITHUB_OUTPUT cat RELEASE_BODY.md >> $GITHUB_OUTPUT echo "EOF" >> $GITHUB_OUTPUT - name: Prepare release assets run: | set -euxo pipefail mkdir -p _release_assets # Copy core binaries and rename dms-*.gz to dms-cli-*.gz for file in _core_assets/dms-*.gz*; do if [ -f "$file" ]; then basename=$(basename "$file") if [[ "$basename" == dms-distropkg-* ]]; then cp "$file" "_release_assets/$basename" else newname=$(echo "$basename" | sed 's/^dms-/dms-cli-/') cp "$file" "_release_assets/$newname" fi fi done # Copy dankinstall binaries cp _core_assets/dankinstall-*.gz* _release_assets/ # Copy completions cp _core_assets/completion.* _release_assets/ 2>/dev/null || true # Create QML source package (exclude build artifacts and git files) # Copy root LICENSE and CONTRIBUTING.md to quickshell/ for packaging cp LICENSE CONTRIBUTING.md quickshell/ # Tar the CONTENTS of quickshell/, not the directory itself (cd quickshell && tar --exclude='.git' \ --exclude='.github' \ --exclude='*.tar.gz' \ -czf ../_release_assets/dms-qml.tar.gz .) # Generate checksum for QML package (cd _release_assets && sha256sum dms-qml.tar.gz > dms-qml.tar.gz.sha256) # Create full packages for each architecture for arch in amd64 arm64; do mkdir -p _temp_full/dms mkdir -p _temp_full/bin mkdir -p _temp_full/completions # Extract QML source tar -xzf _release_assets/dms-qml.tar.gz -C _temp_full/dms # Add CLI binaries if [ -f "_core_assets/dms-${arch}.gz" ]; then gunzip -c "_core_assets/dms-${arch}.gz" > _temp_full/bin/dms chmod +x _temp_full/bin/dms fi if [ -f "_core_assets/dms-distropkg-${arch}.gz" ]; then gunzip -c "_core_assets/dms-distropkg-${arch}.gz" > _temp_full/bin/dms-distropkg chmod +x _temp_full/bin/dms-distropkg fi # Add shell completions for completion in _core_assets/completion.*; do if [ -f "$completion" ]; then cp "$completion" _temp_full/completions/ fi done # Copy docs directory if [ -d "docs" ]; then cp -r docs _temp_full/ fi # Create installation guide cat > _temp_full/INSTALL.md << 'EOFINSTALL' # DankMaterialShell Installation ## Requirements - Wayland compositor (niri or Hyprland recommended) - Quickshell framework - Qt6 ## Installation Steps 1. **Install quickshell assets:** ```bash mkdir -p ~/.config/quickshell cp -r dms ~/.config/quickshell/ ``` 2. **Install the DMS CLI binaries:** ```bash sudo install -m 755 bin/dms /usr/local/bin/dms ``` 3. **Install shell completions (optional):** ```bash # Bash sudo install -m 644 completions/completion.bash /usr/share/bash-completion/completions/dms # Fish sudo install -m 644 completions/completion.fish /usr/share/fish/vendor_completions.d/dms.fish # Zsh sudo install -m 644 completions/completion.zsh /usr/share/zsh/site-functions/_dms ``` 4. **Start the shell:** ```bash dms run ``` ## Configuration - Settings are stored in `~/.config/DankMaterialShell/settings.json` - Plugins go in `~/.config/DankMaterialShell/plugins/` - See the documentation in the `dms/` directory for more details ## Troubleshooting - Run with verbose output: `DMS_LOG_LEVEL=debug dms run` - Ensure all dependencies are installed EOFINSTALL # Create the full package (cd _temp_full && tar -czf "../_release_assets/dms-full-${arch}.tar.gz" .) # Generate checksum (cd _release_assets && sha256sum "dms-full-${arch}.tar.gz" > "dms-full-${arch}.tar.gz.sha256") # Cleanup rm -rf _temp_full done - name: Create GitHub Release uses: softprops/action-gh-release@v2 with: tag_name: ${{ env.TAG }} name: Release ${{ env.TAG }} body: ${{ steps.changelog.outputs.changelog }} files: _release_assets/** draft: false prerelease: ${{ contains(env.TAG, '-') }} env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} # trigger-obs-update: # runs-on: ubuntu-latest # needs: release # env: # TAG: ${{ inputs.tag }} # steps: # - name: Checkout # uses: actions/checkout@v4 # with: # ref: ${{ inputs.tag }} # - name: Install OSC # run: | # sudo apt-get update # sudo apt-get install -y osc # mkdir -p ~/.config/osc # cat > ~/.config/osc/oscrc << EOF # [general] # apiurl = https://api.opensuse.org # [https://api.opensuse.org] # user = ${{ secrets.OBS_USERNAME }} # pass = ${{ secrets.OBS_PASSWORD }} # EOF # chmod 600 ~/.config/osc/oscrc # - name: Update OBS packages # run: | # cd distro # bash scripts/obs-upload.sh dms "Update to ${TAG}" # trigger-ppa-update: # runs-on: ubuntu-latest # needs: release # env: # TAG: ${{ inputs.tag }} # steps: # - name: Checkout # uses: actions/checkout@v4 # with: # ref: ${{ inputs.tag }} # - name: Install build dependencies # run: | # sudo apt-get update # sudo apt-get install -y \ # debhelper \ # devscripts \ # dput \ # lftp \ # build-essential \ # fakeroot \ # dpkg-dev # - name: Configure GPG # env: # GPG_KEY: ${{ secrets.GPG_PRIVATE_KEY }} # run: | # echo "$GPG_KEY" | gpg --import # GPG_KEY_ID=$(gpg --list-secret-keys --keyid-format LONG | grep sec | awk '{print $2}' | cut -d'/' -f2) # echo "DEBSIGN_KEYID=$GPG_KEY_ID" >> $GITHUB_ENV # - name: Upload to PPA # run: | # cd distro/ubuntu/ppa # bash create-and-upload.sh ../dms dms questing # copr-build: # runs-on: ubuntu-latest # needs: release # env: # TAG: ${{ inputs.tag }} # steps: # - name: Checkout repository # uses: actions/checkout@v4 # with: # ref: ${{ inputs.tag }} # - name: Determine version # id: version # run: | # VERSION="${TAG#v}" # echo "version=$VERSION" >> $GITHUB_OUTPUT # echo "Building DMS stable version: $VERSION" # - name: Setup build environment # run: | # sudo apt-get update # sudo apt-get install -y rpm wget curl jq gzip # mkdir -p ~/rpmbuild/{BUILD,BUILDROOT,RPMS,SOURCES,SPECS,SRPMS} # - name: Download release assets # run: | # VERSION="${{ steps.version.outputs.version }}" # cd ~/rpmbuild/SOURCES # wget "https://github.com/AvengeMedia/DankMaterialShell/releases/download/v${VERSION}/dms-qml.tar.gz" || { # echo "Failed to download dms-qml.tar.gz for v${VERSION}" # exit 1 # } # - name: Generate stable spec file # run: | # VERSION="${{ steps.version.outputs.version }}" # CHANGELOG_DATE="$(date '+%a %b %d %Y')" # cat > ~/rpmbuild/SPECS/dms.spec <<'SPECEOF' # # Spec for DMS stable releases - Generated by GitHub Actions # %global debug_package %{nil} # %global version VERSION_PLACEHOLDER # %global pkg_summary DankMaterialShell - Material 3 inspired shell for Wayland compositors # Name: dms # Version: %{version} # Release: 1%{?dist} # Summary: %{pkg_summary} # License: MIT # URL: https://github.com/AvengeMedia/DankMaterialShell # Source0: dms-qml.tar.gz # BuildRequires: gzip # BuildRequires: wget # BuildRequires: systemd-rpm-macros # Requires: (quickshell or quickshell-git) # Requires: accountsservice # Requires: dms-cli = %{version}-%{release} # Requires: dgop # Recommends: cava # Recommends: cliphist # Recommends: danksearch # Recommends: matugen # Recommends: wl-clipboard # Recommends: NetworkManager # Recommends: qt6-qtmultimedia # Suggests: qt6ct # %description # DankMaterialShell (DMS) is a modern Wayland desktop shell built with Quickshell # and optimized for the niri and hyprland compositors. Features notifications, # app launcher, wallpaper customization, and fully customizable with plugins. # Includes auto-theming for GTK/Qt apps with matugen, 20+ customizable widgets, # process monitoring, notification center, clipboard history, dock, control center, # lock screen, and comprehensive plugin system. # %package -n dms-cli # Summary: DankMaterialShell CLI tool # License: MIT # URL: https://github.com/AvengeMedia/DankMaterialShell # %description -n dms-cli # Command-line interface for DankMaterialShell configuration and management. # Provides native DBus bindings, NetworkManager integration, and system utilities. # %prep # %setup -q -c -n dms-qml # # Download architecture-specific binaries during build # case "%{_arch}" in # x86_64) # ARCH_SUFFIX="amd64" # ;; # aarch64) # ARCH_SUFFIX="arm64" # ;; # *) # echo "Unsupported architecture: %{_arch}" # exit 1 # ;; # esac # wget -O %{_builddir}/dms-cli.gz "https://github.com/AvengeMedia/DankMaterialShell/releases/latest/download/dms-distropkg-${ARCH_SUFFIX}.gz" || { # echo "Failed to download dms-cli for architecture %{_arch}" # exit 1 # } # gunzip -c %{_builddir}/dms-cli.gz > %{_builddir}/dms-cli # chmod +x %{_builddir}/dms-cli # %build # %install # install -Dm755 %{_builddir}/dms-cli %{buildroot}%{_bindir}/dms # install -d %{buildroot}%{_datadir}/bash-completion/completions # install -d %{buildroot}%{_datadir}/zsh/site-functions # install -d %{buildroot}%{_datadir}/fish/vendor_completions.d # %{_builddir}/dms-cli completion bash > %{buildroot}%{_datadir}/bash-completion/completions/dms || : # %{_builddir}/dms-cli completion zsh > %{buildroot}%{_datadir}/zsh/site-functions/_dms || : # %{_builddir}/dms-cli completion fish > %{buildroot}%{_datadir}/fish/vendor_completions.d/dms.fish || : # install -Dm644 assets/systemd/dms.service %{buildroot}%{_userunitdir}/dms.service # install -Dm644 assets/dms-open.desktop %{buildroot}%{_datadir}/applications/dms-open.desktop # install -Dm644 assets/danklogo.svg %{buildroot}%{_datadir}/icons/hicolor/scalable/apps/danklogo.svg # install -dm755 %{buildroot}%{_datadir}/quickshell/dms # cp -r %{_builddir}/dms-qml/* %{buildroot}%{_datadir}/quickshell/dms/ # rm -rf %{buildroot}%{_datadir}/quickshell/dms/.git* # rm -f %{buildroot}%{_datadir}/quickshell/dms/.gitignore # rm -rf %{buildroot}%{_datadir}/quickshell/dms/.github # rm -rf %{buildroot}%{_datadir}/quickshell/dms/distro # echo "%{version}" > %{buildroot}%{_datadir}/quickshell/dms/VERSION # %posttrans # if [ -d "%{_sysconfdir}/xdg/quickshell/dms" ]; then # rmdir "%{_sysconfdir}/xdg/quickshell/dms" 2>/dev/null || true # rmdir "%{_sysconfdir}/xdg/quickshell" 2>/dev/null || true # rmdir "%{_sysconfdir}/xdg" 2>/dev/null || true # fi # # Signal running DMS instances to reload # pkill -USR1 -x dms >/dev/null 2>&1 || : # %files # %license LICENSE # %doc README.md CONTRIBUTING.md # %{_datadir}/quickshell/dms/ # %{_userunitdir}/dms.service # %{_datadir}/applications/dms-open.desktop # %{_datadir}/icons/hicolor/scalable/apps/danklogo.svg # %files -n dms-cli # %{_bindir}/dms # %{_datadir}/bash-completion/completions/dms # %{_datadir}/zsh/site-functions/_dms # %{_datadir}/fish/vendor_completions.d/dms.fish # %changelog # * CHANGELOG_DATE_PLACEHOLDER AvengeMedia - VERSION_PLACEHOLDER-1 # - Stable release VERSION_PLACEHOLDER # - Built from GitHub release # SPECEOF # sed -i "s/VERSION_PLACEHOLDER/${VERSION}/g" ~/rpmbuild/SPECS/dms.spec # sed -i "s/CHANGELOG_DATE_PLACEHOLDER/${CHANGELOG_DATE}/g" ~/rpmbuild/SPECS/dms.spec # - name: Build SRPM # id: build # run: | # cd ~/rpmbuild/SPECS # rpmbuild -bs dms.spec # SRPM=$(ls ~/rpmbuild/SRPMS/*.src.rpm | tail -n 1) # SRPM_NAME=$(basename "$SRPM") # echo "srpm_path=$SRPM" >> $GITHUB_OUTPUT # echo "srpm_name=$SRPM_NAME" >> $GITHUB_OUTPUT # echo "SRPM built: $SRPM_NAME" # - name: Upload SRPM artifact # uses: actions/upload-artifact@v4 # with: # name: dms-stable-srpm-${{ steps.version.outputs.version }} # path: ${{ steps.build.outputs.srpm_path }} # retention-days: 90 # - name: Install Copr CLI # run: | # sudo apt-get install -y python3-pip # pip3 install copr-cli # mkdir -p ~/.config # cat > ~/.config/copr << EOF # [copr-cli] # login = ${{ secrets.COPR_LOGIN }} # username = avengemedia # token = ${{ secrets.COPR_TOKEN }} # copr_url = https://copr.fedorainfracloud.org # EOF # chmod 600 ~/.config/copr # - name: Upload to Copr # run: | # SRPM="${{ steps.build.outputs.srpm_path }}" # VERSION="${{ steps.version.outputs.version }}" # echo "Uploading SRPM to avengemedia/dms..." # BUILD_OUTPUT=$(copr-cli build avengemedia/dms "$SRPM" --nowait 2>&1) # echo "$BUILD_OUTPUT" # BUILD_ID=$(echo "$BUILD_OUTPUT" | grep -oP 'Build was added to.*\K[0-9]+' || echo "unknown") # if [ "$BUILD_ID" != "unknown" ]; then # echo "Build submitted: https://copr.fedorainfracloud.org/coprs/avengemedia/dms/build/$BUILD_ID/" # fi