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
2 changes: 1 addition & 1 deletion .github/workflows/__main-ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ jobs:
release:
needs: ci
if: github.event_name != 'schedule'
uses: hoverkraft-tech/ci-github-publish/.github/workflows/release-actions.yml@ea6682de88070c254dac619a6623a242a6d57cd3 # 1.0.3
uses: hoverkraft-tech/ci-github-publish/.github/workflows/release-actions.yml@f06e0e72a76bfca57c34d08d03e5c1914275fd4c # 2.0.0
permissions:
contents: read
with:
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/__prepare-release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ permissions: {}

jobs:
release:
uses: hoverkraft-tech/ci-github-publish/.github/workflows/prepare-release.yml@ea6682de88070c254dac619a6623a242a6d57cd3 # 1.0.3
uses: hoverkraft-tech/ci-github-publish/.github/workflows/prepare-release.yml@f06e0e72a76bfca57c34d08d03e5c1914275fd4c # 2.0.0
permissions:
contents: read
pull-requests: write
4 changes: 2 additions & 2 deletions .github/workflows/__release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -53,14 +53,14 @@ jobs:

- name: Plan release
id: plan-release
uses: hoverkraft-tech/ci-github-publish/actions/release/plan@ea6682de88070c254dac619a6623a242a6d57cd3 # 1.0.3
uses: hoverkraft-tech/ci-github-publish/actions/release/plan@f06e0e72a76bfca57c34d08d03e5c1914275fd4c # 2.0.0
with:
target-sha: ${{ github.sha }}
github-token: ${{ steps.generate-token.outputs.token }}

- name: Create and publish release
if: (steps.plan-release.outputs.has-changes == 'true' || (github.event_name == 'workflow_dispatch' && inputs.force)) && steps.plan-release.outputs.tag != ''
uses: hoverkraft-tech/ci-github-publish/actions/release/create@ea6682de88070c254dac619a6623a242a6d57cd3 # 1.0.3
uses: hoverkraft-tech/ci-github-publish/actions/release/create@f06e0e72a76bfca57c34d08d03e5c1914275fd4c # 2.0.0
env:
OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }} # zizmor: ignore[secrets-outside-env] repository secret is scoped to the release summary step
with:
Expand Down
14 changes: 14 additions & 0 deletions .github/workflows/__shared-ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,20 @@ jobs:
permissions:
contents: read

test-action-package-test:
name: Test action "package/test"
needs: linter
uses: $/.github/workflows/__test-action-package-test.yml
permissions:
contents: read

test-action-package-discover:
name: Test action "package/discover"
needs: linter
uses: $/.github/workflows/__test-action-package-discover.yml
permissions:
contents: read

test-action-setup-node:
name: Test action "setup-node"
needs: linter
Expand Down
171 changes: 171 additions & 0 deletions .github/workflows/__test-action-package-discover.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,171 @@
name: Internal - Tests for "package/discover" action

on:
workflow_call:

permissions: {}

