Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
82 changes: 82 additions & 0 deletions .github/workflows/release-github-actions.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
name: Release github-actions

# Auto-publishes the github-actions/ actions whenever they change on main.
# On each qualifying push it rebuilds the esbuild bundles, verifies the
# committed dist/ is up to date, then cuts an immutable vX.Y.Z tag and moves
# the vX major alias to the same commit so `@vX` consumers get the update.
#
# Versioning: the full version (vMAJOR.MINOR.PATCH) is read straight from
# github-actions/package.json — package.json is the single source of truth.
# Bump "version" there in your PR (patch, minor, or major); the workflow tags
# exactly that version and points the vMAJOR alias at it. A major bump creates
# a fresh vN alias and leaves older majors untouched. If a tag for the current
# version already exists, the run fails — that's the signal to bump the version.

on:
push:
branches: [ main ]
paths:
- 'github-actions/**'
workflow_dispatch:

permissions:
contents: write

concurrency:
group: release-github-actions
cancel-in-progress: false

jobs:
release:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0 # full history + tags needed to compute the next version

- uses: actions/setup-node@v4
with:
node-version: '24'

- name: Build action bundles
working-directory: github-actions
run: |
npm ci
npm run build
- name: Verify committed dist/ is up to date
run: |
if ! git diff --quiet -- github-actions/dist; then
echo "::error::github-actions/dist is stale. Run 'npm ci && npm run build' in github-actions/ and commit the result before merging."
git --no-pager diff --stat -- github-actions/dist
exit 1
fi
- name: Resolve version from package.json
id: ver
run: |
VER=$(node -p "require('./github-actions/package.json').version")
MAJOR=$(echo "$VER" | cut -d. -f1)
NEW="v${VER}"
ALIAS="v${MAJOR}"
git fetch --tags --force
if git rev-parse -q --verify "refs/tags/${NEW}" >/dev/null; then
echo "::error::Tag ${NEW} already exists. Bump \"version\" in github-actions/package.json before merging."
exit 1
fi
echo "new=$NEW" >> "$GITHUB_OUTPUT"
echo "alias=$ALIAS" >> "$GITHUB_OUTPUT"
echo "Releasing $NEW (alias $ALIAS) at $GITHUB_SHA"
- name: Tag and move major alias
env:
NEW: ${{ steps.ver.outputs.new }}
ALIAS: ${{ steps.ver.outputs.alias }}
run: |
git config user.name "github-actions[bot]"
git config user.email "41898282+github-actions[bot]@users.noreply.github.com"
git tag -a "$NEW" -m "$NEW" "$GITHUB_SHA"
git tag -fa "$ALIAS" -m "$ALIAS -> $NEW" "$GITHUB_SHA"
git push origin "$NEW"
git push -f origin "$ALIAS"
echo "::notice::Released $NEW; $ALIAS now points at $NEW"
13 changes: 13 additions & 0 deletions github-actions/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
# Build outputs from gulp + esbuild
node_modules/
out/

# dist/ is committed for GitHub Actions consumers — it's referenced from
# each action.yml's `main:` field and must be present at the tagged ref.
# Do NOT add 'dist/' here.

# Editor / OS
.DS_Store
*.tsbuildinfo
*.log
.vscode/
27 changes: 27 additions & 0 deletions github-actions/AGENTS.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
# Agent guide — github-actions

This directory holds the **`install-ms-cli`**, **`ms-app-pack`**, and
**`ms-app-deploy`** GitHub Actions for building and deploying Microsoft Managed
Apps (MAAF) from CI.

If you're an agent (GitHub Copilot CLI, Claude Code, or any other) helping with
this component, the reusable skills below are plain Markdown runbooks — read the
relevant one and follow its steps.

## Skills (`agent-skills/`)

| Skill | Use it when |
|---|---|
| [`agent-skills/release-guide.md`](agent-skills/release-guide.md) | Cutting a release PR — bump `package.json`, update the changelog, rebuild `dist/`, open the PR. |
| [`agent-skills/byob-setup.md`](agent-skills/byob-setup.md) | Setting up a Bring-Your-Own-Build deploy pipeline end-to-end (service principal, per-environment permission grant, app creation, workflow wiring). |
| [`agent-skills/architecture.md`](agent-skills/architecture.md) | Understanding the end-to-end flow — setup, local dev, CI loops, the deploy sequence, and the release/versioning model (with diagrams). |

## Build & release essentials

- **Build the actions:** `cd github-actions && npm install && npm run build`
(compiles `src/` and bundles each action into `dist/actions/<name>/index.js`).
- **`dist/` is committed** and referenced by each `action.yml`'s `main:` — always
rebuild it after changing `src/`.
- **Versioning:** `package.json` is the single source of truth. Bump it to release;
the release workflow tags `vX.Y.Z` and moves the `vX` alias on merge to `main`.
- See [`README.md`](README.md) for usage and inputs/outputs.
48 changes: 48 additions & 0 deletions github-actions/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
# Changelog

All notable changes to the Managed Apps GitHub Actions (under `github-actions/`)
are documented here. This project follows [Semantic Versioning](https://semver.org)
and the format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/).

The version here mirrors `github-actions/package.json`. Add/extend the entry for
the new version **in the same PR that bumps the version**, before it merges to
`main` (see "Updating this changelog" at the bottom).

## [Unreleased]

## [1.0.1] - 2026-06-22

Initial release of the Managed Apps GitHub Actions.

