Skip to content
Merged
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
44 changes: 38 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,37 @@ buildNumber=
The build number can remain unset if you are using the default version name generators below.
The generated `version_code` output uses the deterministic default formula `major * 10000 + minor * 100 + patch`.

#### Version storage

The default `version_storage` backend is `version-properties`, which reads and writes `version.properties` in the repository root.
Projects that already keep shared Gradle settings in `gradle.properties` can use the `gradle-properties` backend instead.

Both supported backends use the same keys:

```properties
majorVersion=1
minorVersion=0
patchVersion=0
buildNumber=
```

| Backend | File | Behavior |
| ------------------ | -------------------- | ----------------------------------------------------------------- |
| version-properties | `version.properties` | Compatibility default. The action writes the version keys file. |
| gradle-properties | `gradle.properties` | The action updates the version keys and preserves unrelated keys. |

To use `gradle.properties`:

```yaml
- name: Bump version
id: bump_version
uses: oflynned/android-version-bump@master
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
version_storage: gradle-properties
```

#### build.gradle.kts / Kotlin DSL

For Kotlin DSL projects, pass the generated values from GitHub Actions into Gradle as project properties.
Expand Down Expand Up @@ -244,12 +275,13 @@ Enable this field by passing a build number/string/SHA as an input to the action

Pass these in the `with:` block

| Tag | Effect | Example | Default value |
|----------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|------------------------------------------------------------------------------------|--------------------------|
| tag_prefix | Prefix used in the generated release commit message. The git tag, `git_tag`, and `new_tag` outputs remain the unprefixed version. | `tag_prefix: 'release-'` makes the default commit message `release: release-1.0.0` | `v` |
| skip_ci | Affixes `[skip-ci]` to the end of the commit message, even if you provide a custom message | `skip_ci: false` | true |
| build_number | Sets the build run number in the version | `build_number: ${{ github.run_number }}` generates `1.0.0.5` | '' |
| commit_message | Sets the commit message when a release bump is performed. Can optionally use `{{ version }}` to insert the generated version bump with the tag prefix into the commit message. | `ci: {{ version }} was just released into the wild! :tada: :partying_face:` | `release: {{ version }}` |
| Tag | Effect | Example | Default value |
|-----------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|------------------------------------------------------------------------------------|--------------------------|
| version_storage | Selects where version metadata is read from and written to. Supported values are `version-properties` and `gradle-properties`. | `version_storage: gradle-properties` updates `gradle.properties` | `version-properties` |
| tag_prefix | Prefix used in the generated release commit message. The git tag, `git_tag`, and `new_tag` outputs remain the unprefixed version. | `tag_prefix: 'release-'` makes the default commit message `release: release-1.0.0` | `v` |
| skip_ci | Affixes `[skip-ci]` to the end of the commit message, even if you provide a custom message | `skip_ci: false` | true |
| build_number | Sets the build run number in the version | `build_number: ${{ github.run_number }}` generates `1.0.0.5` | '' |
| commit_message | Sets the commit message when a release bump is performed. Can optionally use `{{ version }}` to insert the generated version bump with the tag prefix into the commit message. | `ci: {{ version }} was just released into the wild! :tada: :partying_face:` | `release: {{ version }}` |

## Outputs

Expand Down
2 changes: 1 addition & 1 deletion SECURITY.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
## Supported Versions

| Version | Supported |
| ------- | ------------------ |
|---------|--------------------|
| 1.x.x | :white_check_mark: |
| < 1.0 | :x: |

Expand Down
4 changes: 4 additions & 0 deletions action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,10 @@ branding:
icon: chevron-up
color: blue
inputs:
version_storage:
required: false
description: 'Version metadata storage backend: version-properties or gradle-properties'
default: 'version-properties'
tag_prefix:
required: false
description: 'Prefix to add to the generated release commit message'
Expand Down
8 changes: 4 additions & 4 deletions dist/index.js

Large diffs are not rendered by default.

35 changes: 35 additions & 0 deletions e2e/action.e2e.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,41 @@ describe('packaged action with local git repositories', () => {
},
);

it('reads and writes gradle.properties when configured', () => {
const fixture = run({
version: '1.2.3',
versionStorage: 'gradle-properties',
commits: ['fix: repair launch'],
inputs: {
version_storage: 'gradle-properties',
},
});

expect(fixture.result.status).toBe(0);
expect(gitInRemote(fixture, 'show', 'main:gradle.properties')).toBe(
[
'org.gradle.jvmargs=-Xmx2g',
'majorVersion=1',
'minorVersion=2',
'patchVersion=4',
'buildNumber=',
].join('\n'),
);
expect(
gitInRemote(
fixture,
'diff-tree',
'--no-commit-id',
'--name-only',
'-r',
'main',
),
).toBe('gradle.properties');
expect(gitInRemote(fixture, 'rev-parse', 'refs/tags/1.2.4')).toBe(
gitInRemote(fixture, 'rev-parse', 'refs/heads/main'),
);
});

