Use the sibling scripts from the Ezytire repository root:
Build-StagingCustomProjects.ps1 rebuilds only supported projects affected by
the selected source paths and stages their Release DLLs in
Tireweb Sites\Web\Bin.
Deploy-StagingCustom.ps1 deploys a specific list of files under
Tireweb Sites\Web to staging. It maps that local folder directly to a
user-selected remote staging directory and verifies each uploaded file's
remote size.
Deployment workflow
For a direct deployment chat, clear the previously saved remote directory at
the beginning of skill loading, then load the settings helper:
. "$HOME\.copilot\skills\deploy-files-staging\StagingDeploymentSettings.ps1"
Remove-StagingDeploymentRemoteRoot
For a direct deployment, ask the user for the remote staging directory that
should be used for this chat session before previewing files, unless the
user already provided one in the deployment request. Accept either
EOSB-757 or /EOSB-757; normalize it before use.
For a direct deployment, save the chosen directory locally, outside the
repository:
$remoteRoot = Set-StagingDeploymentRemoteRoot -RemoteRoot $chosenRemoteRoot
For succeeding direct deployments in the same chat session, reuse that saved
directory without asking again.
If the user asks to change directories, or provides a new directory in a
later invocation, use the new value and immediately resave it with
Set-StagingDeploymentRemoteRoot before previewing.
Resolve the complete changed-path list. The deployment script accepts either:
- An explicit list via
-IncludePaths, or
- Git log arguments via
-GenerateListFromGitLogArgs that the script passes
to git log --name-only --pretty=format:.
Examples:
# Explicit list
& "$HOME\.copilot\skills\deploy-files-staging\Deploy-StagingCustom.ps1" `
-RepositoryRoot (Get-Location).Path `
-RemoteRoot $remoteRoot `
-IncludePaths 'Tireweb Sites/Web/App_Modules/248-GMapLiteStore/BrakesPlus.ascx','Tireweb Sites/Web/App_Modules/248-GMapLiteStore/Default.ascx.cs' `
-WhatIf
# Generated from git log date range on development
& "$HOME\.copilot\skills\deploy-files-staging\Deploy-StagingCustom.ps1" `
-RepositoryRoot (Get-Location).Path `
-RemoteRoot $remoteRoot `
-GenerateListFromGitLogArgs 'development','--since=2026-08-01','--until=2026-08-08' `
-WhatIf
Classify paths outside Tireweb Sites\Web. If any belong to a supported
project, run Build-StagingCustomProjects.ps1 once with the complete
changed-path list. The helper rebuilds each affected project at most once in
Release configuration and copies its expected DLL into
Tireweb Sites\Web\Bin.
$preparedDlls = @(
& "$HOME\.copilot\skills\deploy-files-staging\Build-StagingCustomProjects.ps1" `
-RepositoryRoot (Get-Location).Path `
-ChangedPaths $changedPaths
)
$webPaths = @(
$changedPaths |
Where-Object { $_ -like 'Tireweb Sites/Web/*' }
)
$deploymentPaths = @($webPaths) + @($preparedDlls.WebRelativePath)
Treat every build error or missing expected DLL as blocking. Do not deploy a
stale or partial build. Report warnings, but proceed only when MSBuild exits
successfully and all expected DLLs were staged. Do not build the full
solution when a mapped smaller project covers the source changes.
Run the deployment preview with the chosen directory, the explicit
$deploymentPaths queue, and -WhatIf. Do not rebuild between preview and
upload; the confirmed upload must use the exact staged DLL that was previewed.
After a successful preview, and before asking for confirmation or uploading
anything, always present the complete final upload queue in this exact
review format:
Remote root: /EOSB-757
Upload queue:
1. `Tireweb Sites/Web/path/file.ext`
2. `Tireweb Sites/Web/path/other.ext`
Use a numbered Markdown list with one complete repository-relative
deployment path per item, enclosed in inline code. Normalize displayed
paths to / separators and sort them deterministically by the complete
path. Build this list from the preview's final deployable queue, not from
the raw changed-path list, so it includes every staged DLL such as
Tireweb Sites/Web/Bin/Customization.dll and excludes files skipped by
validation. Keep the remote root on its own line outside the numbered list.
If the final queue is empty, report Upload queue: empty and do not ask for
confirmation or deploy.
Select the confirmation behavior only after displaying that final queue:
- Standard mode (default): ask the user for explicit confirmation after
the queue is displayed.
- Autopilot mode: when the user explicitly requests
autopilot, display
the same queue and remote root, then proceed directly to the real upload.
Do not add a confirmation prompt.
Autopilot mode only skips the post-preview confirmation. It never skips:
- remote directory selection or normalization;
- the preview; or
- scope validation.
After confirmation in standard mode, or immediately after displaying the
queue in autopilot mode, run the same command without -WhatIf:
& "$HOME\.copilot\skills\deploy-files-staging\Deploy-StagingCustom.ps1" `
-RepositoryRoot (Get-Location).Path `
-RemoteRoot $remoteRoot `
-IncludePaths '...'
Report success or the error emitted by the script. Always display the full
list of files uploaded in that deployment, with local repository-relative
and remote paths. Do not retry a failed upload without first resolving and
explaining the failure.
How file lists are resolved
-IncludePaths accepts an array of repository-relative paths. Paths are
normalized, deduplicated, checked for directory traversal, verified to exist
on disk, and limited to files under Tireweb Sites\Web.
-GenerateListFromGitLogArgs accepts an array of arguments passed after
git log --name-only --pretty=format:. It runs:
git log --name-only --pretty=format: <args>
The output is deduplicated and then validated the same way as -IncludePaths.
The two parameters cannot be combined.
Supported source paths are converted to DLL deployment artifacts by
Build-StagingCustomProjects.ps1:
| Changed-path prefix |
Project |
Staged Release DLL |
Charlie/ |
Charlie\Charlie.csproj |
Tireweb Sites\Web\Bin\Charlie.dll |
Tireweb Business/ |
Tireweb Business\Tireweb Business.csproj |
Tireweb Sites\Web\Bin\Tireweb Business.dll |
Poindexter/ |
Poindexter\Poindexter.csproj |
Tireweb Sites\Web\Bin\Poindexter.dll |
Wonky Wheel/Wonky/ |
Wonky Wheel\Wonky\Wonky.csproj |
Tireweb Sites\Web\Bin\Wonky.dll |
Tireweb Sites/Sites/ |
Tireweb Sites\Sites\Sites.csproj |
Tireweb Sites\Web\Bin\Tireweb.Sites.dll |
Customization/ |
Customization\Customization.csproj |
Tireweb Sites\Web\Bin\Customization.dll |
Build each affected project at most once and preserve this dependency order.
A source path outside these mappings remains excluded until its project and
output DLL are explicitly added to the helper.
Files outside Tireweb Sites\Web that do not match a supported project are
reported as excluded and are not deployed.
Sensitive and secret files are blocked from deployment. The exact blocklist
includes but is not limited to:
WebsiteOptions.config
App_Files\*.config
.env and .env.*
secrets.json and secrets.*.json
appsettings.json and appsettings.*.json
- Certificate and key files (
.pfx, .key, .pem, .cer, .crt)
If a blocked file is included, the deployment stops with an error before any
upload occurs.
SFTP authentication
The staging connection uses aldrin.d@52.44.202.235:22 with the password
from the current user's Windows Credential Manager. It uses the bundled
portable WinSCP .NET library and pins this server fingerprint:
ssh-rsa 1024 Yxo6FcvF30RCXrUQYJep89aRHkX8a6MAMY2XwFXPV6w
If the credential has not been saved, direct the user to run the existing
staging credential helper:
& "$HOME\.copilot\skills\staging-deployment\Set-StagingCredential.ps1"
The password must never be entered in chat, source control, a command line, or
a configuration file. Do not read or modify FileZilla's sites.xml.
Safety
- Do not add
shell or bash to this skill's allowed-tools.
- The script uploads the requested files only; it deliberately does not delete
files from the staging server.
- Autopilot mode requires explicit user authorization for that deployment. Never
infer it from a previous unrelated deployment.
- Do not change the configured host or username unless the user explicitly
requests an override.
- The directory selected by the user is remembered for the current chat session
and is reused automatically unless the user explicitly changes it.
1---2name: deploy-files-staging3description: Deploy a user-supplied list of Ezytire web files and rebuilt project DLLs to staging through SFTP, with optional generation of the list from a git log expression. Use when asked to deploy a custom set of files, a generated file list, or a date-range-based set of changes to staging.4---56Use the sibling scripts from the Ezytire repository root:78- `Build-StagingCustomProjects.ps1` rebuilds only supported projects affected by9 the selected source paths and stages their Release DLLs in10 `Tireweb Sites\Web\Bin`.11- `Deploy-StagingCustom.ps1` deploys a specific list of files under12 `Tireweb Sites\Web` to staging. It maps that local folder directly to a13 user-selected remote staging directory and verifies each uploaded file's14 remote size.1516## Deployment workflow17181. For a direct deployment chat, clear the previously saved remote directory at19 the beginning of skill loading, then load the settings helper:2021 ```powershell22 . "$HOME\.copilot\skills\deploy-files-staging\StagingDeploymentSettings.ps1"23 Remove-StagingDeploymentRemoteRoot24 ```25262. For a direct deployment, ask the user for the remote staging directory that27 should be used for this chat session before previewing files, unless the28 user already provided one in the deployment request. Accept either29 `EOSB-757` or `/EOSB-757`; normalize it before use.303. For a direct deployment, save the chosen directory locally, outside the31 repository:3233 ```powershell34 $remoteRoot = Set-StagingDeploymentRemoteRoot -RemoteRoot $chosenRemoteRoot35 ```36374. For succeeding direct deployments in the same chat session, reuse that saved38 directory without asking again.395. If the user asks to change directories, or provides a new directory in a40 later invocation, use the new value and immediately resave it with41 `Set-StagingDeploymentRemoteRoot` before previewing.426. Resolve the complete changed-path list. The deployment script accepts either:4344 - An explicit list via `-IncludePaths`, or45 - Git log arguments via `-GenerateListFromGitLogArgs` that the script passes46 to `git log --name-only --pretty=format:`.4748 Examples:4950 ```powershell51 # Explicit list52 & "$HOME\.copilot\skills\deploy-files-staging\Deploy-StagingCustom.ps1" `53 -RepositoryRoot (Get-Location).Path `54 -RemoteRoot $remoteRoot `55 -IncludePaths 'Tireweb Sites/Web/App_Modules/248-GMapLiteStore/BrakesPlus.ascx','Tireweb Sites/Web/App_Modules/248-GMapLiteStore/Default.ascx.cs' `56 -WhatIf57 ```5859 ```powershell60 # Generated from git log date range on development61 & "$HOME\.copilot\skills\deploy-files-staging\Deploy-StagingCustom.ps1" `62 -RepositoryRoot (Get-Location).Path `63 -RemoteRoot $remoteRoot `64 -GenerateListFromGitLogArgs 'development','--since=2026-08-01','--until=2026-08-08' `65 -WhatIf66 ```67687. Classify paths outside `Tireweb Sites\Web`. If any belong to a supported69 project, run `Build-StagingCustomProjects.ps1` once with the complete70 changed-path list. The helper rebuilds each affected project at most once in71 Release configuration and copies its expected DLL into72 `Tireweb Sites\Web\Bin`.7374 ```powershell75 $preparedDlls = @(76 & "$HOME\.copilot\skills\deploy-files-staging\Build-StagingCustomProjects.ps1" `77 -RepositoryRoot (Get-Location).Path `78 -ChangedPaths $changedPaths79 )8081 $webPaths = @(82 $changedPaths |83 Where-Object { $_ -like 'Tireweb Sites/Web/*' }84 )85 $deploymentPaths = @($webPaths) + @($preparedDlls.WebRelativePath)86 ```8788 Treat every build error or missing expected DLL as blocking. Do not deploy a89 stale or partial build. Report warnings, but proceed only when MSBuild exits90 successfully and all expected DLLs were staged. Do not build the full91 solution when a mapped smaller project covers the source changes.928. Run the deployment preview with the chosen directory, the explicit93 `$deploymentPaths` queue, and `-WhatIf`. Do not rebuild between preview and94 upload; the confirmed upload must use the exact staged DLL that was previewed.959. After a successful preview, and before asking for confirmation or uploading96 anything, always present the complete final upload queue in this exact97 review format:9899 ```text100 Remote root: /EOSB-757101102 Upload queue:103 1. `Tireweb Sites/Web/path/file.ext`104 2. `Tireweb Sites/Web/path/other.ext`105 ```106107 Use a numbered Markdown list with one complete repository-relative108 deployment path per item, enclosed in inline code. Normalize displayed109 paths to `/` separators and sort them deterministically by the complete110 path. Build this list from the preview's final deployable queue, not from111 the raw changed-path list, so it includes every staged DLL such as112 `Tireweb Sites/Web/Bin/Customization.dll` and excludes files skipped by113 validation. Keep the remote root on its own line outside the numbered list.114 If the final queue is empty, report `Upload queue: empty` and do not ask for115 confirmation or deploy.11610. Select the confirmation behavior only after displaying that final queue:117 - **Standard mode (default):** ask the user for explicit confirmation after118 the queue is displayed.119 - **Autopilot mode:** when the user explicitly requests `autopilot`, display120 the same queue and remote root, then proceed directly to the real upload.121 Do not add a confirmation prompt.12211. Autopilot mode only skips the post-preview confirmation. It never skips:123 - remote directory selection or normalization;124 - the preview; or125 - scope validation.12612. After confirmation in standard mode, or immediately after displaying the127 queue in autopilot mode, run the same command without `-WhatIf`:128129 ```powershell130 & "$HOME\.copilot\skills\deploy-files-staging\Deploy-StagingCustom.ps1" `131 -RepositoryRoot (Get-Location).Path `132 -RemoteRoot $remoteRoot `133 -IncludePaths '...'134 ```13513613. Report success or the error emitted by the script. Always display the full137 list of files uploaded in that deployment, with local repository-relative138 and remote paths. Do not retry a failed upload without first resolving and139 explaining the failure.140141## How file lists are resolved142143- `-IncludePaths` accepts an array of repository-relative paths. Paths are144 normalized, deduplicated, checked for directory traversal, verified to exist145 on disk, and limited to files under `Tireweb Sites\Web`.146- `-GenerateListFromGitLogArgs` accepts an array of arguments passed after147 `git log --name-only --pretty=format:`. It runs:148149 ```powershell150 git log --name-only --pretty=format: <args>151 ```152153 The output is deduplicated and then validated the same way as `-IncludePaths`.154- The two parameters cannot be combined.155- Supported source paths are converted to DLL deployment artifacts by156 `Build-StagingCustomProjects.ps1`:157158 | Changed-path prefix | Project | Staged Release DLL |159 | --- | --- | --- |160 | `Charlie/` | `Charlie\Charlie.csproj` | `Tireweb Sites\Web\Bin\Charlie.dll` |161 | `Tireweb Business/` | `Tireweb Business\Tireweb Business.csproj` | `Tireweb Sites\Web\Bin\Tireweb Business.dll` |162 | `Poindexter/` | `Poindexter\Poindexter.csproj` | `Tireweb Sites\Web\Bin\Poindexter.dll` |163 | `Wonky Wheel/Wonky/` | `Wonky Wheel\Wonky\Wonky.csproj` | `Tireweb Sites\Web\Bin\Wonky.dll` |164 | `Tireweb Sites/Sites/` | `Tireweb Sites\Sites\Sites.csproj` | `Tireweb Sites\Web\Bin\Tireweb.Sites.dll` |165 | `Customization/` | `Customization\Customization.csproj` | `Tireweb Sites\Web\Bin\Customization.dll` |166167 Build each affected project at most once and preserve this dependency order.168 A source path outside these mappings remains excluded until its project and169 output DLL are explicitly added to the helper.170- Files outside `Tireweb Sites\Web` that do not match a supported project are171 reported as excluded and are not deployed.172- Sensitive and secret files are blocked from deployment. The exact blocklist173 includes but is not limited to:174 - `WebsiteOptions.config`175 - `App_Files\*.config`176 - `.env` and `.env.*`177 - `secrets.json` and `secrets.*.json`178 - `appsettings.json` and `appsettings.*.json`179 - Certificate and key files (`.pfx`, `.key`, `.pem`, `.cer`, `.crt`)180181 If a blocked file is included, the deployment stops with an error before any182 upload occurs.183184## SFTP authentication185186The staging connection uses `aldrin.d@52.44.202.235:22` with the password187from the current user's Windows Credential Manager. It uses the bundled188portable WinSCP .NET library and pins this server fingerprint:189190```text191ssh-rsa 1024 Yxo6FcvF30RCXrUQYJep89aRHkX8a6MAMY2XwFXPV6w192```193194If the credential has not been saved, direct the user to run the existing195staging credential helper:196197```powershell198& "$HOME\.copilot\skills\staging-deployment\Set-StagingCredential.ps1"199```200201The password must never be entered in chat, source control, a command line, or202a configuration file. Do not read or modify FileZilla's `sites.xml`.203204## Safety205206- Do not add `shell` or `bash` to this skill's `allowed-tools`.207- The script uploads the requested files only; it deliberately does not delete208 files from the staging server.209- Autopilot mode requires explicit user authorization for that deployment. Never210 infer it from a previous unrelated deployment.211- Do not change the configured host or username unless the user explicitly212 requests an override.213- The directory selected by the user is remembered for the current chat session214 and is reused automatically unless the user explicitly changes it.