
1. Automating software release packaging from FileMaker
- Automating software release packaging from FileMaker
- Before the release process was automated
- Overview of the solution
- Why the Windows and macOS workflows differ
- Copying configured release items
- Coordinating macOS tools
- Notarization and ticket stapling
- Uploading the completed release
- Logging and error handling
- Handing the release to the download manager
- Design lessons from the example
This example is valid for ACF-Plugin version 1.7.9.2 and upwards.
Preparing a software release often involves much more than creating an archive. Files must be collected from several locations, signatures must be checked, installers may need to be built, and the final artifacts must be uploaded and published. On macOS, the release may also require notarization and ticket stapling before it can be distributed.
This example shows how a FileMaker solution and the ACF Plugin can coordinate that workflow. FileMaker stores the release configuration and provides the operator interface, while ACF performs file operations, creates archives, runs platform tools, communicates with remote storage, and reports each step back to FileMaker.
The purpose of the example is to demonstrate the architecture and the important integration points. It is not a complete listing of the release application, and signing identities, credentials, server addresses, and other environment-specific values have deliberately been omitted.
1.1. Before the release process was automated ↑
Before this solution was created, preparing a release was a labour-intensive manual task. Xcode performed the necessary build and signing of the application artifacts, but the remaining components still had to be collected and arranged into the final release archive. This included documentation, release notes, examples, supporting files, and other product-specific material. Repeating these steps manually made it easy for releases to differ in structure or for a required file to be overlooked.
The automated workflow starts with the signed artifacts produced by Xcode and takes responsibility for the rest of the release process. The FileMaker solution stores where every additional component is located and where it belongs in the finished package. Documentation and related files can continue to be maintained in their normal locations; the release process collects the current versions when the package is built.
This configuration is reusable between releases of the same product. In the usual case, the operator only needs to select the newly signed application artifacts and update the version number. The solution then recreates the established package structure, performs the required checks and platform-specific processing, and uploads the result. This saves time while also producing more complete and consistent releases.
1.2. Overview of the solution ↑