it('applies inputs, identity, and head-ref checkout', () => {
const fixture = run({
version: '1.2.3',
Expand Down
32 changes: 21 additions & 11 deletions e2e/harness.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,11 @@ const realGit = execFileSync('command', ['-v', 'git'], {
}).trim();

type EventCommit = string | { id: string; message: string };
type VersionStorage = 'version-properties' | 'gradle-properties';

type FixtureOptions = {
version?: string;
versionStorage?: VersionStorage;
commits?: string[];
eventCommits?: EventCommit[];
inputs?: Record<string, string>;
Expand All @@ -35,17 +37,25 @@ export type ActionFixture = {
const git = (cwd: string, args: string[]): string =>
execFileSync(realGit, args, { cwd, encoding: 'utf8' }).trim();

const writeVersion = (workspace: string, version: string): void => {
const writeVersion = (
workspace: string,
version: string,
storage: VersionStorage = 'version-properties',
): void => {
const [major, minor, patch] = version.split('.');
fs.writeFileSync(
path.join(workspace, 'version.properties'),
[
`majorVersion=${major}`,
`minorVersion=${minor}`,
`patchVersion=${patch}`,
'buildNumber=',
].join('\n'),
);
const fileName =
storage === 'gradle-properties'
? 'gradle.properties'
: 'version.properties';
const contents = [
...(storage === 'gradle-properties' ? ['org.gradle.jvmargs=-Xmx2g'] : []),
`majorVersion=${major}`,
`minorVersion=${minor}`,
`patchVersion=${patch}`,
'buildNumber=',
].join('\n');

fs.writeFileSync(path.join(workspace, fileName), contents);
};

const createGitShim = (root: string, remote: string): string => {
Expand Down Expand Up @@ -94,7 +104,7 @@ export const runActionFixture = (
git(workspace, ['config', 'user.email', 'fixture@example.com']);
fs.writeFileSync(path.join(workspace, 'README.md'), 'fixture\n');
if (options.version) {
writeVersion(workspace, options.version);
writeVersion(workspace, options.version, options.versionStorage);
}
git(workspace, ['add', '.']);
git(workspace, ['commit', '-m', 'chore: initial fixture']);
Expand Down
28 changes: 27 additions & 1 deletion src/env.test.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { mock } from 'jest-mock-extended';
import { getCommitMessage } from './env';
import { getCommitMessage, getVersionStorageBackend } from './env';
import { Toolkit } from './toolkit';
import { Build } from './version';

Expand All @@ -19,6 +19,32 @@ describe('Env', () => {
jest.resetAllMocks();
});

describe('getVersionStorageBackend', () => {
it('should default to version properties', () => {
toolkit.inputs['version_storage'] = undefined;

const result = getVersionStorageBackend(toolkit);

expect(result).toEqual('version-properties');
});

it('should return configured version storage backend', () => {
toolkit.inputs['version_storage'] = 'gradle-properties';

const result = getVersionStorageBackend(toolkit);

expect(result).toEqual('gradle-properties');
});

it('should reject unknown version storage backends', () => {
toolkit.inputs['version_storage'] = 'spreadsheet';

expect(() => getVersionStorageBackend(toolkit)).toThrow(
'Invalid version storage backend "spreadsheet"',
);
});
});

describe('getCommitMessage', () => {
it('should default message on none set', () => {
toolkit.inputs['commit_message'] = undefined;
Expand Down
24 changes: 24 additions & 0 deletions src/env.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,19 @@ import { Build } from './version';

export type Key =
| 'gradle_location'
| 'version_storage'
| 'tag_prefix'
| 'skip_ci'
| 'commit_message'
| 'build_number';

export const versionStorageBackends = [
'version-properties',
'gradle-properties',
] as const;

export type VersionStorageBackend = (typeof versionStorageBackends)[number];

export const getValue = (
toolkit: Toolkit,
key: Key,
Expand All @@ -32,6 +40,22 @@ export const getBuildNumber = (toolkit: Toolkit): string => {
return getValue(toolkit, 'build_number', '');
};

export const getVersionStorageBackend = (
toolkit: Toolkit,
): VersionStorageBackend => {
const backend = getValue(toolkit, 'version_storage', 'version-properties');

if (versionStorageBackends.includes(backend as VersionStorageBackend)) {
return backend as VersionStorageBackend;
}

throw new Error(
`Invalid version storage backend "${backend}". Expected one of: ${versionStorageBackends.join(
', ',
)}`,
);
};

export const getCommitMessage = (
toolkit: Toolkit,
build: Build,
Expand Down
3 changes: 2 additions & 1 deletion src/git.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,13 @@ export const setGitIdentity = async (toolkit: Toolkit): Promise<void> => {
export const createCommit = async (
toolkit: Toolkit,
commit: string,
paths = ['version.properties'],
): Promise<void> => {
try {
toolkit.log.log(`Creating version commit`);
toolkit.log.log({ commit });

await runCommand('git', ['add', 'version.properties']);
await runCommand('git', ['add', ...paths]);
await runCommand('git', ['commit', '-m', commit]);
} catch {
toolkit.log.warn(
Expand Down
Loading