Skip to content

Conversation

@gregnazario
Copy link
Contributor

@gregnazario gregnazario commented Jan 22, 2026

Add a GitHub Actions workflow and documentation to demonstrate building and using Aptos Move artifacts in CI/CD pipelines.

Closes #20


Open in Cursor Open in Web

@cursor
Copy link

cursor bot commented Jan 22, 2026

Cursor Agent can help with this pull request. Just @cursor in comments and I'll start working on changes in this branch.
Learn more about Cursor Agents

@gregnazario gregnazario requested a review from Copilot January 22, 2026 03:03
@gregnazario gregnazario requested a review from 0xmaayan January 22, 2026 03:04
@gregnazario gregnazario marked this pull request as ready for review January 22, 2026 03:04
Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR adds a complete example demonstrating how to build and use Aptos Move artifacts in CI/CD pipelines, addressing issue #20 which requested support for building upgrade payloads for object code deployment.

Changes:

  • Added a working GitHub Actions workflow that demonstrates building Move packages, generating publish payloads, and generating upgrade payloads
  • Added comprehensive documentation to the README with practical examples for CI/CD integration
  • Created a sample Move module (hello_blockchain) to serve as a working example for the workflow

Reviewed changes

Copilot reviewed 4 out of 5 changed files in this pull request and generated 4 comments.

File Description
.github/workflows/build-move-artifacts.yaml Implements a complete CI/CD workflow with three jobs: building Move artifacts, using those artifacts in a downstream job, and demonstrating upgrade payload generation
README.md Adds detailed documentation section explaining how to use the Aptos CLI in CI/CD pipelines with examples for both publish and upgrade payloads
examples/hello_blockchain/Move.toml Configuration file for the example Move package with dependencies on Aptos Framework
examples/hello_blockchain/sources/message.move Simple Move module implementing a message storage system with events, used to demonstrate the build process

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines 122 to 130
python3 -c "
import json
with open('$PAYLOAD_FILE') as f:
payload = json.load(f)
print('Payload type:', payload.get('type', 'N/A'))
print('Function:', payload.get('function', 'N/A'))
if 'args' in payload:
print('Number of args:', len(payload['args']))
"
Copy link

Copilot AI Jan 22, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The Python script has incorrect indentation. The multi-line Python string starting at line 122 has inconsistent indentation - the import json statement and subsequent lines should be aligned with the opening of the Python script, not indented further. This will cause a Python IndentationError when the script executes.

Suggested change
python3 -c "
import json
with open('$PAYLOAD_FILE') as f:
payload = json.load(f)
print('Payload type:', payload.get('type', 'N/A'))
print('Function:', payload.get('function', 'N/A'))
if 'args' in payload:
print('Number of args:', len(payload['args']))
"
python3 -c "import json; f = open('$PAYLOAD_FILE'); payload = json.load(f); print('Payload type:', payload.get('type', 'N/A')); print('Function:', payload.get('function', 'N/A')); args = payload.get('args'); print('Number of args:', len(args) if isinstance(args, list) else 'N/A')"

Copilot uses AI. Check for mistakes.
working-directory: examples/hello_blockchain
run: |
echo "=== Build artifacts ==="
find build -type f -name "*.mv" -o -name "*.json" 2>/dev/null || echo "No build directory"
Copy link

Copilot AI Jan 22, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The find command has incorrect syntax. The expression -name "*.mv" -o -name "*.json" should be grouped with parentheses when used with -type f to ensure correct precedence. Without parentheses, only files matching *.json will be checked for type f, while *.mv files will be listed regardless of type. Use \( -name "*.mv" -o -name "*.json" \) instead.

Suggested change
find build -type f -name "*.mv" -o -name "*.json" 2>/dev/null || echo "No build directory"
find build -type f \( -name "*.mv" -o -name "*.json" \) 2>/dev/null || echo "No build directory"