The release solution stores one record for each archive to be produced. Related records describe the files and folders that belong in the archive and where each item should be placed.
1.2.1. Selecting files and folders from FileMaker ↑
The portal shown in the screenshot includes buttons for selecting the source file or directory for each release item. FileMaker does not provide a built-in calculation function for displaying a native file or folder picker and returning the selected path. This is a frequently requested requirement when building utilities and configuration interfaces in FileMaker.
The solution uses two functions from the ACF Bootstrap library, which is included with ACF applications:
ACFU_SelectFileOnly ( string_startPath ; string_Prompt )
ACFU_SelectFolder ( string_prompt )
ACFU_SelectFileOnly opens a native file picker, optionally starting in a specified location, and returns the selected file path. ACFU_SelectFolder opens a native directory picker and returns the selected folder path. If the user cancels the dialog, the existing field value can be retained.
This makes the release configuration easier and safer to maintain. The operator selects an item instead of typing a long path manually, reducing spelling mistakes and invalid paths. The same functions can also be reused anywhere a FileMaker solution needs the user to select a local file or directory.
1.2.2. The data model ↑
The simplified data model is:
| Table | Purpose |
|---|---|
ZipArchive |
Stores the project name, version, platform, local output path, and remote target folder. |
ZipArchiveItems |
Stores each source path and its destination folder in the release. |
ZipConfig |
Stores environment-specific remote server configuration. |
ACF_Downloads |
Receives the published file name and remote path for the download manager. |
The FileMaker script is responsible for orchestration:
- Start a build log.
- Call the appropriate ACF function for the target platform.
- Add the ACF console output to the log after each operation.
- Stop immediately and show an error if an operation fails.
- Store the completed release name and remote path for publication.
The ACF package is responsible for the lower-level work:
- Querying the related archive items with SQL.
- Copying files and folders to their intended destinations.
- Creating ZIP archives or macOS staging folders.
- Calling signing, installer, notarization, and DMG tools.
- Uploading the completed artifact to an FTP server.
- Printing detailed progress information for the build log.
1.3. Why the Windows and macOS workflows differ ↑
The same FileMaker solution builds releases for both platforms, but the two workflows are deliberately different.
1.3.1. Windows ZIP release ↑
The Windows release is written directly into a ZIP archive. ACF opens the ZIP and copies each registered source item to an explicit path inside it. When all items have been copied, ACF closes the archive and uploads the finished ZIP file.
The release is currently initiated on a Mac, but it does not use the macOS zip command on a folder. Because ACF adds only the registered files and folders, macOS metadata such as .DS_Store and __MACOSX is not included in the Windows archive.
The complete high-level operation is exposed as one ACF function:
function PackZipArchive (
string PrimaryKey,
string outputZipPath,
string remoteArchiveFolder
)
string res = CopyArchiveItemsToZip(PrimaryKey, outputZipPath);
if (res != "OK") then
throw res;
end if
return UploadReleaseFile(outputZipPath, remoteArchiveFolder);
end
The corresponding FileMaker script can therefore remain small:
Set Variable [ $result ;
ACF_run ( "PackZipArchive" ;
ZipArchive::PrimaryKey ;
ZipArchive::ZipFileName ;
ZipArchive::FullTargetPath
)
]
Set Field [ ZipArchive::Console ; ACF_GetConsoleOutput ]
1.3.2. macOS DMG release ↑
The macOS workflow needs an inspectable staging folder because artifacts must be verified, installers may need to be constructed, and several items may require notarization before the final disk image is made.
The process is:
- Recreate the staging folder.
- Copy all registered release items into it.
- Identify applications, plugins, packages, disk images, and command-line tools that require additional processing.
- Verify the existing code signatures.
- Build a signed installer package where required.
- Submit the staged artifacts to Apple's notary service.
- Staple and validate the accepted notarization tickets.
- Create the final DMG from the staging folder.
- Notarize, staple, and validate the DMG.
- Upload the completed DMG to the remote release archive.
Separating staging from DMG creation also gives the operator an opportunity to inspect the prepared release before the final archive is produced.
1.4. Copying configured release items ↑
The source files are not hard-coded in the ACF package. ACF reads the release definition from the FileMaker tables with ExecuteSQL. NOTE the INTO part at the bottom that is an ACF extention to FileMaker SQL to store the SQL result in arrays instead of producing a CSV style dump.
array string FilePaths;
array string TargetFolders;
array int IsDirectory;
array int IsFileExists;
string sql =
"SELECT
FileLocalFilePath,
TargetFolder,
isDirectory,
isFileExists
FROM
ZipArchiveItems
WHERE
ArchiveFK = :PrimaryKey
ORDER BY
TargetFolder,
FileLocalFilePath
INTO :FilePaths, :TargetFolders, :IsDirectory, :IsFileExists
";
string res = ExecuteSQL(sql);
Each source path is combined with its configured target folder. For a ZIP release, the target is a path inside the open archive:
string zip = open_zip(outputZipPath);
for (i = 1, sizeof(FilePaths))
string targetPath = MakeZipTargetPath(
zip,
TargetFolders[i],
FilePaths[i]
);
res = copy_file(FilePaths[i], targetPath);
end for
close_zip(zip);
For a macOS release, the same configuration is used to copy the items into a normal staging folder instead. This keeps release contents under FileMaker control while allowing platform-specific processing afterward.
Before copying, the implementation verifies that the source exists. A missing item causes an exception rather than producing a partial release.
1.5. Coordinating macOS tools ↑
ACF can use SystemCommand to coordinate command-line tools and capture their output. The actual signing identities and notary profiles should be stored in protected configuration rather than embedded in code intended for distribution.
Typical tools used in this workflow include:
| Tool | Role |
|---|---|
codesign |
Verifies signatures on applications, plugins, disk images, and executable code. |
pkgbuild |
Creates and signs a macOS installer package. |
pkgutil |
Verifies the installer package signature and timestamp. |
xcrun notarytool |
Submits an artifact to Apple's notary service and waits for the result. |
xcrun stapler |
Attaches and validates the accepted notarization ticket. |
| DropDMG | Creates the final DMG using a predefined visual configuration. |
A command is constructed with quoted paths, executed in the appropriate working directory, and then checked for both the expected output and the expected resulting file.
command = "codesign --verify --strict --verbose=2 " + ShellQuote(Path);
print "\nVerifying signature:\n" + command + "\n";
string res = SystemCommand(command, GetDirectoriesFromPath(Path));
print res + "\n";
if (pos(res, "valid on disk") < 0) then
throw "Signature verification failed:\n" + res;
end if
The same principle is used after pkgbuild and DropDMG: successful command execution alone is not considered sufficient. The workflow also verifies that the expected .pkg or .dmg file was created.
1.6. Notarization and ticket stapling ↑
Applications and FileMaker plugin bundles are placed in a temporary ZIP before submission. Installer packages and disk images can be submitted directly.
Before submitting an artifact, the workflow asks stapler whether it already has a valid ticket. This makes the operation safer to repeat and avoids submitting an already notarized artifact again.
The simplified sequence is:
xcrun stapler validate <artifact>
xcrun notarytool submit <artifact> --keychain-profile <profile> --wait
xcrun stapler staple <artifact>
xcrun stapler validate <artifact>
The final validation is important. It confirms that the accepted ticket was attached to the distributed artifact, not only that Apple accepted the submission.
1.7. Uploading the completed release ↑
ACF uses the same path-based file API for local files, ZIP archives, and FTP connections. The upload function opens the configured remote server, creates the full destination path, copies the artifact, and closes the connection.
function UploadReleaseFile (
string localPath,
string remoteArchiveFolder
)
if (! file_exists(localPath)) then
throw "Source file does not exist: " + localPath;
end if
string ftp = ConnectRemoteServer();
remoteArchiveFolder = EnsureTrailingSlash(remoteArchiveFolder);
string remoteTarget = ftp
+ remoteArchiveFolder
+ GetFilenameFromPath(localPath);
string res = copy_file(localPath, remoteTarget);
close_ftp(ftp);
if (res != "OK") then
throw "FTP upload failed: " + res;
end if
return "OK";
end
In production, the server name and credentials come from configuration fields. They should not be printed in the build log or included in source code examples.
1.8. Logging and error handling ↑
Every ACF function prints useful progress information to the ACF console. The FileMaker script retrieves that text with ACF_GetConsoleOutput and appends it to a build log after each call.
A successful macOS log shows a progression similar to this:
Copying release items to the staging folder
Verifying command-line utility signature
Building installer package
Verifying installer package signature
Submitting installer for notarization
Notarization status: Accepted
Stapling and validating installer ticket
Creating DMG
Submitting DMG for notarization
Notarization status: Accepted
Stapling and validating DMG ticket
Uploading completed DMG
Result: OK
Each operation returns "OK" on success or throws an exception with a detailed message. The FileMaker script checks the result before continuing. A failed signature check, missing source file, rejected notarization, missing output artifact, or failed upload therefore stops the release before it can be published.
1.9. Handing the release to the download manager ↑
After a successful upload, FileMaker stores the release name and the remote file path in the related download record. The download manager can then call the website's WordPress API to update the public download information.
Keeping this as a separate final step has two advantages:
- A release is never announced before packaging and upload have completed successfully.
- The operator can review the version, description, and download path before publishing them.
The workflow can be made fully automatic, or the final API call can require operator confirmation depending on the release policy.
1.10. Design lessons from the example ↑
This release system demonstrates several patterns that are useful beyond software packaging:
- Keep configuration in FileMaker. Users can maintain release contents, versions, and destinations without changing ACF source code.
- Keep orchestration visible. The FileMaker script shows the major workflow and can present progress and errors to the operator.
- Use ACF for system integration. File operations, archives, SQL, remote connections, and command-line tools can be combined in one controlled automation layer.
- Verify outputs, not only commands. Check signatures, return values, and generated files before moving to the next stage.
- Fail early. Do not create or publish a partial release when a required source file or validation step fails.
- Make long operations observable. Console output and persistent logs make signing and notarization problems much easier to diagnose.
- Adapt the process to the target platform. A direct ZIP build is appropriate for Windows, while the macOS workflow needs staging, signing, installer construction, and notarization.
The result is a repeatable release process controlled from FileMaker, while ACF provides access to the operating system and remote services needed to complete the work.
