diff --git a/.github/ISSUE_TEMPLATE/01-bug-report.yml b/.github/ISSUE_TEMPLATE/01-bug-report.yml index 84995545..e6e6331b 100644 --- a/.github/ISSUE_TEMPLATE/01-bug-report.yml +++ b/.github/ISSUE_TEMPLATE/01-bug-report.yml @@ -6,115 +6,50 @@ body: - type: markdown attributes: value: | - # Console command & output formatting + # Configuration + - type: textarea + id: config + attributes: + label: mas config + description: The output of `mas config --markdown` + value: | + - - Use a multiline console block: start with ```` ```console ````, end with ```` ``` ````, each on its own line - - Prefix each non-console step (or comment) with two hashes & a space: `## …` - - Remove shell prompts; instead, prefix each console command with a dollar sign & a space: `$ …` - - Prefix each output line beginning with `#`, `$`, `%`, or `>` with an additional instance of that character: `##…`, `$$…`, `%%…`, or `>>…` - - Write all other output lines without any prefix: `…` + ### Output of `mas version` + - e.g.: + ### Output of `sw_vers -productVersion` + - ````text - ```console - ## In the Mac App Store GUI, … - $ mas list - 123 App 1 (4.5.6) - 124 App 2 (10.2) - ``` - ```` - - # Environment - - type: input - id: mas-version - attributes: - label: mas version - description: The output of `mas version` - placeholder: "example: 1.8.7" - validations: - required: true - - type: input - id: macos-version - attributes: - label: macOS version - description: The output of `sw_vers -productVersion` - placeholder: "example: 15.1.1" - validations: - required: true - - type: input - id: macos-build - attributes: - label: macOS build version - description: The output of `sw_vers -buildVersion` - placeholder: "example: 24B2091" - validations: - required: true - - type: input - id: processor - attributes: - label: Processor - description: The output of `sysctl -n machdep.cpu.brand_string` - placeholder: "example: Apple M1" - validations: - required: true - - type: dropdown - id: install-method - attributes: - label: mas installation method - options: - - Homebrew core (brew install mas) - - Homebrew custom tap (brew install mas-cli/tap/mas) - - GitHub Releases (https://github.com/mas-cli/mas/releases) - - Built from source - - Other - default: 0 - validations: - required: true - - type: textarea - id: install-details - attributes: - label: mas installation details - # yamllint disable rule:trailing-spaces - value: | - + ### Output of `sw_vers -buildVersion` + - + ### Output of `sysctl -n machdep.cpu.brand_string` + - + ### Installation method (delete the incorrect ones) - - # yamllint enable rule:trailing-spaces + - Homebrew core (via `brew install mas`) + - Homebrew custom tap (via `brew install mas-cli/tap/mas`) + - GitHub Releases (from ) + - Built from source (provide info about build) + - Other validations: - required: false + required: true - type: markdown attributes: value: | # Issue - type: textarea - id: expected-behavior + id: description attributes: - label: Expected behavior + label: Bug description placeholder: - Prefer copied, pasted & formatted commands & output in a multiline console block (as instructed - above) instead of screenshots - validations: - required: true - - type: textarea - id: actual-behavior - attributes: - label: Actual behavior - placeholder: - Prefer copied, pasted & formatted commands & output in a multiline console block (as instructed - above) instead of screenshots + Include expected & actual output, as well as other pertinent info. validations: required: true - type: textarea @@ -122,18 +57,38 @@ body: attributes: label: Steps to reproduce description: | - Copy, paste & format commands & output in the multiline console block (as instructed above) that reproduce the bug + Copy, paste & format commands & output in the console block (as instructed below) value: | ```console ``` validations: required: true - - type: textarea - id: context + - type: markdown attributes: - label: Additional context - placeholder: "example: Does the bug occur in other mas or macOS versions?" - validations: - required: false + value: | + # Console command & output formatting instructions + + Provide console commands & output as copied, pasted & formatted text, instead of as screenshots. + + If long descriptive text or screenshots of dialogs or apps are necessary, provide them between console blocks. + + Format commands & output as follows (where `…` is a placeholder): + + - Use a multiline console block: start with ```` ```console ````, end with ```` ``` ````, each on its own line + - Prefix each non-console step (or comment) with two hashes & a space: `## …` + - Remove shell prompts; instead, prefix each console command with a dollar sign & a space: `$ …` + - Prefix each output line beginning with `#`, `$`, `%`, or `>` with an additional instance of that character: `##…`, `$$…`, `%%…`, or `>>…` + - Write all other output lines without any prefix: `…` + + e.g.: + + ````text + ```console + ## In the Mac App Store GUI, … + $ mas list + 123 App 1 (4.5.6) + 124 App 2 (10.2) + ``` + ```` diff --git a/.github/workflows/build-test.yml b/.github/workflows/build-test.yml index c9e5989f..d35dd3f3 100644 --- a/.github/workflows/build-test.yml +++ b/.github/workflows/build-test.yml @@ -35,7 +35,7 @@ jobs: run: script/bootstrap - name: Build - run: script/build + run: script/build build-test - name: Test run: script/test diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml index 2df87f88..9c4f1605 100644 --- a/.github/workflows/codeql.yml +++ b/.github/workflows/codeql.yml @@ -39,7 +39,7 @@ jobs: if: matrix.language == 'swift' shell: bash run: | - script/build + script/build codeql - name: Perform CodeQL Analysis uses: github/codeql-action/analyze@v3 diff --git a/.github/workflows/tag-pushed.yml b/.github/workflows/tag-pushed.yml index 99a0aac3..6b7256c1 100644 --- a/.github/workflows/tag-pushed.yml +++ b/.github/workflows/tag-pushed.yml @@ -57,7 +57,7 @@ jobs: - name: 📦 Build universal executable & package it in an installer run: | sudo xcode-select -s /Applications/Xcode_16.2.app/Contents/Developer - script/package + script/package package - name: 🚰 Bump custom tap formula env: diff --git a/Sources/mas/Commands/Config.swift b/Sources/mas/Commands/Config.swift new file mode 100644 index 00000000..275b487b --- /dev/null +++ b/Sources/mas/Commands/Config.swift @@ -0,0 +1,94 @@ +// +// Config.swift +// mas +// +// Created by Ross Goldberg on 2025-01-03. +// Copyright © 2024 mas-cli. All rights reserved. +// + +import ArgumentParser +import CommerceKit + +private let unknown = "unknown" + +extension MAS { + /// Displays mas config & related system info. + struct Config: ParsableCommand { + static let configuration = CommandConfiguration( + abstract: "Display mas config & related system info" + ) + + @Flag(help: "Output as Markdown") + var markdown = false + + /// Runs the command. + func run() throws { + if markdown { + print("```text") + } + print( + """ + mas ▁▁▁▁ \(Package.version) + from ▁▁▁ \(Package.installMethod) + origin ▁ \(Package.gitOrigin) + rev ▁▁▁▁ \(Package.gitRevision) + swift ▁▁ \(Package.swiftVersion) + driver ▁ \(Package.swiftDriverVersion) + region ▁ \(Storefront.isoRegion?.alpha2 ?? unknown) + macos ▁▁ \( + ProcessInfo.processInfo.operatingSystemVersionString.dropFirst(8) + .replacingOccurrences(of: "Build ", with: "") + ) + mac ▁▁▁▁ \(macModel()) + cpu ▁▁▁▁ \(cpuBrandString()) + arch ▁▁▁ \(architecture()) + """ + ) + if markdown { + print("```") + } + } + } +} + +private func macModel() -> String { + var name = [CTL_HW, HW_MODEL] + + var size = 0 + guard sysctl(&name, u_int(name.count), nil, &size, nil, 0) == 0 else { + perror("sysctl") + return unknown + } + + var buffer = [CChar](repeating: 0, count: size) + guard sysctl(&name, u_int(name.count), &buffer, &size, nil, 0) == 0 else { + perror("sysctl") + return unknown + } + + return String(cString: buffer) +} + +private func cpuBrandString() -> String { + configValue("machdep.cpu.brand_string") +} + +private func architecture() -> String { + configValue("hw.machine") +} + +private func configValue(_ name: String) -> String { + var size = 0 + guard sysctlbyname(name, nil, &size, nil, 0) == 0 else { + perror("sysctlbyname") + return unknown + } + + var buffer = [CChar](repeating: 0, count: size) + guard sysctlbyname(name, &buffer, &size, nil, 0) == 0 else { + perror("sysctlbyname") + return unknown + } + + return String(cString: buffer) +} diff --git a/Sources/mas/MAS.swift b/Sources/mas/MAS.swift index 9dc9abaa..6c56bec4 100644 --- a/Sources/mas/MAS.swift +++ b/Sources/mas/MAS.swift @@ -15,6 +15,7 @@ struct MAS: ParsableCommand { abstract: "Mac App Store command-line interface", subcommands: [ Account.self, + Config.self, Home.self, Info.self, Install.self, diff --git a/contrib/completion/mas.fish b/contrib/completion/mas.fish index 28738a17..238d4dc2 100644 --- a/contrib/completion/mas.fish +++ b/contrib/completion/mas.fish @@ -25,6 +25,10 @@ complete -c mas -f ### account complete -c mas -n "__fish_use_subcommand" -f -a account -d "Display the Apple ID signed in in the Mac App Store" complete -c mas -n "__fish_seen_subcommand_from help" -xa "account" +### config +complete -c mas -n "__fish_use_subcommand" -f -a config -d "Display mas config & related system info" +complete -c mas -n "__fish_seen_subcommand_from help" -xa "config" +complete -c mas -n "__fish_seen_subcommand_from config" -l markdown -d "Output as Markdown" ### help complete -c mas -n "__fish_use_subcommand" -f -a help -d "Display general or command-specific help" complete -c mas -n "__fish_seen_subcommand_from help" -xa "help" diff --git a/script/build b/script/build index 809de60a..8dbf8922 100755 --- a/script/build +++ b/script/build @@ -10,6 +10,6 @@ printf $'==> 🏗️ Building mas %s\n' "$(script/version)" -script/generate_version_info_for_swift +script/generate_package_swift "${1:-}" -swift build --configuration release "${@}" +swift build --configuration release "${@:2}" diff --git a/script/generate_package_swift b/script/generate_package_swift new file mode 100755 index 00000000..172bef6b --- /dev/null +++ b/script/generate_package_swift @@ -0,0 +1,22 @@ +#!/bin/zsh -Ndefgku +# +# script/generate_package_swift +# mas +# +# Generates a file to provide the mas version to Swift code. +# + +. "${0:a:h}/_setup_script" + +# Write version to Swift singleton +cat <Sources/mas/Package.swift +/// Generated by \`script/generate_package_swift\`. +enum Package { + static let version = "$(script/version)" + static let installMethod = "${1:-unknown}" + static let gitOrigin = "$(git remote get-url origin)" + static let gitRevision = "$(git rev-parse HEAD)" + static let swiftVersion = "$(printf %s "${${$(swift --version 2>/dev/null)#Apple Swift version }%%$'\n'*}")" + static let swiftDriverVersion = "$(printf %s "${${$((swift --version 3>&2 2>&1 1>&3) 2>/dev/null)#swift-driver version: }% }")" +} +EOF diff --git a/script/generate_version_info_for_swift b/script/generate_version_info_for_swift deleted file mode 100755 index c29e2741..00000000 --- a/script/generate_version_info_for_swift +++ /dev/null @@ -1,17 +0,0 @@ -#!/bin/zsh -Ndefgku -# -# script/generate_version_info_for_swift -# mas -# -# Generates a file to provide the mas version to Swift code. -# - -. "${0:a:h}/_setup_script" - -# Write version to Swift singleton -cat <Sources/mas/Package.swift -/// Generated by \`script/generate_version_info_for_swift\`. -enum Package { - static let version = "$(script/version)" -} -EOF diff --git a/script/lint b/script/lint index 9632678e..25d66286 100755 --- a/script/lint +++ b/script/lint @@ -14,7 +14,7 @@ printf $'==> 🚨 Linting mas %s\n' "$(script/version)" -script/generate_version_info_for_swift +script/generate_package_swift for linter in git markdownlint periphery shellcheck swift-format swiftformat swiftlint yamllint; do if ! command -v "${linter}" >/dev/null; then @@ -38,7 +38,7 @@ for source in Package.swift Sources Tests; do done printf -- $'--> 🐚 ShellCheck\n' -shellcheck -s bash -o all -e SC1088,SC2296,SC2301,SC2312 -a -P SCRIPTDIR script/**/*(.) +shellcheck -s bash -o all -e SC1088,SC1102,SC2296,SC2299,SC2300,SC2301,SC2312 -a -P SCRIPTDIR script/**/*(.) ((exit_code |= ${?})) printf -- $'--> 〽️ Markdown\n' diff --git a/script/package b/script/package index 1c1bba9a..1cbbe827 100755 --- a/script/package +++ b/script/package @@ -8,7 +8,7 @@ . "${0:a:h}/_setup_script" -script/build --arch arm64 --arch x86_64 +script/build "${1:-}" --arch arm64 --arch x86_64 build_dir=.build destination_root="${build_dir}/destination" diff --git a/script/test b/script/test index 9930ce97..95b6afd7 100755 --- a/script/test +++ b/script/test @@ -10,7 +10,7 @@ printf $'==> ✅ Testing mas %s\n' "$(script/version)" -script/generate_version_info_for_swift +script/generate_package_swift script -q /dev/null swift test "${@}" | (grep -vxE $'Test Suite \'.+\' (?:started|passed) at \\d{4}-\\d{2}-\\d{2} \\d{2}:\\d{2}:\\d{2}\\.\\d{3}\\.?\\r|Test Case \'-\\[.+\\]\' (?:started|passed \\(\\d+\\.\\d+ seconds\\))\\.\\r|\\t Executed \\d+ tests?, with 0 failures \\(0 unexpected\\) in \\d+\\.\\d+ \\(\\d+\\.\\d+\\) seconds\\r' || true)