### Added
- `install-ms-cli` — installs `@microsoft/managed-apps-cli` (binary: `ms`) on the
runner. Supports the public npm registry and private Azure DevOps Artifacts
feeds (`_password`/PAT vs. bearer `_authToken`, chosen by strict hostname match).
- `ms-app-pack` — runs `ms app pack` to build the app and stage the packed artifact.
- `ms-app-deploy` — runs `ms app deploy` with `--artifact`, `--commit`, or
CLI-internal pack modes, selected from `repoType` in `ms.config.json`.
Outputs `app-id`, `environment-id`, `commit-sha`, and `app-play-uri`.

### Fixed
- `ms-app-deploy` now parses the CLI's streamed `--json` output correctly — the
CLI emits NDJSON progress lines followed by a multi-line result object, which
the previous greedy parse spliced into one invalid blob and failed on. It now
extracts the last valid JSON object, and reads `appId` (the CLI's field name)
plus sources `environment-id` from `ms.config.json`.

### Notes
- Actions run on the `node24` runtime; esbuild bundles target `node24`.
- Shared env-var constants live in a side-effect-free `src/shared/env.ts`, so the
`ms-app-pack` / `ms-app-deploy` bundles never embed the installer's entry point.

---

## Updating this changelog

- Edit this file **in the same PR** that changes anything under `github-actions/`.
- While developing, add lines under **`[Unreleased]`**.
- When you bump `version` in `package.json`, rename the `[Unreleased]` block to the
new version with today's date, and start a fresh empty `[Unreleased]` above it.
- Group entries under `Added` / `Changed` / `Fixed` / `Removed`, and frame them by
what a consumer pinning `@v1` would notice.
- The release workflow does **not** touch this file — it's maintained by hand.
88 changes: 88 additions & 0 deletions github-actions/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
# Managed Apps GitHub Actions

GitHub Actions for building and deploying [Microsoft Managed Apps](https://www.npmjs.com/package/@microsoft/managed-apps-cli) from CI.

## Actions

| Action | What it does | Ref |
|---|---|---|
| [`install-ms-cli`](./install-ms-cli) | Installs `@microsoft/managed-apps-cli` (binary: `ms`) on the runner. | `microsoft/Managed-Apps/github-actions/install-ms-cli@v1` |
| [`ms-app-pack`](./ms-app-pack) | Runs `ms app pack` — builds and packs the app into a deployable artifact. | `microsoft/Managed-Apps/github-actions/ms-app-pack@v1` |
| [`ms-app-deploy`](./ms-app-deploy) | Runs `ms app deploy` — uploads the artifact and deploys to the target environment. | `microsoft/Managed-Apps/github-actions/ms-app-deploy@v1` |

## Quick start

```yaml
name: Deploy Managed App

on:
push:
branches: [main]
paths:
- 'apps/my-app/**'
- '.github/workflows/deploy-managed-app.yml'
workflow_dispatch:

jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v5
- uses: actions/setup-node@v5
with: { node-version: '24' }
- run: npm install
working-directory: apps/my-app
- uses: microsoft/Managed-Apps/github-actions/install-ms-cli@v1
- uses: microsoft/Managed-Apps/github-actions/ms-app-pack@v1
with:
working-directory: 'apps/my-app'
app-id: ${{ secrets.PP_SP_CLIENT_ID }}
client-secret: ${{ secrets.PP_SP_CLIENT_SECRET }}
tenant-id: ${{ secrets.PP_SP_TENANT_ID }}
- uses: microsoft/Managed-Apps/github-actions/ms-app-deploy@v1
with:
working-directory: 'apps/my-app'
app-id: ${{ secrets.PP_SP_CLIENT_ID }}
client-secret: ${{ secrets.PP_SP_CLIENT_SECRET }}
tenant-id: ${{ secrets.PP_SP_TENANT_ID }}
```

See each action's `action.yml` for the full input/output reference.

## Agent skills

Step-by-step guides any operator — or coding-agent CLI (GitHub Copilot CLI, Claude Code, etc.) — can follow. See [`AGENTS.md`](AGENTS.md) for the index.

- [Architecture & Flow](agent-skills/architecture.md) — the end-to-end MAAF lifecycle (setup, local dev, CI loops), the `ms-app-deploy` sequence with RP rejection points, and the release/versioning flow, with diagrams.
- [BYOB setup walkthrough](agent-skills/byob-setup.md) — step-by-step guide to standing up a BYOB deploy pipeline (service principal, per-environment permission grant, app creation, workflow wiring).
- [Release guide](agent-skills/release-guide.md) — how to cut a release PR (version bump + changelog + dist rebuild).

## Prerequisites

- A **Service Principal** in Microsoft Entra ID with the right role on your target Power Platform environment (System Administrator + System Customizer for Dataverse-enabled environments; Environment Admin for non-Dataverse environments via the BAP REST API).
- **`AllowExternalArtifactDeployment`** enabled on the target environment by your tenant administrator.
- A Managed App created with `ms app create --repo none` (BYOB / escape-hatch mode), `ms.config.json` committed in the repo.

## Building the actions

```pwsh
cd github-actions
npm install
npm run build
npm run dist
```

This compiles the TypeScript sources under `src/actions/` and bundles each action into a single JS file under `dist/actions/<action-name>/index.js` via esbuild.

Each action's `action.yml` references the bundled `dist/actions/<name>/index.js` as its entry point.

## Versioning

Actions follow the repository's release tags. Consumers can pin to:

- `@v1` — major version, gets new features + non-breaking changes
- `@v1.x.y` — specific immutable version, never moves

## License

[MIT](../LICENSE)
Loading