jobs:
discover:
name: Package discovery (${{ matrix.fixture.name }})
runs-on: ubuntu-latest
permissions:
contents: read
strategy:
fail-fast: false
matrix:
fixture:
- name: standalone npm
root: { private: false }
expected: ["."]
- name: npm workspaces and exclusions
root:
private: true
workspaces: [packages/*, "!packages/excluded"]
expected: [packages/cli, packages/core]
- name: workspace root is not implicitly packaged
root:
private: false
workspaces: [packages/core]
expected: [packages/core]
- name: Yarn workspace object
manager: yarn
root:
workspaces: { packages: [packages/*, "!packages/excluded"] }
expected: [packages/cli, packages/core]
- name: pnpm workspaces
manager: pnpm
files:
pnpm-workspace.yaml: |
packages:
- 'packages/*'
- '!packages/excluded'
expected: [packages/cli, packages/core]
- name: pnpm 10 workspaces
manager: pnpm10
files:
pnpm-workspace.yaml: |
packages:
- 'packages/*'
- '!packages/excluded'
expected: [packages/cli, packages/core]
- name: standalone pnpm with settings
manager: pnpm
root: { private: false }
files:
pnpm-workspace.yaml: "packages: []"
expected: ["."]
- name: Lerna package patterns take precedence
root: { workspaces: [packages/excluded] }
files:
lerna.json: '{"version":"independent","packages":["packages/*","!packages/excluded"]}'
expected: [packages/cli, packages/core]
- name: explicit subset
root: { workspaces: [packages/*] }
directories: '["packages/core"]'
expected: [packages/core]
- name: explicit root
root: { private: false, workspaces: [packages/*] }
directories: '["."]'
expected: ["."]
- name: private standalone
expected: failure
- name: private workspaces only
root: { workspaces: [packages/private] }
expected: failure
- name: unmatched workspaces
root: { workspaces: [missing/*] }
expected: failure
- name: explicit private package
directories: '["packages/private"]'
expected: failure
- name: empty override
directories: "[]"
expected: failure
- name: invalid override
directories: '{"directory":"packages/core"}'
expected: failure
- name: escaping directory
directories: '["../outside"]'
expected: failure
- name: duplicate normalized directories
directories: '["packages/core", "./packages/core/"]'
expected: failure
- name: symlink outside the project
directories: '["linked"]'
expected: failure
steps:
- name: Arrange - Checkout
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false
- name: Arrange - Create uninstalled project fixtures
id: fixture
uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
env:
FIXTURE: ${{ toJSON(matrix.fixture) }}
with:
script: |
const fs = require('node:fs');
const path = require('node:path');
const fixture = JSON.parse(process.env.FIXTURE);
const temporary = fs.mkdtempSync(path.join(process.env.RUNNER_TEMP, 'package-discovery-'));
const directory = path.join(temporary, 'project');
const write = async (file, content) => {
const target = path.join(directory, file);
await io.mkdirP(path.dirname(target));
fs.writeFileSync(target, typeof content === 'string' ? content : JSON.stringify(content));
};
const manifest = { name: 'discovery-root', version: '1.0.0', private: true, ...fixture.root,
scripts: { preinstall: 'exit 91', postinstall: 'exit 91', prepare: 'exit 91' } };
if (fixture.manager?.startsWith('pnpm')) {
const lock = JSON.parse(fs.readFileSync('actions/release/prepare/package-lock.json', 'utf8'));
manifest.packageManager = `pnpm@${lock.packages[`node_modules/${fixture.manager}`].version}`;
await write('pnpm-lock.yaml', "lockfileVersion: '9.0'\n");
} else if (fixture.manager === 'yarn') {
await write('yarn.lock', '# yarn lockfile v1\n');
} else {
await write('package-lock.json', { name: manifest.name, version: manifest.version, lockfileVersion: 3, packages: { '': manifest } });
}
await write('package.json', manifest);
await write('.node-version', fs.readFileSync('.node-version', 'utf8'));
for (const name of ['core', 'cli', 'private', 'excluded']) {
await write(`packages/${name}/package.json`, { name: `@example/${name}`, version: '1.0.0', private: name === 'private', scripts: manifest.scripts });
}
await write('examples/unconfigured/package.json', { name: 'unconfigured', version: '1.0.0' });
for (const [file, content] of Object.entries(fixture.files || {})) await write(file, content);
await io.mkdirP(path.join(temporary, 'outside'));
fs.writeFileSync(path.join(temporary, 'outside/package.json'), JSON.stringify({ name: 'outside', version: '1.0.0' }));
fs.symlinkSync(path.join(temporary, 'outside'), path.join(directory, 'linked'), 'dir');
core.setOutput('directory', directory);
const lockfile = fixture.manager?.startsWith('pnpm') ? 'pnpm-lock.yaml' : fixture.manager === 'yarn' ? 'yarn.lock' : 'package-lock.json';
core.setOutput('lockfile', path.join(directory, lockfile));
core.setOutput('lock-content', fs.readFileSync(path.join(directory, lockfile), 'utf8'));
- name: Act - Discover packages without installing dependencies
id: discover
continue-on-error: true
uses: $/actions/package/discover
with:
working-directory: ${{ steps.fixture.outputs.directory }}
directories: ${{ matrix.fixture.directories || '' }}
- name: Assert - Selection and dependency installation
uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
env:
EXPECTED: ${{ toJSON(matrix.fixture.expected) }}
OUTCOME: ${{ steps.discover.outcome }}
DIRECTORIES: ${{ steps.discover.outputs.directories }}
PROJECT: ${{ steps.fixture.outputs.directory }}
LOCKFILE: ${{ steps.fixture.outputs.lockfile }}
LOCK_CONTENT: ${{ steps.fixture.outputs.lock-content }}
with:
script: |
const assert = require('node:assert/strict');
const fs = require('node:fs');
const path = require('node:path');
const expected = JSON.parse(process.env.EXPECTED);
assert.equal(process.env.OUTCOME, expected === 'failure' ? 'failure' : 'success');
if (expected !== 'failure') assert.deepEqual(JSON.parse(process.env.DIRECTORIES), expected);
const installed = await (await glob.create(`${process.env.PROJECT}/**/node_modules`, { followSymbolicLinks: false })).glob();
assert.deepEqual(installed, []);
assert.equal(fs.existsSync(path.join(process.env.PROJECT, 'package.tgz')), false);
assert.equal(fs.readFileSync(process.env.LOCKFILE, 'utf8'), process.env.LOCK_CONTENT);
26 changes: 26 additions & 0 deletions .github/workflows/__test-action-package-publish.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ jobs:
contents: read
outputs:
package-tarball-artifact-id: ${{ steps.package.outputs.package-tarball-artifact-id }}
published-version-artifact-id: ${{ steps.published-version.outputs.package-tarball-artifact-id }}
steps:
- name: Arrange - Checkout sources
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
Expand All @@ -31,6 +32,24 @@ jobs:
with:
working-directory: tests/npm

- id: published-fixture
name: Arrange - Use an existing npm name and version
uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
with:
script: |
const fs = require('node:fs');
const path = require('node:path');
const { stdout } = await exec.getExecOutput('npm', ['--version'], { silent: true });
const version = stdout.trim();
const directory = fs.mkdtempSync(path.join(process.env.RUNNER_TEMP, 'published-version-'));
fs.writeFileSync(path.join(directory, 'package.json'), JSON.stringify({ name: 'npm', version, packageManager: `npm@${version}` }));
core.setOutput('directory', directory);
- id: published-version
name: Arrange - Pack the existing-version fixture
uses: $/actions/package/create
with:
working-directory: ${{ steps.published-fixture.outputs.directory }}

publish:
name: Publish dry run (${{ matrix.os }}, ${{ matrix.tag || 'default tag' }})
needs: package
Expand All @@ -57,6 +76,13 @@ jobs:
dry-run: "true"
provenance: "false"

- name: Act - Validate an already-published version without publishing
uses: $/actions/package/publish
with:
package-tarball-artifact-id: ${{ needs.package.outputs.published-version-artifact-id }}
dry-run: "true"
provenance: "false"

- id: invalid-artifact
name: Act - Reject multiple artifact IDs
continue-on-error: true
Expand Down
Loading
Loading