Copilot uses AI. Check for mistakes.
Comment on lines +48 to +58
#[test(account = @0x1)]
public entry fun sender_can_set_message(account: signer) acquires MessageHolder {
let addr = signer::address_of(&account);
aptos_framework::account::create_account_for_test(addr);
set_message(account, std::string::utf8(b"Hello, Blockchain"));

assert!(
get_message(addr) == std::string::utf8(b"Hello, Blockchain"),
ENO_MESSAGE
);
}
Copy link

Copilot AI Jan 22, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The test coverage for this module is incomplete. The test only covers the initial message creation scenario. Missing test cases include: (1) calling get_message on an address without a MessageHolder (should trigger ENO_MESSAGE error), (2) updating an existing message to verify the MessageChange event is emitted correctly, and (3) verifying the event fields are populated correctly when updating a message.

Copilot uses AI. Check for mistakes.
### Example: Building Publish Payload

```yaml
# In your GitHub Actions workflow
Copy link

Copilot AI Jan 22, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The documentation example is missing the Node.js setup and npm install steps that are required before running npx aptos --install. Users following this example would encounter errors if they don't have Node.js configured in their workflow. Consider adding a note that Node.js must be set up first, or include those prerequisite steps in the example.

Suggested change
# In your GitHub Actions workflow
# In your GitHub Actions workflow
- name: Set up Node.js
uses: actions/setup-node@v4
with:
node-version: '20'
- name: Install Aptos CLI npm package
run: npm install @aptos-labs/aptos-cli

Copilot uses AI. Check for mistakes.
cursoragent and others added 4 commits January 27, 2026 02:40
- Add example Move project (hello_blockchain) for testing artifact generation
- Add build-move-artifacts.yaml workflow demonstrating:
  - Building Move packages
  - Generating publish payloads (build-publish-payload)
  - Generating upgrade payloads (build-upgrade-payload) for object code deployment
  - Uploading and using artifacts in subsequent jobs
- Update README with CI/CD artifact building documentation

Co-authored-by: greg <[email protected]>
The previous path (../../node_modules/.bin/../../../dist/aptos.js) was invalid.
Use the installed CLI at ~/.local/bin/aptos directly instead.

Co-authored-by: greg <[email protected]>
- Verify hello_blockchain example has correct Move.toml structure
- Verify source files exist with proper module declarations
- Verify build-move-artifacts workflow has required configuration
- Verify workflow demonstrates artifact upload/download patterns
- Verify upgrade payload generation is documented

Co-authored-by: greg <[email protected]>
- Fix find command syntax with proper parentheses grouping
- Fix Python script indentation in payload validation step
- Add Node.js setup steps to README CI/CD examples
- Add comprehensive Move module tests:
  - Test for get_message with no message (expected failure)
  - Test for updating existing message with event emission

Co-authored-by: greg <[email protected]>
@cursor cursor bot force-pushed the cursor/aptos-cli-output-artifacts-17f1 branch from c131e01 to 1a71e4c Compare January 27, 2026 02:40
@gregnazario gregnazario requested a review from Copilot January 27, 2026 02:41
Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 4 out of 5 changed files in this pull request and generated 4 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines 119 to 122
# Check that the JSON is valid
python3 -c "import json; json.load(open('$PAYLOAD_FILE')); print('Valid JSON')"
# Check for expected fields
python3 -c "import json; f = open('$PAYLOAD_FILE'); payload = json.load(f); print('Payload type:', payload.get('type', 'N/A')); print('Function:', payload.get('function', 'N/A')); args = payload.get('args'); print('Number of args:', len(args) if isinstance(args, list) else 'N/A')"
Copy link

Copilot AI Jan 27, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The Python code opens files without using a context manager (with statement), which means the files are not explicitly closed. While Python's garbage collector will eventually close them, it's better practice to use 'with open() as f:' syntax to ensure files are properly closed. Consider refactoring to use context managers or at minimum call f.close() explicitly.

Suggested change
# Check that the JSON is valid
python3 -c "import json; json.load(open('$PAYLOAD_FILE')); print('Valid JSON')"
# Check for expected fields
python3 -c "import json; f = open('$PAYLOAD_FILE'); payload = json.load(f); print('Payload type:', payload.get('type', 'N/A')); print('Function:', payload.get('function', 'N/A')); args = payload.get('args'); print('Number of args:', len(args) if isinstance(args, list) else 'N/A')"
# Validate JSON and check for expected fields using a context manager
python3 - "$PAYLOAD_FILE" << 'EOF'
import json
import sys
if len(sys.argv) < 2:
raise SystemExit("Usage: python3 - <payload_file>")
payload_file = sys.argv[1]
with open(payload_file, "r", encoding="utf-8") as f:
payload = json.load(f)
print("Valid JSON")
print("Payload type:", payload.get("type", "N/A"))
print("Function:", payload.get("function", "N/A"))
args = payload.get("args")
print("Number of args:", len(args) if isinstance(args, list) else "N/A")
EOF

Copilot uses AI. Check for mistakes.
public entry fun test_update_message(account: signer) acquires MessageHolder {
let addr = signer::address_of(&account);
aptos_framework::account::create_account_for_test(addr);

Copy link

Copilot AI Jan 27, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This line contains trailing whitespace. Please remove the trailing whitespace to keep the code clean and consistent with common coding standards.

Suggested change

Copilot uses AI. Check for mistakes.
README.md Outdated
Comment on lines 165 to 168
- uses: actions/upload-artifact@v4
with:
name: move-artifacts
path: publish-payload.json
Copy link

Copilot AI Jan 27, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is an inconsistency in the artifact path specification. In the first example (line 139), the path includes the working directory prefix "your-move-project/publish-payload.json", but in the "Using Artifacts in Subsequent Jobs" example, the path is just "publish-payload.json" without the directory prefix. For consistency and clarity, both examples should follow the same pattern. Since the build steps use "working-directory", the artifact path in line 168 should also include "your-move-project/" prefix to match line 139, or both should consistently use just the filename if the working-directory context is maintained.

Copilot uses AI. Check for mistakes.
# Check that the JSON is valid
python3 -c "import json; json.load(open('$PAYLOAD_FILE')); print('Valid JSON')"
# Check for expected fields
python3 -c "import json; f = open('$PAYLOAD_FILE'); payload = json.load(f); print('Payload type:', payload.get('type', 'N/A')); print('Function:', payload.get('function', 'N/A')); args = payload.get('args'); print('Number of args:', len(args) if isinstance(args, list) else 'N/A')"
Copy link

Copilot AI Jan 27, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This Python one-liner is excessively long (approximately 220 characters) and difficult to read. Consider breaking it into multiple lines or using a multi-line Python script for better readability and maintainability. For example, you could use Python's triple-quoted multi-line string syntax or create a temporary Python script file.

Suggested change
python3 -c "import json; f = open('$PAYLOAD_FILE'); payload = json.load(f); print('Payload type:', payload.get('type', 'N/A')); print('Function:', payload.get('function', 'N/A')); args = payload.get('args'); print('Number of args:', len(args) if isinstance(args, list) else 'N/A')"
python3 - << PYCODE
import json
import os
payload_path = os.environ["PAYLOAD_FILE"]
with open(payload_path) as f:
payload = json.load(f)
print("Payload type:", payload.get("type", "N/A"))
print("Function:", payload.get("function", "N/A"))
args = payload.get("args")
print("Number of args:", len(args) if isinstance(args, list) else "N/A")
PYCODE

Copilot uses AI. Check for mistakes.
- Remove trailing whitespace in message.move test
- Fix artifact path inconsistency in README examples
- Improve Python validation script readability using heredoc with proper context manager

Co-authored-by: greg <[email protected]>
@gregnazario gregnazario merged commit 5ca4c43 into main Jan 27, 2026
12 checks passed
@gregnazario gregnazario deleted the cursor/aptos-cli-output-artifacts-17f1 branch January 27, 2026 23:33
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Add support for build-upgrade-payload

4 participants