Repository navigation
Conversation
Merge Main pulls into Develop
Moved the MgPermissionType, MgTenantID, and MgClientID assignments above the module checks so the permission type is set when the Files check tests it.
- AGENTS.md: changelog, file encoding and line ending, safety, and code rules for AI assistants. CLAUDE.md points to it. - .gitattributes: pin every text file to LF so checkouts match the repository regardless of core.autocrlf. - ScriptMessage.psm1: remove the UTF-8 byte order mark; the file is pure ASCII.
- Research_Notes/: PowerShell language behavior, file encoding and line endings, and Microsoft Graph behavior, with every claim labelled by its evidence (measured, from source, from documentation, or unverified). - AGENTS.md: rules for writing research notes, and keep links to them out of changelog entries.
The To, CC, and BCC check converted the raw parameters to strings. A one-item array holding a PSCustomObject converts to an empty string, so a valid single recipient read from a JSON config was rejected. The check now runs on the converted recipients and requires at least one non-blank address, which also rejects recipients whose addresses are all blank. - Send-ScriptMessage.ps1: check the converted recipients instead of the raw parameters. - Tests/Send-ScriptMessage.Tests.ps1: first Pester test (Pester 5 or later), covering accepted and rejected recipient shapes with Microsoft Graph mocked. - CHANGELOG.md: new 1.1.1 section (Unreleased) for the fix.
- Tests.yml: lint the workflows (actionlint) and run the Pester suite under Windows PowerShell 5.1 and PowerShell 7 on pushes, pull requests, and when called by the release workflow. - Release.yml: replaces PSGallery.yml. A pushed version tag is checked (annotated, matches the manifest, dated changelog section, on main or on develop for a prerelease), tested, built once, published to the PowerShell Gallery from the psgallery environment, and only then released on GitHub with the same package attached. - Tests/Invoke-Tests.ps1: runs the suite in both editions and exits non-zero on any failure; can use a pinned Pester version saved on demand. - Tests/ScriptMessage.Module.Tests.ps1: the manifest is valid, exports match the Public folder, and PSScriptAnalyzer reports no errors.
… process - RELEASING.md: versioning rules (Semantic Versioning after 1.1.0, the public contract, hard cases), the Simple Modified Gitflow branch rules, the tag-triggered release steps, hotfixes, prereleases, and the repository settings that enforce them. - CONTRIBUTING.md and .github/pull_request_template.md: everyday workflow, release classification, and a changelog and test checklist for pull requests. - CHANGELOG.md: Keep a Changelog preamble, with the unreleased fix moved under [Unreleased] and Fixed. - AGENTS.md: the changelog uses [Unreleased] and the Keep a Changelog categories; a release is an annotated tag handled by Release.yml; text files are UTF-8 without a BOM, and PowerShell files are ASCII only. - README.md: a Versioning section replaces the public preview note, and the branching paragraph links CONTRIBUTING.md and RELEASING.md. - ScriptMessage.psd1: PSEdition_Desktop, PSEdition_Core, and Windows gallery tags, and the license and release notes links point at main. - Research_Notes/File-Encoding-And-Line-Endings.md: the ASCII rule covers PowerShell files, and how config files are read on 5.1 is unverified.
The Chat case created the message hashtable only inside its attachment branch, so a chat with no attachments indexed into a null array when adding members and sent nothing, reporting the error in the result. A chat sent in the same call as mail worked only because the Mail case left the hashtable behind. Build the message and convert the body before the attachment branch, which also stops the mail message object from leaking into the chat. Adds Pester coverage for one-on-one chats, group chats, and mail plus chat in a single call. None of it contacts a tenant.
The chat attachment upload encoded the filename with [System.Web.HttpUtility]::UrlEncode. Windows PowerShell 5.1 does not always have that type loaded, so a chat with an attachment could fail and send nothing. Form encoding also turned each space into a plus sign, which a URL path reads literally. Use [uri]::EscapeDataString, which needs no extra assembly in either edition and encodes a space as %20. - MicrosoftGraph.ps1: escape the upload filename with EscapeDataString. - Tests/Send-ScriptMessage.Tests.ps1: a one-on-one chat with an attachment checks the upload path, and mail with one and two attachments checks that every attachment reaches Send-MgUserMail. None of it contacts a tenant. - CHANGELOG.md: two Fixed entries, one for the 5.1 failure and one for spaces in filenames. - Research_Notes/PowerShell-Language-Behavior.md: the measured 5.1 failure and why it can look intermittent.
… chat-only setups Connect-ScriptMessage checked for Microsoft.Graph.Users.Actions on every Microsoft Graph connection, repeating the per-message-type module checks in Connect-ScriptMessage_MicrosoftGraph, so a configuration that allows only Chat failed without that module. The check never shipped in a release. Remove it, and add tests for a chat-only configuration and a configuration that allows Mail.
With application permissions, Send-ScriptMessage connects to Microsoft Graph before every send, replacing any connection the calling script made itself. Disconnecting afterwards leaves that script with no connection, so its next Graph command fails with "Authentication needed". Staying connected does not restore the script's own connection, but a script that uses the same app keeps working. The template switched this default to true after 1.1.0, so false matches the last release and needs no changelog entry. - Templates/config_scriptmessage.json: MgDisconnectWhenDone is false. - Research_Notes/Microsoft-Graph-Behavior.md: section 7 records how application-permission connections behave, measured in both editions without sending a message. Section 6 now limits its token cache inference to delegated permissions and cites the SDK 2.25.0 source.
Add the user-visible changes since 1.1.0 that had no entry, each checked against the 1.1.0 tag: Microsoft.Graph.Files no longer being required with application permissions, the certificate password error naming Microsoft Graph, and the template's new MgDelegatedPermission_RequestFilesReadWritePermission setting. Remove the introduction about format and versioning, which RELEASING.md covers.
…aths Get-ScriptMessageConfig read the file with Get-Content and no -Encoding, so non-ASCII characters were silently misread. Windows PowerShell 5.1 decoded a UTF-8 file without a byte order mark in the legacy code page, and PowerShell 7 decoded a legacy code page file as UTF-8. Get-Content -Path also treated square brackets as wildcard characters, so a path containing them was never found. The file is now opened with .NET after PowerShell resolves the path literally. A byte order mark sets the encoding; without one, the file is read as strict UTF-8, falling back to Encoding.GetEncoding(0) when it is not valid UTF-8. That code page is the system's in both editions, the same one 5.1's Get-Content uses. -Encoding UTF8 alone would have broken 5.1 reads of files written by 5.1's Set-Content. A wildcard in the path no longer matches, which was never a supported use. - Tests/Get-ScriptMessageConfig.Tests.ps1: four encodings, a relative path, a PowerShell drive, brackets, and a missing file. Each encoding and bracket test fails against the previous reader in the edition its bug affected. - Research_Notes/File-Encoding-And-Line-Endings.md section 5 and Research_Notes/PowerShell-Language-Behavior.md section 8 record the measurements. - CHANGELOG.md: three Minor entries under Fixed.
Research_Notes/PowerShell-Language-Behavior.md section 9, measured in both
editions: a lone PSCustomObject converts to @{Name=A; ...}, but one inside a
one-item array converts to an empty string, so [string]::IsNullOrEmpty reports
true. The recipient conversion functions pair that test with a second one,
which is what keeps a single recipient from being treated as none. A single
PSCustomObject passed to Send-ScriptMessage -Attachment, which is not a
supported type, comes back as no attachment instead of raising an error.
- ScriptMessage.psd1: ModuleVersion 1.1.1. - CHANGELOG.md: the Unreleased entries become the dated 1.1.1 section, under a new empty Unreleased section.
Prepare release 1.1.1
There was a problem hiding this comment.
🟡 Changes recommended
The release automation would not reliably run/publish due to broken tag filters and invalid artifact action versions, and there’s also a confirmed runtime-breaking bug in the certificate-file authentication path.
Get a fresh assessment by requesting another Copilot review.
Pull request overview
Release PR to ship ScriptMessage 1.1.1 by merging develop into main, including the release notes and the accompanying reliability improvements (tests/CI), documentation, and Microsoft Graph behavior fixes.
Changes:
- Adds a Pester test suite (plus a cross-edition runner) and GitHub Actions workflows to run tests and publish releases.
- Fixes Microsoft Graph sending edge cases (recipient validation, chat messages with/without attachments, attachment filename escaping, config file path/encoding handling).
- Updates release/process documentation and supporting repo metadata (manifest version/tags/links, changelog, contributing and releasing docs,
.gitattributes).
File summaries
| File | Description |
|---|---|
| Tests/Send-ScriptMessage.Tests.ps1 | Adds coverage for recipient validation, chat sends (with/without attachments), and mail attachments. |
| Tests/ScriptMessage.Module.Tests.ps1 | Validates manifest and exported functions; runs PSScriptAnalyzer errors check when available. |
| Tests/Invoke-Tests.ps1 | Adds a runner to execute tests under both Windows PowerShell 5.1 and PowerShell 7 (optionally with pinned Pester). |
| Tests/Get-ScriptMessageConfig.Tests.ps1 | Adds tests for config decoding across BOM/UTF-8/UTF-16/legacy code page and path edge cases. |
| Tests/Connect-ScriptMessage.Tests.ps1 | Adds tests for Graph sub-module requirements depending on allowed message types. |
| Templates/config_scriptmessage.json | Updates sample config with additional settings (e.g., mail/chat and delegated files permission). |
| ScriptMessage/Services/MicrosoftGraph.ps1 | Adjusts Graph module checks and chat attachment upload filename escaping; refactors chat body construction. |
| ScriptMessage/ScriptMessage.psm1 | Removes BOM / normalizes header line. |
| ScriptMessage/ScriptMessage.psd1 | Bumps module version to 1.1.1 and updates metadata links/tags. |
| ScriptMessage/Public/Send-ScriptMessage.ps1 | Fixes recipient validation to reject only truly blank addresses (and not reject 1-item recipient arrays). |
| ScriptMessage/Public/Get-ScriptMessageConfig.ps1 | Switches to a BOM-aware + fallback decoding strategy and resolves PS paths to full filesystem paths. |
| ScriptMessage/Public/Connect-ScriptMessage.ps1 | Clarifies service-level module checks responsibility in comment. |
| Research_Notes/PowerShell-Language-Behavior.md | Adds measured PowerShell runtime behaviors that affect module implementation choices. |
| Research_Notes/Microsoft-Graph-Behavior.md | Documents Graph/SDK behavior and constraints the module relies on (with evidence labeling). |
| Research_Notes/File-Encoding-And-Line-Endings.md | Adds measured evidence behind encoding/line-ending rules and config-reading behavior. |
| RELEASING.md | Introduces formal versioning/branching/release workflow documentation. |
| README.md | Updates top-level docs to reflect semver/versioning and contribution/release guidance links. |
| CONTRIBUTING.md | Adds contributor workflow guidance and safety/testing rules. |
| CLAUDE.md | Adds pointer to AGENTS.md as the shared AI guidance source. |
| CHANGELOG.md | Adds the 1.1.1 dated release section and reintroduces an empty [Unreleased] section. |
| AGENTS.md | Adds the consolidated contributor/AI guidance, including changelog and encoding rules. |
| .github/workflows/Tests.yml | Adds CI workflow for lint + Pester (cross-edition). |
| .github/workflows/Release.yml | Adds tag-driven release workflow: validate → test → publish to PSGallery → create GitHub release. |
| .github/workflows/PSGallery.yml | Removes legacy PSGallery publish workflow (superseded by Release.yml). |
| .github/pull_request_template.md | Adds structured PR template with release classification and checklist. |
| .gitattributes | Pins LF line endings across text files and marks binaries explicitly. |
Review details
- Files reviewed: 26/26 changed files
- Comments generated: 2
- Review effort level: Lite
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
[Unreleased] now exists only on develop, and only while it has entries. The release-prep pull request renames it to the version heading without adding a new empty one, and the first later pull request with a changelog entry adds it back. The Release workflow's tag check refuses to publish a CHANGELOG.md that still has an [Unreleased] section. - Release.yml: the validate job fails on an [Unreleased] heading. - RELEASING.md, AGENTS.md, CONTRIBUTING.md, pull request template: add the section only with an entry, never during release prep, and merge nothing else into develop between release prep and the release merge. - CHANGELOG.md: remove the empty [Unreleased] section added by the 1.1.1 release prep.
5 of 9 tasks
Keep the [Unreleased] changelog section off main
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
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Release pull request for 1.1.1: merges
developintomain. After it merges, the merge commit is tagged1.1.1,which runs the Release workflow. The release notes are the
1.1.1section ofCHANGELOG.md, prepared in #8.This targets
mainbecause it is a release, not a hotfix.Release classification
Checklist
develop, ormainfor a hotfixCHANGELOG.mdhas an entry under[Unreleased]in the right section, or the change is not user-visible.\Tests\Invoke-Tests.ps1passes